comparison t/proxy.t @ 27:f3b50effc1d4

Keepalive: add proxy tests.
author Maxim Dounin <mdounin@mdounin.ru>
date Tue, 26 Jul 2011 12:52:34 +0400
parents
children 52ca695446d3
comparison
equal deleted inserted replaced
26:cb15f6f4d820 27:f3b50effc1d4
1 #!/usr/bin/perl
2
3 # (C) Maxim Dounin
4
5 # Tests for proxy with keepalive.
6
7 ###############################################################################
8
9 use warnings;
10 use strict;
11
12 use Test::More;
13 use IO::Socket::INET;
14 use Socket qw/ CRLF /;
15
16 use Test::Nginx;
17
18 ###############################################################################
19
20 select STDERR; $| = 1;
21 select STDOUT; $| = 1;
22
23 my $t = Test::Nginx->new()->has(qw/http proxy ssi rewrite/)
24 ->write_file_expand('nginx.conf', <<'EOF');
25
26 %%TEST_GLOBALS%%
27
28 daemon off;
29
30 events {
31 }
32
33 http {
34 %%TEST_GLOBALS_HTTP%%
35
36 upstream backend {
37 server 127.0.0.1:8081;
38 keepalive 1;
39 }
40
41 server {
42 listen 127.0.0.1:8080;
43 server_name localhost;
44
45 proxy_read_timeout 2s;
46 proxy_http_version 1.1;
47 proxy_set_header Connection "";
48
49 location / {
50 proxy_pass http://backend;
51 }
52
53 location /unbuffered/ {
54 proxy_pass http://backend;
55 proxy_buffering off;
56 }
57
58 location /inmemory/ {
59 ssi on;
60 rewrite ^ /ssi.html break;
61 }
62 }
63 }
64
65 EOF
66
67 $t->write_file('ssi.html',
68 '<!--#include virtual="/include$request_uri" set="x" -->' .
69 'set: <!--#echo var="x" -->');
70
71 $t->run_daemon(\&http_daemon);
72
73 eval {
74 open OLDERR, ">&", \*STDERR; close STDERR;
75 $t->run();
76 open STDERR, ">&", \*OLDERR;
77 };
78 plan(skip_all => 'no keepalive patches') if $@;
79
80 $t->plan(42);
81
82 ###############################################################################
83
84 # There are 3 mostly independend modes of upstream operation:
85 #
86 # 1. Buffered, i.e. normal mode with "proxy_buffering on;"
87 # 2. Unbuffered, i.e. "proxy_buffering off;".
88 # 3. In memory, i.e. ssi <!--#include ... set -->
89 #
90 # These all should be tested.
91
92 my ($r, $n);
93
94 # buffered
95
96 like($r = http_get('/buffered/length1'), qr/SEE-THIS/, 'buffered');
97 $r =~ m/X-Connection: (\d+)/; $n = $1;
98 like(http_get('/buffered/length2'), qr/X-Connection: $n.*SEE/ms, 'buffered 2');
99
100 like($r = http_get('/buffered/chunked1'), qr/SEE-THIS/, 'buffered chunked');
101 $r =~ m/X-Connection: (\d+)/; $n = $1;
102 like(http_get('/buffered/chunked2'), qr/X-Connection: $n/,
103 'buffered chunked 2');
104
105 like($r = http_get('/buffered/complex1'), qr/(0123456789){100}/,
106 'buffered complex chunked');
107 $r =~ m/X-Connection: (\d+)/; $n = $1;
108 like(http_get('/buffered/complex2'), qr/X-Connection: $n/,
109 'buffered complex chunked 2');
110
111 like($r = http_get('/buffered/chunk01'), qr/200 OK/, 'buffered 0 chunk');
112 $r =~ m/X-Connection: (\d+)/; $n = $1;
113 like(http_get('/buffered/chunk02'), qr/X-Connection: $n/, 'buffered 0 chunk 2');
114
115 like($r = http_head('/buffered/length/head1'), qr/(?!SEE-THIS)/,
116 'buffered head');
117 $r =~ m/X-Connection: (\d+)/; $n = $1;
118 like(http_head('/buffered/length/head2'), qr/X-Connection: $n/,
119 'buffered head 2');
120
121 like($r = http_get('/buffered/empty1'), qr/200 OK/, 'buffered empty');
122 $r =~ m/X-Connection: (\d+)/; $n = $1;
123 like(http_get('/buffered/empty2'), qr/X-Connection: $n/, 'buffered empty 2');
124
125 like($r = http_get('/buffered/304nolen1'), qr/304 Not/, 'buffered 304');
126 $r =~ m/X-Connection: (\d+)/; $n = $1;
127 like(http_get('/buffered/304nolen2'), qr/X-Connection: $n/, 'buffered 304 2');
128
129 like($r = http_get('/buffered/304len1'), qr/304 Not/,
130 'buffered 304 with length');
131 $r =~ m/X-Connection: (\d+)/; $n = $1;
132 like(http_get('/buffered/304len2'), qr/X-Connection: $n/,
133 'buffered 304 with length 2');
134
135 # unbuffered
136
137 like($r = http_get('/unbuffered/length1'), qr/SEE-THIS/, 'unbuffered');
138 $r =~ m/X-Connection: (\d+)/; $n = $1;
139 like(http_get('/unbuffered/length2'), qr/X-Connection: $n/, 'unbuffered 2');
140
141 like($r = http_get('/unbuffered/chunked1'), qr/SEE-THIS/, 'unbuffered chunked');
142 $r =~ m/X-Connection: (\d+)/; $n = $1;
143 like(http_get('/unbuffered/chunked2'), qr/X-Connection: $n/,
144 'unbuffered chunked 2');
145
146 like($r = http_get('/unbuffered/complex1'), qr/(0123456789){100}/,
147 'unbuffered complex chunked');
148 $r =~ m/X-Connection: (\d+)/; $n = $1;
149 like(http_get('/unbuffered/complex2'), qr/X-Connection: $n/,
150 'unbuffered complex chunked 2');
151
152 like($r = http_get('/unbuffered/chunk01'), qr/200 OK/, 'unbuffered 0 chunk');
153 $r =~ m/X-Connection: (\d+)/; $n = $1;
154 like(http_get('/unbuffered/chunk02'), qr/X-Connection: $n/,
155 'unbuffered 0 chunk 2');
156
157 like($r = http_get('/unbuffered/empty1'), qr/200 OK/, 'unbuffered empty');
158 $r =~ m/X-Connection: (\d+)/; $n = $1;
159 like(http_get('/unbuffered/empty2'), qr/X-Connection: $n/,
160 'unbuffered empty 2');
161
162 like($r = http_head('/unbuffered/length/head1'), qr/(?!SEE-THIS)/,
163 'unbuffered head');
164 $r =~ m/X-Connection: (\d+)/; $n = $1;
165 like(http_head('/unbuffered/length/head2'), qr/X-Connection: $n/,
166 'unbuffered head 2');
167
168 like($r = http_get('/unbuffered/304nolen1'), qr/304 Not/, 'unbuffered 304');
169 $r =~ m/X-Connection: (\d+)/; $n = $1;
170 like(http_get('/unbuffered/304nolen2'), qr/X-Connection: $n/,
171 'unbuffered 304 2');
172
173 like($r = http_get('/unbuffered/304len1'), qr/304 Not/,
174 'unbuffered 304 with length');
175 $r =~ m/X-Connection: (\d+)/; $n = $1;
176 like(http_get('/unbuffered/304len2'), qr/X-Connection: $n/,
177 'unbuffered 304 with length 2');
178
179 # in memory
180
181 like($r = http_get('/inmemory/length1'), qr/SEE-THIS/, 'inmemory');
182 $r =~ m/SEE-THIS(\d+)/; $n = $1;
183 like(http_get('/inmemory/length2'), qr/SEE-THIS$n/, 'inmemory 2');
184
185 like($r = http_get('/inmemory/empty1'), qr/200 OK/, 'inmemory empty');
186 $r =~ m/SEE-THIS(\d+)/; $n = $1;
187 like(http_get('/inmemory/empty2'), qr/200 OK/, 'inmemory empty 2');
188
189 like($r = http_get('/inmemory/chunked1'), qr/SEE-THIS/, 'inmemory chunked');
190 $r =~ m/SEE-THIS(\d+)/; $n = $1;
191 like(http_get('/inmemory/chunked2'), qr/SEE-THIS$n/, 'inmemory chunked 2');
192
193 like($r = http_get('/inmemory/complex1'), qr/(0123456789){100}/,
194 'inmemory complex chunked');
195 $r =~ m/SEE-THIS(\d+)/; $n = $1;
196 like(http_get('/inmemory/complex2'), qr/SEE-THIS$n/,
197 'inmemory complex chunked 2');
198
199 like(http_get('/inmemory/chunk01'), qr/set: $/, 'inmemory 0 chunk');
200 like(http_get('/inmemory/chunk02'), qr/set: $/, 'inmemory 0 chunk 2');
201
202 ###############################################################################
203
204 sub http_daemon {
205 my $server = IO::Socket::INET->new(
206 Proto => 'tcp',
207 LocalHost => '127.0.0.1:8081',
208 Listen => 5,
209 Reuse => 1
210 )
211 or die "Can't create listening socket: $!\n";
212
213 my $ccount = 0;
214 my $rcount = 0;
215
216 # dumb server which is able to keep connections alive
217
218 while (my $client = $server->accept()) {
219 Test::Nginx::log_core('||', "connection from " . $client->peerhost());
220 $client->autoflush(1);
221 $ccount++;
222
223 while (1) {
224 my $headers = '';
225 my $uri = '';
226
227 while (<$client>) {
228 Test::Nginx::log_core('||', $_);
229 $headers .= $_;
230 last if (/^\x0d?\x0a?$/);
231 }
232
233 last if $headers eq '';
234 $rcount++;
235
236 $uri = $1 if $headers =~ /^\S+\s+([^ ]+)\s+HTTP/i;
237
238 if ($uri =~ m/length/) {
239 print $client
240 "HTTP/1.1 200 OK" . CRLF .
241 "X-Request: $rcount" . CRLF .
242 "X-Connection: $ccount" . CRLF .
243 "Content-Length: 26" . CRLF . CRLF;
244 print $client "TEST-OK-IF-YOU-SEE-THIS" .
245 sprintf("%03d", $ccount)
246 unless $headers =~ /^HEAD/i;
247
248 } elsif ($uri =~ m/empty/) {
249 print $client
250 "HTTP/1.1 200 OK" . CRLF .
251 "X-Request: $rcount" . CRLF .
252 "X-Connection: $ccount" . CRLF .
253 "Content-Length: 0" . CRLF . CRLF;
254
255 } elsif ($uri =~ m/304nolen/) {
256 print $client
257 "HTTP/1.1 304 Not Modified" . CRLF .
258 "X-Request: $rcount" . CRLF .
259 "X-Connection: $ccount" . CRLF . CRLF;
260
261 } elsif ($uri =~ m/304len/) {
262 print $client
263 "HTTP/1.1 304 Not Modified" . CRLF .
264 "X-Request: $rcount" . CRLF .
265 "X-Connection: $ccount" . CRLF .
266 "Content-Length: 100" . CRLF . CRLF;
267
268 } elsif ($uri =~ m/chunked/) {
269 print $client
270 "HTTP/1.1 200 OK" . CRLF .
271 "X-Request: $rcount" . CRLF .
272 "X-Connection: $ccount" . CRLF .
273 "Transfer-Encoding: chunked" . CRLF .
274 CRLF;
275 print $client
276 "1a" . CRLF .
277 "TEST-OK-IF-YOU-SEE-THIS" .
278 sprintf("%03d", $ccount) . CRLF .
279 "0" . CRLF . CRLF
280 unless $headers =~ /^HEAD/i;
281
282 } elsif ($uri =~ m/complex/) {
283 print $client
284 "HTTP/1.1 200 OK" . CRLF .
285 "X-Request: $rcount" . CRLF .
286 "X-Connection: $ccount" . CRLF .
287 "Transfer-Encoding: chunked" . CRLF .
288 CRLF;
289
290 if ($headers !~ /^HEAD/i) {
291 for my $n (1..100) {
292 print $client
293 "a" . CRLF .
294 "0123456789" . CRLF;
295 select undef, undef, undef, 0.01
296 if $n % 50 == 0;
297 }
298 print $client
299 "1a" . CRLF .
300 "TEST-OK-IF-YOU-SEE-THIS" .
301 sprintf("%03d", $ccount) .
302 CRLF .
303 "0" . CRLF;
304 select undef, undef, undef, 0.05;
305 print $client CRLF;
306 }
307
308 } elsif ($uri =~ m/chunk0/) {
309 print $client
310 "HTTP/1.1 200 OK" . CRLF .
311 "X-Request: $rcount" . CRLF .
312 "X-Connection: $ccount" . CRLF .
313 "Transfer-Encoding: chunked" . CRLF .
314 CRLF;
315 print $client
316 "0" . CRLF . CRLF
317 unless $headers =~ /^HEAD/i;
318
319 } else {
320 print $client
321 "HTTP/1.1 404 Not Found" . CRLF .
322 "X-Request: $rcount" . CRLF .
323 "X-Connection: $ccount" . CRLF .
324 "Connection: close" . CRLF . CRLF .
325 "Oops, '$uri' not found" . CRLF;
326 last;
327 }
328 }
329
330 close $client;
331 }
332 }
333
334 ###############################################################################