| 1 | #!/usr/bin/perl
|
|---|
| 2 |
|
|---|
| 3 | # (C) Maxim Dounin
|
|---|
| 4 | # (C) Markus Linnala
|
|---|
| 5 |
|
|---|
| 6 | # Tests keepalive is kept regardless proxy type.
|
|---|
| 7 |
|
|---|
| 8 | ###############################################################################
|
|---|
| 9 |
|
|---|
| 10 | use warnings;
|
|---|
| 11 | use strict;
|
|---|
| 12 |
|
|---|
| 13 | use Test::More;
|
|---|
| 14 |
|
|---|
| 15 | use IO::Socket::INET;
|
|---|
| 16 | use Socket qw/ CRLF /;
|
|---|
| 17 |
|
|---|
| 18 | BEGIN { use FindBin; chdir($FindBin::Bin); }
|
|---|
| 19 |
|
|---|
| 20 | use lib 'lib';
|
|---|
| 21 | use Test::Nginx;
|
|---|
| 22 |
|
|---|
| 23 | ###############################################################################
|
|---|
| 24 |
|
|---|
| 25 | select STDERR; $| = 1;
|
|---|
| 26 | select STDOUT; $| = 1;
|
|---|
| 27 |
|
|---|
| 28 | plan(skip_all => 'win32') if $^O eq 'MSWin32';
|
|---|
| 29 |
|
|---|
| 30 | my $t = Test::Nginx->new()->has(qw/http proxy upstream_keepalive sub/)->plan(2)
|
|---|
| 31 | ->write_file_expand('nginx.conf', <<'EOF');
|
|---|
| 32 |
|
|---|
| 33 | %%TEST_GLOBALS%%
|
|---|
| 34 |
|
|---|
| 35 | daemon off;
|
|---|
| 36 |
|
|---|
| 37 | events {
|
|---|
| 38 | }
|
|---|
| 39 |
|
|---|
| 40 | http {
|
|---|
| 41 | %%TEST_GLOBALS_HTTP%%
|
|---|
| 42 |
|
|---|
| 43 | upstream backend {
|
|---|
| 44 | server 127.0.0.1:8081;
|
|---|
| 45 | }
|
|---|
| 46 |
|
|---|
| 47 | server {
|
|---|
| 48 | listen 127.0.0.1:8080;
|
|---|
| 49 | server_name localhost;
|
|---|
| 50 |
|
|---|
| 51 | location / {
|
|---|
| 52 | proxy_pass http://backend;
|
|---|
| 53 | proxy_http_version 1.1;
|
|---|
| 54 | proxy_set_header Connection "";
|
|---|
| 55 | }
|
|---|
| 56 | }
|
|---|
| 57 | }
|
|---|
| 58 |
|
|---|
| 59 | EOF
|
|---|
| 60 |
|
|---|
| 61 | $t->run_daemon(\&http_daemon);
|
|---|
| 62 | $t->run()->waitforsocket('127.0.0.1:8081')
|
|---|
| 63 | or die "Can't start test backend";
|
|---|
| 64 |
|
|---|
| 65 | ###############################################################################
|
|---|
| 66 |
|
|---|
| 67 | like(http_ka('/','1.0'), qr/Connection: keep-alive/, 'keepalive/1.0 proxy chunked');
|
|---|
| 68 | like(http_cl('/','1.0'), qr/Connection: close/, 'close/1.0 proxy chunked');
|
|---|
| 69 |
|
|---|
| 70 | like(http_ka('/','1.1'), qr/Connection: keep-alive/, 'keepalive/1.1 proxy chunked');
|
|---|
| 71 | like(http_cl('/','1.1'), qr/Connection: close/, 'close/1.1 proxy chunked');
|
|---|
| 72 |
|
|---|
| 73 | ###############################################################################
|
|---|
| 74 |
|
|---|
| 75 | sub http_ka {
|
|---|
| 76 | my ($q, $p) = @_;
|
|---|
| 77 | my_http(<<EOF, 'sleep' => 0.1);
|
|---|
| 78 | GET $q HTTP/$p
|
|---|
| 79 | Host: localhost
|
|---|
| 80 | Connection: Keep-Alive
|
|---|
| 81 |
|
|---|
| 82 | EOF
|
|---|
| 83 | }
|
|---|
| 84 |
|
|---|
| 85 | sub http_cl {
|
|---|
| 86 | my ($q, $p) = @_;
|
|---|
| 87 | my_http(<<EOF, 'sleep' => 0.1);
|
|---|
| 88 | GET $q HTTP/$p
|
|---|
| 89 | Host: localhost
|
|---|
| 90 | Connection: close
|
|---|
| 91 |
|
|---|
| 92 | EOF
|
|---|
| 93 | }
|
|---|
| 94 |
|
|---|
| 95 | ###############################################################################
|
|---|
| 96 |
|
|---|
| 97 | sub my_http {
|
|---|
| 98 | my ($request, %extra) = @_;
|
|---|
| 99 | my $reply;
|
|---|
| 100 |
|
|---|
| 101 | eval {
|
|---|
| 102 | local $SIG{ALRM} = sub { die "timeout\n" };
|
|---|
| 103 | local $SIG{PIPE} = sub { die "sigpipe\n" };
|
|---|
| 104 | alarm(5);
|
|---|
| 105 |
|
|---|
| 106 | my $s = $extra{socket} || IO::Socket::INET->new(
|
|---|
| 107 | Proto => 'tcp',
|
|---|
| 108 | PeerAddr => '127.0.0.1:8080',
|
|---|
| 109 | )
|
|---|
| 110 | or die "Can't connect to nginx: $!\n";
|
|---|
| 111 |
|
|---|
| 112 | log_out($request);
|
|---|
| 113 | $s->print($request);
|
|---|
| 114 |
|
|---|
| 115 | select undef, undef, undef, $extra{sleep} if $extra{sleep};
|
|---|
| 116 | return '' if $extra{aborted};
|
|---|
| 117 |
|
|---|
| 118 | if ($extra{body}) {
|
|---|
| 119 | log_out($extra{body});
|
|---|
| 120 | $s->print($extra{body});
|
|---|
| 121 | }
|
|---|
| 122 |
|
|---|
| 123 | # Done writing
|
|---|
| 124 | $s->shutdown(1);
|
|---|
| 125 |
|
|---|
| 126 | local $/;
|
|---|
| 127 | $reply = $s->getline();
|
|---|
| 128 |
|
|---|
| 129 | alarm(0);
|
|---|
| 130 | };
|
|---|
| 131 | alarm(0);
|
|---|
| 132 | if ($@) {
|
|---|
| 133 | log_in("died: $@");
|
|---|
| 134 | return undef;
|
|---|
| 135 | }
|
|---|
| 136 |
|
|---|
| 137 | log_in($reply);
|
|---|
| 138 | return $reply;
|
|---|
| 139 | }
|
|---|
| 140 |
|
|---|
| 141 | sub http_daemon {
|
|---|
| 142 | my $server = IO::Socket::INET->new(
|
|---|
| 143 | Proto => 'tcp',
|
|---|
| 144 | LocalHost => '127.0.0.1:8081',
|
|---|
| 145 | Listen => 5,
|
|---|
| 146 | Reuse => 1
|
|---|
| 147 | )
|
|---|
| 148 | or die "Can't create listening socket: $!\n";
|
|---|
| 149 |
|
|---|
| 150 | # dumb server which is able to keep connections alive
|
|---|
| 151 |
|
|---|
| 152 | while (my $client = $server->accept()) {
|
|---|
| 153 | $client->autoflush(1);
|
|---|
| 154 |
|
|---|
| 155 | while (1) {
|
|---|
| 156 | my $headers = '';
|
|---|
| 157 | my $uri = '';
|
|---|
| 158 |
|
|---|
| 159 | while (<$client>) {
|
|---|
| 160 | $headers .= $_;
|
|---|
| 161 | last if (/^\x0d?\x0a?$/);
|
|---|
| 162 | }
|
|---|
| 163 |
|
|---|
| 164 | last if $headers eq '';
|
|---|
| 165 |
|
|---|
| 166 | $uri = $1 if $headers =~ /^\S+\s+([^ ]+)\s+HTTP/i;
|
|---|
| 167 |
|
|---|
| 168 | print { $client }
|
|---|
| 169 | "HTTP/1.1 200 OK" . CRLF .
|
|---|
| 170 | "Transfer-Encoding: chunked" . CRLF .
|
|---|
| 171 | CRLF .
|
|---|
| 172 | "a" . CRLF .
|
|---|
| 173 | "finished" . CRLF .
|
|---|
| 174 | CRLF . "0" . CRLF . CRLF;
|
|---|
| 175 |
|
|---|
| 176 | last;
|
|---|
| 177 | }
|
|---|
| 178 |
|
|---|
| 179 | close $client;
|
|---|
| 180 | }
|
|---|
| 181 | }
|
|---|
| 182 |
|
|---|
| 183 | ###############################################################################
|
|---|