use strict; use warnings FATAL => 'all'; use Apache::Test; use Apache::TestRequest; use Socket; # send # arg #1: url prefix # arg #2: Host header (none if undef) # expected results: # arg #3: response code # arg #4: SERVER_NAME # arg #5: SERVER_PORT (canonical port if 'REMOTE') # undef == don't care my $url_suffix = 'modules/cgi/env.pl'; my @test_cases = ( [ "/", "righthost" => 200, 'righthost', 'REMOTE' ], [ "/", "righthost:123" => 200, 'righthost', '123' ], [ "/", "Righthost" => 200, 'righthost', 'REMOTE' ], [ "/", "Righthost:123" => 200, 'righthost', '123' ], [ "/", "128.0.0.1" => 200, '128.0.0.1', 'REMOTE' ], [ "/", "128.0.0.1:123" => 200, '128.0.0.1', '123' ], [ "/", "[::1]" => 200, '[::1]', 'REMOTE' ], [ "/", "[::1]:123" => 200, '[::1]', '123' ], [ "/", "[a::1]" => 200, '[a::1]', 'REMOTE' ], [ "/", "[a::1]:123" => 200, '[a::1]', '123' ], [ "/", "[A::1]" => 200, '[a::1]', 'REMOTE' ], [ "/", "[A::1]:123" => 200, '[a::1]', '123' ], [ "http://righthost/", undef => 200, 'righthost', 'REMOTE' ], [ "http://righthost:123/", undef => 200, 'righthost', '123' ], [ "http://Righthost/", undef => 200, 'righthost', 'REMOTE' ], [ "http://Righthost:123/", undef => 200, 'righthost', '123' ], [ "http://128.0.0.1/", undef => 200, '128.0.0.1', 'REMOTE' ], [ "http://128.0.0.1:123/", undef => 200, '128.0.0.1', '123' ], [ "http://[::1]/", undef => 200, '[::1]', 'REMOTE' ], [ "http://[::1]:123/", undef => 200, '[::1]', '123' ], [ "http://righthost/", "wronghost" => 200, 'righthost', 'REMOTE' ], [ "http://righthost:123/", "wronghost:321" => 200, 'righthost', '123' ], [ "http://Righthost/", "wronghost" => 200, 'righthost', 'REMOTE' ], [ "http://Righthost:123/", "wronghost:321" => 200, 'righthost', '123' ], [ "http://128.0.0.1/", "126.0.0.1" => 200, '128.0.0.1', 'REMOTE' ], [ "http://128.0.0.1:123/", "126.0.0.1:321" => 200, '128.0.0.1', '123' ], [ "http://[::1]/", "[::2]" => 200, '[::1]', 'REMOTE' ], [ "http://[::1]:123/", "[::2]:321" => 200, '[::1]', '123' ], ); my @todo; if (!have_min_apache_version('2.4.24')) { # r1426827 push @todo, 32, 35, 56, 59, 80, 83; } if (!have_min_apache_version('2.4')) { # r1147614, PR 26005 push @todo, 20, 23, 26, 29; } plan tests => 3 * scalar(@test_cases), todo => \@todo, need need_min_apache_version('2.2'), need_cgi; foreach my $t (@test_cases) { my $req = "GET $t->[0]$url_suffix HTTP/1.1\r\nConnection: close\r\n"; $req .= "Host: $t->[1]\r\n" if defined $t->[1]; $req .= "\r\n"; my %ex = ( rc => $t->[2], SERVER_NAME => $t->[3], SERVER_PORT => $t->[4], ); my $sock = Apache::TestRequest::vhost_socket(); if (!$sock) { print "# failed to connect\n"; ok(0); next; } if (defined $ex{SERVER_PORT} && $ex{SERVER_PORT} eq 'REMOTE') { my $peername = getpeername($sock); my ($port) = sockaddr_in($peername); $ex{SERVER_PORT} = "$port"; } $sock->print($req); $sock->shutdown(1); sleep(0.1); print "# SENDING:\n# ", escape($req), "\n"; my $response_data = ""; my $buf; while ($sock->read($buf, 10000) > 0) { $response_data .= $buf; } my $response = HTTP::Response->parse($response_data); if (! defined $response) { die "HTTP::Response->parse failed"; } my $rc = $response->code; if (! defined $rc) { print "# HTTPD dropped the connection\n"; ok(0); } else { print "# expecting $ex{rc}, got ", $rc, "\n"; ok ($rc == $ex{rc}); } foreach my $var (qw/SERVER_NAME SERVER_PORT/) { if (! defined $ex{$var}) { print "# don't care about $var\n"; ok(1); } elsif ($response_data =~ /^$var = (.*)$/m) { my $val = $1; print "# got $var='$val', expected '$ex{$var}'\n"; ok($val eq $ex{$var}); } else { print "# no $var in response, expected '$ex{$var}'\n"; ok(0); } } } sub escape { my $in = shift; $in =~ s{\\}{\\\\}g; $in =~ s{\r}{\\r}g; $in =~ s{\n}{\\n}g; $in =~ s{\t}{\\t}g; $in =~ s{([\x00-\x1f])}{sprintf("\\x%02x", ord($1))}ge; return $in; }