Mercurial > hg > ngx_http_upstream_keepalive
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 ############################################################################### |