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