diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 21:12:02 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 21:12:02 +0000 |
commit | 77e50caaf2ef81cd91075cf836fed0e75718ffb4 (patch) | |
tree | 53b7b411290b63192fc9e924a3b6b65cdf67e9d0 /debian/vendor-h2o/t/50reverse-proxy | |
parent | Adding upstream version 1.8.3. (diff) | |
download | dnsdist-77e50caaf2ef81cd91075cf836fed0e75718ffb4.tar.xz dnsdist-77e50caaf2ef81cd91075cf836fed0e75718ffb4.zip |
Adding debian version 1.8.3-2.debian/1.8.3-2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
27 files changed, 1063 insertions, 0 deletions
diff --git a/debian/vendor-h2o/t/50reverse-proxy-0.t b/debian/vendor-h2o/t/50reverse-proxy-0.t new file mode 100644 index 0000000..28e191f --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-0.t @@ -0,0 +1,4 @@ +$0 =~ /-([0-9]+)\.t$/s + or die "failed to extract mode"; +exec $^X, "t/50reverse-proxy/test.pl", "--mode=$1"; +die "failed to invoke $^X t/50reverse-proxy/test.pl:$!"; diff --git a/debian/vendor-h2o/t/50reverse-proxy-1.t b/debian/vendor-h2o/t/50reverse-proxy-1.t new file mode 100644 index 0000000..28e191f --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-1.t @@ -0,0 +1,4 @@ +$0 =~ /-([0-9]+)\.t$/s + or die "failed to extract mode"; +exec $^X, "t/50reverse-proxy/test.pl", "--mode=$1"; +die "failed to invoke $^X t/50reverse-proxy/test.pl:$!"; diff --git a/debian/vendor-h2o/t/50reverse-proxy-10.t b/debian/vendor-h2o/t/50reverse-proxy-10.t new file mode 100644 index 0000000..28e191f --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-10.t @@ -0,0 +1,4 @@ +$0 =~ /-([0-9]+)\.t$/s + or die "failed to extract mode"; +exec $^X, "t/50reverse-proxy/test.pl", "--mode=$1"; +die "failed to invoke $^X t/50reverse-proxy/test.pl:$!"; diff --git a/debian/vendor-h2o/t/50reverse-proxy-11.t b/debian/vendor-h2o/t/50reverse-proxy-11.t new file mode 100644 index 0000000..28e191f --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-11.t @@ -0,0 +1,4 @@ +$0 =~ /-([0-9]+)\.t$/s + or die "failed to extract mode"; +exec $^X, "t/50reverse-proxy/test.pl", "--mode=$1"; +die "failed to invoke $^X t/50reverse-proxy/test.pl:$!"; diff --git a/debian/vendor-h2o/t/50reverse-proxy-12.t b/debian/vendor-h2o/t/50reverse-proxy-12.t new file mode 100644 index 0000000..28e191f --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-12.t @@ -0,0 +1,4 @@ +$0 =~ /-([0-9]+)\.t$/s + or die "failed to extract mode"; +exec $^X, "t/50reverse-proxy/test.pl", "--mode=$1"; +die "failed to invoke $^X t/50reverse-proxy/test.pl:$!"; diff --git a/debian/vendor-h2o/t/50reverse-proxy-13.t b/debian/vendor-h2o/t/50reverse-proxy-13.t new file mode 100644 index 0000000..28e191f --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-13.t @@ -0,0 +1,4 @@ +$0 =~ /-([0-9]+)\.t$/s + or die "failed to extract mode"; +exec $^X, "t/50reverse-proxy/test.pl", "--mode=$1"; +die "failed to invoke $^X t/50reverse-proxy/test.pl:$!"; diff --git a/debian/vendor-h2o/t/50reverse-proxy-14.t b/debian/vendor-h2o/t/50reverse-proxy-14.t new file mode 100644 index 0000000..28e191f --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-14.t @@ -0,0 +1,4 @@ +$0 =~ /-([0-9]+)\.t$/s + or die "failed to extract mode"; +exec $^X, "t/50reverse-proxy/test.pl", "--mode=$1"; +die "failed to invoke $^X t/50reverse-proxy/test.pl:$!"; diff --git a/debian/vendor-h2o/t/50reverse-proxy-15.t b/debian/vendor-h2o/t/50reverse-proxy-15.t new file mode 100644 index 0000000..28e191f --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-15.t @@ -0,0 +1,4 @@ +$0 =~ /-([0-9]+)\.t$/s + or die "failed to extract mode"; +exec $^X, "t/50reverse-proxy/test.pl", "--mode=$1"; +die "failed to invoke $^X t/50reverse-proxy/test.pl:$!"; diff --git a/debian/vendor-h2o/t/50reverse-proxy-2.t b/debian/vendor-h2o/t/50reverse-proxy-2.t new file mode 100644 index 0000000..28e191f --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-2.t @@ -0,0 +1,4 @@ +$0 =~ /-([0-9]+)\.t$/s + or die "failed to extract mode"; +exec $^X, "t/50reverse-proxy/test.pl", "--mode=$1"; +die "failed to invoke $^X t/50reverse-proxy/test.pl:$!"; diff --git a/debian/vendor-h2o/t/50reverse-proxy-3.t b/debian/vendor-h2o/t/50reverse-proxy-3.t new file mode 100644 index 0000000..28e191f --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-3.t @@ -0,0 +1,4 @@ +$0 =~ /-([0-9]+)\.t$/s + or die "failed to extract mode"; +exec $^X, "t/50reverse-proxy/test.pl", "--mode=$1"; +die "failed to invoke $^X t/50reverse-proxy/test.pl:$!"; diff --git a/debian/vendor-h2o/t/50reverse-proxy-4.t b/debian/vendor-h2o/t/50reverse-proxy-4.t new file mode 100644 index 0000000..28e191f --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-4.t @@ -0,0 +1,4 @@ +$0 =~ /-([0-9]+)\.t$/s + or die "failed to extract mode"; +exec $^X, "t/50reverse-proxy/test.pl", "--mode=$1"; +die "failed to invoke $^X t/50reverse-proxy/test.pl:$!"; diff --git a/debian/vendor-h2o/t/50reverse-proxy-5.t b/debian/vendor-h2o/t/50reverse-proxy-5.t new file mode 100644 index 0000000..28e191f --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-5.t @@ -0,0 +1,4 @@ +$0 =~ /-([0-9]+)\.t$/s + or die "failed to extract mode"; +exec $^X, "t/50reverse-proxy/test.pl", "--mode=$1"; +die "failed to invoke $^X t/50reverse-proxy/test.pl:$!"; diff --git a/debian/vendor-h2o/t/50reverse-proxy-6.t b/debian/vendor-h2o/t/50reverse-proxy-6.t new file mode 100644 index 0000000..28e191f --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-6.t @@ -0,0 +1,4 @@ +$0 =~ /-([0-9]+)\.t$/s + or die "failed to extract mode"; +exec $^X, "t/50reverse-proxy/test.pl", "--mode=$1"; +die "failed to invoke $^X t/50reverse-proxy/test.pl:$!"; diff --git a/debian/vendor-h2o/t/50reverse-proxy-7.t b/debian/vendor-h2o/t/50reverse-proxy-7.t new file mode 100644 index 0000000..28e191f --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-7.t @@ -0,0 +1,4 @@ +$0 =~ /-([0-9]+)\.t$/s + or die "failed to extract mode"; +exec $^X, "t/50reverse-proxy/test.pl", "--mode=$1"; +die "failed to invoke $^X t/50reverse-proxy/test.pl:$!"; diff --git a/debian/vendor-h2o/t/50reverse-proxy-8.t b/debian/vendor-h2o/t/50reverse-proxy-8.t new file mode 100644 index 0000000..28e191f --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-8.t @@ -0,0 +1,4 @@ +$0 =~ /-([0-9]+)\.t$/s + or die "failed to extract mode"; +exec $^X, "t/50reverse-proxy/test.pl", "--mode=$1"; +die "failed to invoke $^X t/50reverse-proxy/test.pl:$!"; diff --git a/debian/vendor-h2o/t/50reverse-proxy-9.t b/debian/vendor-h2o/t/50reverse-proxy-9.t new file mode 100644 index 0000000..28e191f --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-9.t @@ -0,0 +1,4 @@ +$0 =~ /-([0-9]+)\.t$/s + or die "failed to extract mode"; +exec $^X, "t/50reverse-proxy/test.pl", "--mode=$1"; +die "failed to invoke $^X t/50reverse-proxy/test.pl:$!"; diff --git a/debian/vendor-h2o/t/50reverse-proxy-added-headers.t b/debian/vendor-h2o/t/50reverse-proxy-added-headers.t new file mode 100644 index 0000000..0e87a19 --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-added-headers.t @@ -0,0 +1,73 @@ +use strict; +use warnings; +use Net::EmptyPort qw(check_port empty_port); +use Test::More; +use t::Util; + +plan skip_all => 'curl not found' + unless prog_exists('curl'); +plan skip_all => 'plackup not found' + unless prog_exists('plackup'); +plan skip_all => 'Starlet not found' + unless system('perl -MStarlet /dev/null > /dev/null 2>&1') == 0; + +my $upstream_port = empty_port(); + +my $guard = spawn_server( + argv => [ qw(plackup -s Starlet --keepalive-timeout 100 --access-log /dev/null --listen), $upstream_port, ASSETS_DIR . "/upstream.psgi" ], + is_ready => sub { + check_port($upstream_port); + }, +); + +sub do_test { + my $emit_xff = shift; + my $emit_via = shift; + my $emit_xff_str = $emit_xff ? "ON" : "OFF"; + my $emit_via_str = $emit_via ? "ON" : "OFF"; + + my $server = spawn_h2o(<< "EOT"); +proxy.emit-x-forwarded-headers: $emit_xff_str +proxy.emit-via-header: $emit_via_str +hosts: + default: + paths: + /: + proxy.reverse.url: http://127.0.0.1.XIP.IO:$upstream_port +EOT + + run_with_curl($server, sub { + my ($proto, $port, $curl) = @_; + my $resp = `$curl --silent $proto://127.0.0.1:$port/echo-headers`; + if ($emit_xff) { + like $resp, qr/^x-forwarded-for: ?127\.0\.0\.1$/mi, "x-forwarded-for"; + like $resp, qr/^x-forwarded-proto: ?$proto$/mi, "x-forwarded-proto"; + } else { + unlike $resp, qr/^x-forwarded-for: ?127\.0\.0\.1$/mi, "x-forwarded-for not present"; + unlike $resp, qr/^x-forwarded-proto: ?$proto$/mi, "x-forwarded-proto not present"; + } + if ($emit_via) { + like $resp, qr/^via: ?[^ ]+ 127\.0\.0\.1:$port$/mi, "via"; + } else { + unlike $resp, qr/^via: ?[^ ]+ 127\.0\.0\.1:$port$/mi, "via"; + } + $resp = `$curl --silent --header 'X-Forwarded-For: 127.0.0.2' --header 'Via: 2 example.com' $proto://127.0.0.1:$port/echo-headers`; + if ($emit_xff) { + like $resp, qr/^x-forwarded-for: ?127\.0\.0\.2, 127\.0\.0\.1$/mi, "x-forwarded-for (append)"; + } else { + like $resp, qr/^x-forwarded-for: ?127\.0\.0\.2$/mi, "x-forwarded-for only contains the original header"; + } + if ($emit_via) { + like $resp, qr/^via: ?2 example.com, [^ ]+ 127\.0\.0\.1:$port$/mi, "via (append)"; + } else { + like $resp, qr/^via: 2 example.com$/mi, "via left as-is"; + } + }); +} + +do_test(0, 0); +do_test(0, 1); +do_test(1, 0); +do_test(1, 1); + +done_testing(); diff --git a/debian/vendor-h2o/t/50reverse-proxy-config.t b/debian/vendor-h2o/t/50reverse-proxy-config.t new file mode 100644 index 0000000..62b3466 --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-config.t @@ -0,0 +1,104 @@ +use strict; +use warnings; +use Digest::MD5 qw(md5_hex); +use Net::EmptyPort qw(check_port empty_port); +use Test::More; +use t::Util; + +plan skip_all => 'plackup not found' + unless prog_exists('plackup'); + +plan skip_all => 'Starlet not found' + unless system('perl -MStarlet /dev/null > /dev/null 2>&1') == 0; + +plan skip_all => 'curl not found' + unless prog_exists('curl'); + +# start upstream +my $upstream_port = empty_port(); +my $upstream = spawn_server( + argv => [ + qw(plackup -MPlack::App::File -s Starlet --access-log /dev/null -p), $upstream_port, + ASSETS_DIR . "/upstream.psgi", + ], + is_ready => sub { + check_port($upstream_port); + }, +); + +subtest 'preserve-host' => sub { + my $doit = sub { + my $flag = shift; + my $server = spawn_h2o(<< "EOT"); +hosts: + default: + paths: + /: + proxy.reverse.url: http://127.0.0.1:$upstream_port + proxy.preserve-host: @{[ $flag ? 'ON' : 'OFF' ]} +EOT + my $res = `curl --silent http://127.0.0.1:$server->{port}/echo-headers`; + like $res, qr/^host: 127.0.0.1:@{[ $flag ? $server->{port} : $upstream_port ]}$/im, 'host header'; + + $res = `curl --silent --dump-header /dev/stdout "http://127.0.0.1:$server->{port}/?resp:status=302&resp:location=http://127.0.0.1:$server->{port}/foo"`; + like $res, qr{^location: http://127\.0\.0\.1:$server->{port}/foo}im, 'location: :server_port'; + warn qq{curl --silent --dump-header /dev/stdout "http://127.0.0.1:$server->{port}/?resp:status=302&resp:location=http://127.0.0.1:$upstream_port/foo"}; + $res = `curl --silent --dump-header /dev/stdout "http://127.0.0.1:$server->{port}/?resp:status=302&resp:location=http://127.0.0.1:$upstream_port/foo"`; + like $res, qr{^location: http://127\.0\.0\.1:$server->{port}/foo}im, 'location :upstream_port'; + }; + + subtest 'ON' => sub { + $doit->(1); + }; + subtest 'OFF' => sub { + $doit->(0); + }; +}; + +subtest 'timeout.io' => sub { + my $server = spawn_h2o(<< "EOT"); +hosts: + default: + paths: + /: + proxy.reverse.url: http://127.0.0.1:$upstream_port + proxy.timeout.io: 2000 +EOT + my $fetch = sub { + my $sleep = shift; + `curl --silent --dump-header /dev/stderr http://127.0.0.1:$server->{port}/sleep-and-respond?sleep=$sleep 2>&1 > /dev/null`; + }; + my $resp = $fetch->(1); + like $resp, qr{^HTTP/1\.1 200 }s, "respond before timeout"; + $resp = $fetch->(3); + like $resp, qr{^HTTP/1\.1 502 }s, "respond after timeout"; +}; + +subtest 'infinite-internal-redirect' => sub { + my $server = spawn_h2o(<< "EOT"); +hosts: + default: + paths: + /: + proxy.reverse.url: http://127.0.0.1:$upstream_port +reproxy: ON +EOT + my $resp = `curl --silent --dump-header /dev/stderr "http://127.0.0.1:$server->{port}/?resp:x-reproxy-url=http://127.0.0.1:$upstream_port/infinite-redirect" 2>&1 > /dev/null`; + like $resp, qr{^HTTP/1\.1 502 }s; +}; + +subtest 'max-delegations' => sub { + my $server = spawn_h2o(<< "EOT"); +hosts: + default: + paths: + /: + proxy.reverse.url: http://127.0.0.1:$upstream_port +reproxy: ON +max-delegations: 0 +EOT + my $resp = `curl --silent --dump-header /dev/stderr "http://127.0.0.1:$server->{port}/?resp:x-reproxy-url=http://127.0.0.1:$upstream_port/index.txt" 2>&1 > /dev/null`; + like $resp, qr{^HTTP/1\.1 502 }s; +}; + +done_testing; diff --git a/debian/vendor-h2o/t/50reverse-proxy-disconnected-keepalive.t b/debian/vendor-h2o/t/50reverse-proxy-disconnected-keepalive.t new file mode 100644 index 0000000..4e35cba --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-disconnected-keepalive.t @@ -0,0 +1,77 @@ +use strict; +use warnings; +use File::Temp qw(tempfile); +use Net::EmptyPort qw(check_port empty_port); +use Test::More; +use t::Util; + +plan skip_all => 'curl not found' + unless prog_exists('curl'); +plan skip_all => 'Starlet not found' + unless system('perl -MStarlet /dev/null > /dev/null 2>&1') == 0; + +subtest "tcp" => sub { + my $port = empty_port(); + my $upstream = spawn_upstream($port); + doit("127.0.0.1:$port"); +}; + +subtest "unix-socket" => sub { + plan skip_all => 'skipping unix-socket tests, requires Starlet >= 0.25' + if `perl -MStarlet -e 'print \$Starlet::VERSION'` < 0.25; + + (undef, my $sockfn) = tempfile(UNLINK => 0); + unlink $sockfn; + my $guard = Scope::Guard->new(sub { + unlink $sockfn; + }); + + my $upstream = spawn_upstream($sockfn); + doit("[unix:$sockfn]"); +}; + +done_testing; + +sub doit { + my $upaddr = shift; + + my $server = spawn_h2o(<< "EOT"); +hosts: + default: + paths: + /: + proxy.reverse.url: http://$upaddr + proxy.timeout.io: 1000 + proxy.timeout.keepalive: 10000 +EOT + my $port = $server->{port}; + + my $check_req = sub { + my ($headers, $body) = run_prog("curl --silent --dump-header /dev/stderr http://127.0.0.1:$port/index.txt 2>&1"); + like $headers, qr{^HTTP/1\.1 200 }is; + is $body, "hello\n"; + }; + subtest "first-connect" => $check_req; + subtest "redo-immediate" => $check_req; + sleep 2; + subtest "redo-after-upstream-disconnect" => $check_req; + sleep 2; + subtest "once-more" => $check_req; +}; + +sub spawn_upstream { + my $addr = shift; + spawn_server( + argv => [ + qw(plackup -s Starlet --max-keepalive-reqs 100 --keepalive-timeout 1 --access-log /dev/null --listen), $addr, + ASSETS_DIR . "/upstream.psgi" + ], + is_ready => sub { + if ($addr =~ /^\d+$/) { + check_port($addr); + } else { + !! -e $addr; + } + }, + ); +} diff --git a/debian/vendor-h2o/t/50reverse-proxy-drop-headers.t b/debian/vendor-h2o/t/50reverse-proxy-drop-headers.t new file mode 100644 index 0000000..0ae1e61 --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-drop-headers.t @@ -0,0 +1,57 @@ +use strict; +use warnings; +use Net::EmptyPort qw(check_port empty_port); +use Test::More; +use t::Util; + +plan skip_all => 'curl not found' + unless prog_exists('curl'); +plan skip_all => 'plackup not found' + unless prog_exists('plackup'); +plan skip_all => 'Starlet not found' + unless system('perl -MStarlet /dev/null > /dev/null 2>&1') == 0; + +my $upstream_port = empty_port(); + +my $guard = spawn_server( + argv => [ qw(plackup -s Starlet --keepalive-timeout 100 --access-log /dev/null --listen), "127.0.0.1:$upstream_port", ASSETS_DIR . "/upstream.psgi" ], + is_ready => sub { + check_port($upstream_port); + }, +); + +subtest 'request-header' => sub { +# proxy-authenticate + + my $server = spawn_h2o(<< "EOT"); +hosts: + default: + paths: + /: + proxy.reverse.url: http://127.0.0.1.XIP.IO:$upstream_port +EOT + + my $curl = 'curl --silent --dump-header /dev/stderr'; + my ($headers, $body) = run_prog("$curl" + . " -H 'Proxy-Authenticate: hoge'" + . " -H 'Date: Thu, 01 Jan 1970 00:00:00 GMT'" + . " http://127.0.0.1:@{[$server->{port}]}/echo-headers"); + unlike $body, qr/^proxy-authenticate:/mi, 'proxy-authenticate header should be dropped'; + like $body, qr/^date:/mi, 'date request header is not dropped'; +}; + +subtest 'response header' => sub { + my $server = spawn_h2o(<< "EOT"); +hosts: + default: + paths: + /: + proxy.reverse.url: http://127.0.0.1.XIP.IO:$upstream_port +EOT + + my $curl = 'curl --silent --dump-header /dev/stderr'; + my ($headers, $body) = run_prog("$curl http://127.0.0.1:@{[$server->{port}]}/fixed-date-header"); + unlike $headers, qr/Thu, 01 Jan 1970 00:00:00 GMT/, "date response header from upstream should be dropped and replaced"; +}; + +done_testing(); diff --git a/debian/vendor-h2o/t/50reverse-proxy-https.t b/debian/vendor-h2o/t/50reverse-proxy-https.t new file mode 100644 index 0000000..1bb499f --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-https.t @@ -0,0 +1,70 @@ +use strict; +use warnings; +use Net::EmptyPort qw(check_port empty_port); +use Test::More; +use t::Util; + +plan skip_all => 'plackup not found' + unless prog_exists('plackup'); + +my $upstream_port = empty_port(); +my $upstream = spawn_server( + argv => [ + qw( + plackup -s Standalone --ssl=1 --ssl-key-file=examples/h2o/server.key --ssl-cert-file=examples/h2o/server.crt --port + ), + $upstream_port, ASSETS_DIR . "/upstream.psgi" + ], + is_ready => sub { + check_port($upstream_port); + }, +); + +subtest "reverse-proxy" => sub { + my $server = spawn_h2o(<< "EOT"); +hosts: + default: + paths: + "/verify": + proxy.reverse.url: https://127.0.0.1:$upstream_port + "/no-verify": + proxy.reverse.url: https://127.0.0.1:$upstream_port + proxy.ssl.verify-peer: OFF + "/wikipedia": + proxy.reverse.url: https://en.wikipedia.org/wiki/Main_Page +EOT + run_with_curl($server, sub { + my ($proto, $port, $curl) = @_; + my $resp = `$curl --silent --dump-header /dev/stderr --max-redirs 0 $proto://127.0.0.1:$port/verify/ 2>&1 > /dev/null`; + like $resp, qr{^HTTP/[^ ]* 502\s}is; + $resp = `$curl --silent --dump-header /dev/stderr --max-redirs 0 $proto://127.0.0.1:$port/no-verify/ 2>&1 > /dev/null`; + unlike $resp, qr{^HTTP/[^ ]* 502\s}is; + $resp = `$curl --silent --dump-header /dev/stderr --max-redirs 0 $proto://127.0.0.1:$port/wikipedia/ 2>&1 > /dev/null`; + like $resp, qr{^HTTP/[^ ]* 200\s}is; + }); +}; + +subtest "reproxy" => sub { + plan skip_all => "mruby support is off" + unless server_features()->{mruby}; + my $server = spawn_h2o(<< "EOT"); +proxy.ssl.verify-peer: OFF +hosts: + default: + paths: + "/": + reproxy: ON + mruby.handler: | + Proc.new do |env| + [200, {"x-reproxy-url" => "https://127.0.0.1:$upstream_port/index.txt"}, ["should never see this"]] + end +EOT + run_with_curl($server, sub { + my ($proto, $port, $curl) = @_; + my $resp = `$curl --silent --dump-header /dev/stdout --max-redirs 0 $proto://127.0.0.1:$port/`; + like $resp, qr{^HTTP/[^ ]* 200}im; + like $resp, qr{^hello$}m; + }); +}; + +done_testing(); diff --git a/debian/vendor-h2o/t/50reverse-proxy-preserve-case.t b/debian/vendor-h2o/t/50reverse-proxy-preserve-case.t new file mode 100644 index 0000000..da2aee2 --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-preserve-case.t @@ -0,0 +1,68 @@ +use strict; +use warnings; +use Net::EmptyPort qw(check_port empty_port); +use Test::More; +use t::Util; + +plan skip_all => 'curl not found' + unless prog_exists('curl'); +plan skip_all => 'plackup not found' + unless prog_exists('plackup'); +plan skip_all => 'Starlet not found' + unless system('perl -MStarlet /dev/null > /dev/null 2>&1') == 0; + +my $upstream_port = empty_port(); + +my $upstream = new IO::Socket::INET ( + LocalHost => '127.0.0.1', + LocalPort => $upstream_port, + Proto => 'tcp', + Listen => 1, + Reuse => 1 +); +die "cannot create socket $!\n" unless $upstream; + +sub handler_curl { + my $socket = shift; + my $client_socket = $socket->accept(); + + my $data = ""; + $client_socket->recv($data, 4906); + + my $resp = "HTTP/1.0 200 Ok\r\nMyResponseHeader:1\r\nContent-Length:2\r\nConnection: close\r\n\r\nOk"; + $client_socket->send($resp); + $client_socket->flush; + + close($client_socket); + return $data; +}; + + +my $server = spawn_h2o(<< "EOT"); +hosts: + default: + paths: + /: + proxy.reverse.url: http://127.0.0.1:$upstream_port +EOT + +run_with_curl($server, sub { + my ($proto, $port, $curl) = @_; + open(CURL, "$curl -HUpper-Case:TheValue -kv $proto://127.0.0.1:$port/ 2>&1 |"); + my $forwarded = handler_curl($upstream); + my @lines; + while (<CURL>) { + push(@lines, $_); + + } + my $resp = join("", @lines); + if ($curl =~ /http2/) { + like($forwarded, qr{upper-case:\s*TheValue}, "Request header name is lowercased"); + like($resp, qr{myresponseheader:\s*1}, "Response header name is lowercase"); + } else { + like($forwarded, qr{Upper-Case:\s*TheValue}, "Request header name is not lowercased"); + like($resp, qr{MyResponseHeader:\s*1}, "Response header name has case preserved"); + } + }); + +done_testing(); diff --git a/debian/vendor-h2o/t/50reverse-proxy-proxy-protocol.t b/debian/vendor-h2o/t/50reverse-proxy-proxy-protocol.t new file mode 100644 index 0000000..0bb1a82 --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-proxy-protocol.t @@ -0,0 +1,55 @@ +use strict; +use warnings; +use IO::Socket::INET; +use Test::TCP; +use Net::EmptyPort qw(check_port empty_port); +use Test::More; +use Scope::Guard qw(guard); +use t::Util; + +my $upstream_port = empty_port(); + +my $listen = IO::Socket::INET->new( + LocalAddr => '127.0.0.1', + LocalPort => $upstream_port, + Listen => 5, +) or die "failed to listen to 127.0.0.1:$upstream_port:$!"; + +my $upstream_guard = do { + my $pid = fork; + die "fork failed:$!" + unless defined $pid; + if ($pid == 0) { + # server process + while (1) { + if (my $conn = $listen->accept) { + sysread $conn, my $buf, 4096; +print STDERR "**** $buf"; + syswrite $conn, "HTTP/1.1 200 OK\r\nconnection: close\r\n\r\n$buf"; +print STDERR "**** yeoh"; + $conn->close; + } + } + } + guard { + kill 'TERM', $pid; + }; +}; + +my $server = spawn_h2o(<< "EOT"); +hosts: + default: + paths: + "/": + proxy.reverse.url: http://127.0.0.1:$upstream_port/ + proxy.proxy-protocol: ON + proxy.timeout.keepalive: 0 +EOT + +run_with_curl($server, sub { + my ($proto, $port, $curl_cmd) = @_; + my $resp = `$curl_cmd --silent $proto://127.0.0.1:$port/hello`; + like $resp, qr{^PROXY TCP4 127\.0\.0\.1 127\.0\.0\.1 [0-9]{1,5} $port\r\nGET /hello HTTP/1\.}is; +}); + +done_testing; diff --git a/debian/vendor-h2o/t/50reverse-proxy-session-resumption.t b/debian/vendor-h2o/t/50reverse-proxy-session-resumption.t new file mode 100644 index 0000000..acf6a78 --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-session-resumption.t @@ -0,0 +1,210 @@ +use strict; +use warnings; +use File::Temp qw(tempdir); +use Net::EmptyPort qw(check_port empty_port); +use Test::Builder; +use Test::More; +use t::Util; + +plan skip_all => 'curl not found' + unless prog_exists('curl'); +plan skip_all => 'Starlet not found' + unless system('perl -MStarlet /dev/null > /dev/null 2>&1') == 0; + +my $tempdir = tempdir(CLEANUP => 1); + +sub create_upstream { + unlink "$tempdir/access_log"; + return spawn_h2o(<< "EOT"); +hosts: + default: + paths: + /: + file.dir: @{[ DOC_ROOT ]} + access-log: + path: $tempdir/access_log + format: "%{ssl.session-reused}x" +EOT +} + +sub doit { + my ($conf, $scenario, $opts) = @_; + local $Test::Builder::Level = $Test::Builder::Level + 1; + $opts ||= +{}; + + my $upstream = $opts->{upstream} || create_upstream(); + if (ref($conf) eq 'CODE') { + $conf = $conf->($upstream); + } + my $server = spawn_h2o($conf); + my $port = $server->{port}; + + for my $s (@$scenario) { + my $path = $s->{path} || '/'; + Time::HiRes::sleep($s->{interval}) if $s->{interval}; + my $res = `curl --silent --dump-header /dev/stderr http://127.0.0.1:@{[$server->{port}]}$path 2>&1 > /dev/null`; + like $res, qr{^HTTP/1\.1 200 }, $s->{desc}; + } + + my @log = do { + open my $fh, "<", "$tempdir/access_log" + or die "failed to open access_log:$!"; + map { my $l = $_; chomp $l; $l } <$fh>; + }; + + for my $i (0..scalar(@$scenario)-1) { + my $s = $scenario->[$i]; + next unless defined($s->{expected}); + + my $reused = $log[$i] + 0; + is($reused, $s->{expected}, $s->{desc}); + } +}; + +subtest 'default' => sub { + doit(sub { + my ($upstream) = @_; + return <<"EOC"; +proxy.ssl.verify-peer: OFF +proxy.timeout.keepalive: 0 +hosts: + default: + paths: + /: + proxy.reverse.url: https://127.0.0.1:@{[$upstream->{tls_port}]} +EOC + }, [ + +{}, + +{ expected => 1 }, + ]); +}; + +subtest 'off' => sub { + doit(sub { + my ($upstream) = @_; + return <<"EOC"; +proxy.timeout.keepalive: 0 +proxy.ssl.session-cache: OFF +hosts: + default: + paths: + /: + proxy.ssl.verify-peer: OFF + proxy.reverse.url: https://127.0.0.1:@{[$upstream->{tls_port}]} +EOC + }, [ + +{}, + +{ expected => 0 }, + ]); +}; + +subtest 'lifetime' => sub { + doit(sub { + my ($upstream) = @_; + return <<"EOC"; +proxy.ssl.verify-peer: OFF +proxy.timeout.keepalive: 0 +hosts: + default: + paths: + /: + proxy.reverse.url: https://127.0.0.1:@{[$upstream->{tls_port}]} + proxy.ssl.session-cache: + capacity: 4096 + lifetime: 2 +EOC + }, [ + +{}, + +{ interval => 1, expected => 1 }, + +{ interval => 2, expected => 0, desc => 'expire' }, + ]); +}; + +subtest 'config' => sub { + doit(sub { + my ($upstream) = @_; + return <<"EOC"; +proxy.ssl.verify-peer: OFF +proxy.timeout.keepalive: 0 +hosts: + default: + proxy.ssl.session-cache: OFF + paths: + /: + proxy.reverse.url: https://127.0.0.1:@{[$upstream->{tls_port}]} + proxy.ssl.session-cache: ON + /sample.txt: + proxy.reverse.url: https://127.0.0.1:@{[$upstream->{tls_port}]} + proxy.ssl.session-cache: + capacity: 4096 + lifetime: 2 + +EOC + }, [ + +{ path => '/' }, + +{ path => '/', interval => 0, expected => 1, desc => 'reuse on second request to /' }, + +{ path => '/sample.txt', interval => 0, expected => 0, desc => 'not reuse on first request to /sample.txt' }, + +{ path => '/sample.txt', interval => 1, expected => 1, desc => 'reuse on second request to /sample.txt' }, + +{ path => '/sample.txt', interval => 2, expected => 0, desc => 'expire on third request to /sample.txt' }, + ]); +}; + +subtest 'reproxy' => sub { + my $upstream = create_upstream(); + my $upstream_port = $upstream->{tls_port}; + my $app_port = empty_port(); + my $app_server = spawn_server( + argv => [ + qw( + plackup -s Starlet --max-workers=1 --port + ), + $app_port, "-e sub { [200, ['X-Reproxy-URL' => 'https://127.0.0.1:$upstream_port/'], []] }" + ], + is_ready => sub { + check_port($app_port); + }, + ); + + doit(sub { + return <<"EOC"; +proxy.ssl.verify-peer: OFF +proxy.timeout.keepalive: 0 +hosts: + default: + paths: + /: + proxy.reverse.url: http://127.0.0.1:$app_port + reproxy: ON +EOC + }, [ + +{}, + +{ expected => 1 }, + ], +{ upstream => $upstream }); +}; + +subtest 'multiple-hosts' => sub { + doit(sub { + my ($upstream) = @_; + return <<"EOC"; +proxy.ssl.verify-peer: OFF +proxy.timeout.keepalive: 0 +proxy.ssl.session-cache: ON +hosts: + default: + paths: + /: + proxy.reverse.url: https://127.0.0.1:@{[$upstream->{tls_port}]} + example.com: + paths: + /: + proxy.reverse.url: https://127.0.0.1:@{[$upstream->{tls_port}]} + proxy.ssl.verify-peer: ON + proxy.ssl.session-cache: OFF +EOC + }, [ + +{}, + +{ expected => 1 }, + ]); +}; + +done_testing(); diff --git a/debian/vendor-h2o/t/50reverse-proxy-upstream-down.t b/debian/vendor-h2o/t/50reverse-proxy-upstream-down.t new file mode 100644 index 0000000..3f30a44 --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy-upstream-down.t @@ -0,0 +1,35 @@ +use strict; +use warnings; +use Net::EmptyPort qw(check_port empty_port); +use Test::More; +use t::Util; + +plan skip_all => 'curl not found' + unless prog_exists('curl'); + +sub doit { + my $persistent = shift; + my $upstream_port = empty_port(); + my $server = spawn_h2o(<< "EOT"); +hosts: + default: + paths: + /: + proxy.reverse.url: http://127.0.0.1:$upstream_port + proxy.timeout.io: 2000 +@{[ $persistent ? "" : "proxy.timeout.keepalive: 0" ]} +EOT + my $port = $server->{port}; + my $res = `curl --max-time 5 --silent --dump-header /dev/stderr http://127.0.0.1:$port/ 2>&1 > /dev/null`; + like $res, qr{^HTTP/1\.1 502 }, "502 response on upstream error"; +}; + +subtest 'non-persistent' => sub { + doit(0); +}; + +subtest 'persistent' => sub { + doit(1); +}; + +done_testing(); diff --git a/debian/vendor-h2o/t/50reverse-proxy/hello.txt b/debian/vendor-h2o/t/50reverse-proxy/hello.txt new file mode 100644 index 0000000..ce01362 --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy/hello.txt @@ -0,0 +1 @@ +hello diff --git a/debian/vendor-h2o/t/50reverse-proxy/test.pl b/debian/vendor-h2o/t/50reverse-proxy/test.pl new file mode 100755 index 0000000..3781cba --- /dev/null +++ b/debian/vendor-h2o/t/50reverse-proxy/test.pl @@ -0,0 +1,249 @@ +use strict; +use warnings; +use Digest::MD5 qw(md5_hex); +use File::Temp qw(tempfile); +use Getopt::Long; +use Net::EmptyPort qw(check_port empty_port); +use Test::More; +use URI::Escape; +use t::Util; + +my ($aggregated_mode, $h2o_keepalive, $starlet_keepalive, $starlet_force_chunked, $unix_socket); + +GetOptions( + "mode=i" => sub { + (undef, my $m) = @_; + $h2o_keepalive = ($m & 1) != 0; + $starlet_keepalive = ($m & 2) != 0; + $starlet_force_chunked = ($m & 4) != 0; + $unix_socket = ($m & 8) != 0; + }, + "h2o-keepalive=i" => \$h2o_keepalive, + "starlet-keepalive=i" => \$starlet_keepalive, + "starlet-force-chunked=i" => \$starlet_force_chunked, + "unix-socket=i" => \$unix_socket, +) or exit(1); + +plan skip_all => 'plackup not found' + unless prog_exists('plackup'); + +plan skip_all => 'Starlet not found' + unless system('perl -MStarlet /dev/null > /dev/null 2>&1') == 0; +plan skip_all => 'skipping unix-socket tests, requires Starlet >= 0.25' + if $unix_socket && `perl -MStarlet -e 'print \$Starlet::VERSION'` < 0.25; + +my %files = map { do { + my $fn = DOC_ROOT . "/$_"; + +($_ => { size => (stat $fn)[7], md5 => md5_file($fn) }); +} } qw(index.txt halfdome.jpg); + +my $huge_file_size = 50 * 1024 * 1024; # should be larger than the mmap_backend threshold of h2o +my $huge_file = create_data_file($huge_file_size); +my $huge_file_md5 = md5_file($huge_file); + +my ($unix_socket_file, $unix_socket_guard) = do { + (undef, my $fn) = tempfile(UNLINK => 0); + unlink $fn; + +( + $fn, + Scope::Guard->new(sub { + unlink $fn; + }), + ); +} if $unix_socket; + +my $upstream = $unix_socket_file ? "[unix:$unix_socket_file]" : "127.0.0.1:@{[empty_port()]}"; + +my $guard = do { + local $ENV{FORCE_CHUNKED} = $starlet_force_chunked; + my @args = (qw(plackup -s Starlet --keepalive-timeout 100 --access-log /dev/null --listen), $unix_socket_file || $upstream); + if ($starlet_keepalive) { + push @args, "--max-keepalive-reqs=100"; + } + push @args, ASSETS_DIR . "/upstream.psgi"; + spawn_server( + argv => \@args, + is_ready => sub { + if ($unix_socket_file) { + !! -e $unix_socket_file; + } else { + $upstream =~ /:([0-9]+)$/s + or die "failed to extract port number"; + check_port($1); + } + }, + ); +}; + +my $server = spawn_h2o(<< "EOT"); +hosts: + default: + paths: + /: + proxy.reverse.url: http://$upstream + /gzip: + proxy.reverse.url: http://$upstream + gzip: ON + /files: + file.dir: @{[ DOC_ROOT ]} +@{[ $h2o_keepalive ? "" : " proxy.timeout.keepalive: 0" ]} +reproxy: ON +EOT + +run_with_curl($server, sub { + my ($proto, $port, $curl) = @_; + for my $file (sort keys %files) { + my $content = `$curl --silent --show-error $proto://127.0.0.1:$port/$file`; + is length($content), $files{$file}->{size}, "$proto://127.0.0.1/$file (size)"; + is md5_hex($content), $files{$file}->{md5}, "$proto://127.0.0.1/$file (md5)"; + } + for my $file (sort keys %files) { + my $content = `$curl --silent --show-error --data-binary \@@{[ DOC_ROOT ]}/$file $proto://127.0.0.1:$port/echo`; + is length($content), $files{$file}->{size}, "$proto://127.0.0.1/echo (POST, $file, size)"; + is md5_hex($content), $files{$file}->{md5}, "$proto://127.0.0.1/echo (POST, $file, md5)"; + } + if ($curl !~ /--http2/) { + for my $file (sort keys %files) { + my $content = `$curl --silent --show-error --header 'Transfer-Encoding: chunked' --data-binary \@@{[ DOC_ROOT ]}/$file $proto://127.0.0.1:$port/echo`; + is length($content), $files{$file}->{size}, "$proto://127.0.0.1/echo (POST, chunked, $file, size)"; + is md5_hex($content), $files{$file}->{md5}, "$proto://127.0.0.1/echo (POST, chunked, $file, md5)"; + } + } + my $content = `$curl --silent --show-error --data-binary \@$huge_file $proto://127.0.0.1:$port/echo`; + is length($content), $huge_file_size, "$proto://127.0.0.1/echo (POST, mmap-backed, size)"; + is md5_hex($content), $huge_file_md5, "$proto://127.0.0.1/echo (POST, mmap-backed, md5)"; + if ($curl !~ /--http2/) { + $content = `$curl --silent --show-error --header 'Transfer-Encoding: chunked' --data-binary \@$huge_file $proto://127.0.0.1:$port/echo`; + is length($content), $huge_file_size, "$proto://127.0.0.1/echo (POST, chunked, mmap-backed, size)"; + is md5_hex($content), $huge_file_md5, "$proto://127.0.0.1/echo (POST, chunked, mmap-backed, md5)"; + } + subtest 'rewrite-redirect' => sub { + $content = `$curl --silent --dump-header /dev/stdout --max-redirs 0 "$proto://127.0.0.1:$port/?resp:status=302&resp:location=http://@{[uri_escape($upstream)]}/abc"`; + like $content, qr{HTTP/[^ ]+ 302\s}m; + like $content, qr{^location: ?$proto://127.0.0.1:$port/abc\r$}m; + }; + subtest "x-reproxy-url ($proto)" => sub { + my $fetch_test = sub { + my $url_prefix = shift; + for my $file (sort keys %files) { + my $content = `$curl --silent --show-error "$proto://127.0.0.1:$port/404?resp:status=200&resp:x-reproxy-url=$url_prefix$file"`; + is length($content), $files{$file}->{size}, "$file (size)"; + is md5_hex($content), $files{$file}->{md5}, "$file (md5)"; + } + }; + subtest "abs-url" => sub { + $fetch_test->("http://@{[uri_escape($upstream)]}/"); + }; + subtest "abs-path" => sub { + $fetch_test->("/"); + }; + subtest "rel-path" => sub { + $fetch_test->(""); + }; + my $content = `$curl --silent --show-error "$proto://127.0.0.1:$port/streaming-body?resp:status=200&resp:x-reproxy-url=http://@{[uri_escape($upstream)]}/index.txt"`; + is $content, "hello\n", "streaming-body"; + $content = `$curl --silent "$proto://127.0.0.1:$port/?resp:status=200&resp:x-reproxy-url=https://default/files/index.txt"`; + is length($content), $files{"index.txt"}->{size}, "to file handler (size)"; + is md5_hex($content), $files{"index.txt"}->{md5}, "to file handler (md5)"; + $content = `$curl --silent "$proto://127.0.0.1:$port/?resp:status=200&resp:x-reproxy-url=http://@{[uri_escape($upstream)]}/?resp:status=302%26resp:location=index.txt"`; + is length($content), $files{"index.txt"}->{size}, "reproxy & internal redirect to upstream (size)"; + is md5_hex($content), $files{"index.txt"}->{md5}, "reproxy & internal redirect to upstream (md5)"; + $content = `$curl --silent "$proto://127.0.0.1:$port/?resp:status=200&resp:x-reproxy-url=http://@{[uri_escape($upstream)]}/?resp:status=302%26resp:location=https://default/files/index.txt"`; + is length($content), $files{"index.txt"}->{size}, "reproxy & internal redirect to file (size)"; + is md5_hex($content), $files{"index.txt"}->{md5}, "reproxy & internal redirect to file (md5)"; + $content = `$curl --silent "$proto://127.0.0.1:$port/?resp:status=200&resp:x-reproxy-url=http://default/files"`; + is length($content), $files{"index.txt"}->{size}, "redirect handled internally after delegation (size)"; + is md5_hex($content), $files{"index.txt"}->{md5}, "redirect handled internally after delegation (md5)"; + }; + subtest "x-forwarded ($proto)" => sub { + my $resp = `$curl --silent $proto://127.0.0.1:$port/echo-headers`; + like $resp, qr/^x-forwarded-for: ?127\.0\.0\.1$/mi, "x-forwarded-for"; + like $resp, qr/^x-forwarded-proto: ?$proto$/mi, "x-forwarded-proto"; + like $resp, qr/^via: ?[^ ]+ 127\.0\.0\.1:$port$/mi, "via"; + $resp = `$curl --silent --header 'X-Forwarded-For: 127.0.0.2' --header 'Via: 2 example.com' $proto://127.0.0.1:$port/echo-headers`; + like $resp, qr/^x-forwarded-for: ?127\.0\.0\.2, 127\.0\.0\.1$/mi, "x-forwarded-for (append)"; + like $resp, qr/^via: ?2 example.com, [^ ]+ 127\.0\.0\.1:$port$/mi, "via (append)"; + }; + subtest 'issues/266' => sub { + my $resp = `$curl --dump-header /dev/stderr --silent -H 'cookie: a=@{['x' x 4000]}' $proto://127.0.0.1:$port/index.txt 2>&1 > /dev/null`; + like $resp, qr{^HTTP/[^ ]+ 200\s}m; + }; + subtest 'gzip' => sub { + plan skip_all => 'curl issue #661' + if $curl =~ /--http2/; + my $resp = `$curl --silent -H Accept-Encoding:gzip $proto://127.0.0.1:$port/gzip/alice.txt | gzip -cd`; + is md5_hex($resp), md5_file("@{[DOC_ROOT]}/alice.txt"); + }; +}); + +subtest 'nghttp' => sub { + plan skip_all => 'nghttp not found' + unless prog_exists('nghttp'); + my $doit = sub { + my ($proto, $opt, $port) = @_; + for my $file (sort keys %files) { + my $content = `nghttp $opt $proto://127.0.0.1:$port/$file`; + is length($content), $files{$file}->{size}, "$proto://127.0.0.1/$file (size)"; + is md5_hex($content), $files{$file}->{md5}, "$proto://127.0.0.1/$file (md5)"; + } + my $out = `nghttp $opt -d t/50reverse-proxy/hello.txt $proto://127.0.0.1:$port/echo`; + is $out, "hello\n", "$proto://127.0.0.1/echo (POST)"; + $out = `nghttp $opt -m 10 $proto://127.0.0.1:$port/index.txt`; + is $out, "hello\n" x 10, "$proto://127.0.0.1/index.txt x 10 times"; + $out = `nghttp $opt -d $huge_file $proto://127.0.0.1:$port/echo`; + is length($out), $huge_file_size, "$proto://127.0.0.1/echo (mmap-backed, size)"; + is md5_hex($out), $huge_file_md5, "$proto://127.0.0.1/echo (mmap-backed, md5)"; + subtest 'cookies' => sub { + plan skip_all => 'nghttp issues #161' + if $opt eq '-u'; + $out = `nghttp $opt -H 'cookie: a=b' -H 'cookie: c=d' $proto://127.0.0.1:$port/echo-headers`; + like $out, qr{^cookie: a=b; c=d$}m; + }; + subtest "x-reproxy-url ($proto)" => sub { + for my $file (sort keys %files) { + my $content = `nghttp $opt "$proto://127.0.0.1:$port/404?resp:status=200&resp:x-reproxy-url=http://@{[uri_escape($upstream)]}/$file"`; + is length($content), $files{$file}->{size}, "$file (size)"; + is md5_hex($content), $files{$file}->{md5}, "$file (md5)"; + } + my $content = `nghttp $opt "$proto://127.0.0.1:$port/streaming-body?resp:status=200&resp:x-reproxy-url=http://@{[uri_escape($upstream)]}/index.txt"`; + is $content, "hello\n", "streaming-body"; + $content = `nghttp $opt "$proto://127.0.0.1:$port/?resp:status=200&resp:x-reproxy-url=https://default/files/index.txt"`; + is length($content), $files{"index.txt"}->{size}, "to file handler (size)"; + is md5_hex($content), $files{"index.txt"}->{md5}, "to file handler (md5)"; + $content = `nghttp $opt "$proto://127.0.0.1:$port/?resp:status=200&resp:x-reproxy-url=http://@{[uri_escape($upstream)]}/?resp:status=302%26resp:location=index.txt"`; + is length($content), $files{"index.txt"}->{size}, "reproxy & internal redirect to upstream (size)"; + is md5_hex($content), $files{"index.txt"}->{md5}, "reproxy & internal redirect to upstream (md5)"; + $content = `nghttp $opt "$proto://127.0.0.1:$port/?resp:status=200&resp:x-reproxy-url=http://@{[uri_escape($upstream)]}/?resp:status=302%26resp:location=https://default/files/index.txt"`; + is length($content), $files{"index.txt"}->{size}, "reproxy & internal redirect to file (size)"; + is md5_hex($content), $files{"index.txt"}->{md5}, "reproxy & internal redirect to file (md5)"; + $content = `nghttp -v $opt "$proto://127.0.0.1:$port/?resp:status=200&resp:x-reproxy-url=http://default/files"`; + unlike $content, qr/ :status: 3/, "once delegated, redirects of the file handler should be handled internally"; + }; + subtest 'issues/185' => sub { + my $out = `nghttp $opt -v "$proto://127.0.0.1:$port/?resp:access-control-allow-origin=%2a"`; + is $?, 0; + like $out, qr/ access-control-allow-origin: \*$/m; + }; + subtest 'issues/192' => sub { + my $cookie = '_yohoushi_session=ZU5tK2FhcllVQ1RGaTZmZE9MUXozZnAzdTdmR250ZjRFU1hNSnZ4Y2JxZm9pYzJJSEpISGFKNmtWcW1HcjBySmUxZzIwNngrdlVIOC9jdmg0R3I3TFR4eVYzaHlFSHdEL1M4dnh1SmRCbVl3ZE5FckZEU1NyRmZveWZwTmVjcVV5V1JhNUd5REIvWjAwQ3RiT1ZBNGVMUkhiN0tWR0c1RzZkSVhrVkdoeW1lWXRDeHJPUW52NUwxSytRTEQrWXdoZ1EvVG9kak9aeUxnUFRNTDB4Vis1RDNUYWVHZm12bDgwL1lTa09MTlJYcGpXN2VUWmdHQ2FuMnVEVDd4c3l1TTJPMXF1dGhYcGRHS2U2bW9UaG0yZGIwQ0ZWVzFsY1hNTkY5cVFvWjNqSWNrQ0pOY1gvMys4UmRHdXJLU1A0ZTZQc3pSK1dKcXlpTEF2djJHLzUwbytwSnVpS0xhdFp6NU9kTDhtcmgxamVXMkI0Nm9Nck1rMStLUmV0TEdUeGFSTjlKSzM0STc3NTlSZ05ZVjJhWUNibkdzY1I1NUg4bG96dWZSeGorYzF4M2tzMGhKSkxmeFBTNkpZS09HTFgrREN4SWd4a29kamRxT3FobDRQZ2xMVUE9PS0tQUxSWU5nWmVTVzRoN09sS3pmUVM3dz09--3a411c0cf59845f0b8ccf61f69b8eb87aa1727ac; path=/; HttpOnly'; + my $cookie_encoded = $cookie; + $cookie_encoded =~ s{([^A-Za-z0-9_])}{sprintf "%%%02x", ord $1}eg; + $out = `nghttp $opt -v $proto://127.0.0.1:$port/?resp:set-cookie=$cookie_encoded`; + is $?, 0; + like $out, qr/ set-cookie: $cookie$/m; + }; + }; + subtest 'http (upgrade)' => sub { + $doit->('http', '-u', $server->{port}); + }; + subtest 'http (direct)' => sub { + $doit->('http', '', $server->{port}); + }; + subtest 'https' => sub { + plan skip_all => 'OpenSSL does not support protocol negotiation; it is too old' + unless openssl_can_negotiate(); + $doit->('https', '', $server->{tls_port}); + }; +}; + +done_testing; |