Mercurial > hg > nginx-tests
comparison h2_request_body.t @ 876:a6abbfed42c0
Tests: split HTTP/2 tests, HTTP2 package introduced.
author | Andrey Zelenkov <zelenkov@nginx.com> |
---|---|
date | Wed, 23 Mar 2016 17:23:08 +0300 |
parents | |
children | af2cd0ba6ca7 |
comparison
equal
deleted
inserted
replaced
875:c380b4b7e2e4 | 876:a6abbfed42c0 |
---|---|
1 #!/usr/bin/perl | |
2 | |
3 # (C) Sergey Kandaurov | |
4 # (C) Nginx, Inc. | |
5 | |
6 # Tests for HTTP/2 protocol with request body. | |
7 | |
8 ############################################################################### | |
9 | |
10 use warnings; | |
11 use strict; | |
12 | |
13 use Test::More; | |
14 | |
15 BEGIN { use FindBin; chdir($FindBin::Bin); } | |
16 | |
17 use lib 'lib'; | |
18 use Test::Nginx; | |
19 use Test::Nginx::HTTP2 qw/ :DEFAULT :frame /; | |
20 | |
21 ############################################################################### | |
22 | |
23 select STDERR; $| = 1; | |
24 select STDOUT; $| = 1; | |
25 | |
26 my $t = Test::Nginx->new()->has(qw/http http_ssl http_v2 proxy/)->plan(35); | |
27 | |
28 # Some systems may have also a bug in not treating zero writev iovcnt as EINVAL | |
29 | |
30 $t->todo_alerts(); | |
31 | |
32 $t->write_file_expand('nginx.conf', <<'EOF'); | |
33 | |
34 %%TEST_GLOBALS%% | |
35 | |
36 daemon off; | |
37 | |
38 events { | |
39 } | |
40 | |
41 http { | |
42 %%TEST_GLOBALS_HTTP%% | |
43 | |
44 server { | |
45 listen 127.0.0.1:8080 http2; | |
46 listen 127.0.0.1:8081; | |
47 listen 127.0.0.1:8082 ssl; | |
48 server_name localhost; | |
49 | |
50 location / { } | |
51 location /proxy2/ { | |
52 add_header X-Body $request_body; | |
53 add_header X-Body-File $request_body_file; | |
54 client_body_in_file_only on; | |
55 proxy_pass http://127.0.0.1:8081/; | |
56 } | |
57 location /proxy_ssl/ { | |
58 proxy_pass https://127.0.0.1:8082/; | |
59 } | |
60 location /client_max_body_size { | |
61 add_header X-Body $request_body; | |
62 add_header X-Body-File $request_body_file; | |
63 client_body_in_single_buffer on; | |
64 client_body_in_file_only on; | |
65 proxy_pass http://127.0.0.1:8081/; | |
66 client_max_body_size 10; | |
67 } | |
68 } | |
69 } | |
70 | |
71 EOF | |
72 | |
73 $t->write_file('index.html', ''); | |
74 $t->write_file('t.html', 'SEE-THIS'); | |
75 $t->run(); | |
76 | |
77 ############################################################################### | |
78 | |
79 # request body (uses proxied response) | |
80 | |
81 my $sess = new_session(); | |
82 my $sid = new_stream($sess, { path => '/proxy2/t.html', body_more => 1 }); | |
83 h2_body($sess, 'TEST'); | |
84 my $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
85 | |
86 my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
87 is(read_body_file($frame->{headers}->{'x-body-file'}), 'TEST', 'request body'); | |
88 | |
89 # request body with padding (uses proxied response) | |
90 | |
91 $sess = new_session(); | |
92 $sid = new_stream($sess, { path => '/proxy2/t.html', body_more => 1 }); | |
93 h2_body($sess, 'TEST', { body_padding => 42 }); | |
94 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
95 | |
96 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
97 is(read_body_file($frame->{headers}->{'x-body-file'}), 'TEST', | |
98 'request body with padding'); | |
99 | |
100 $sid = new_stream($sess); | |
101 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
102 | |
103 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
104 is($frame->{headers}->{':status'}, '200', 'request body with padding - next'); | |
105 | |
106 # request body sent in multiple DATA frames in a single packet | |
107 | |
108 $sess = new_session(); | |
109 $sid = new_stream($sess, { path => '/proxy2/t.html', body_more => 1 }); | |
110 h2_body($sess, 'TEST', { body_split => [2] }); | |
111 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
112 | |
113 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
114 is(read_body_file($frame->{headers}->{'x-body-file'}), 'TEST', | |
115 'request body in multiple frames'); | |
116 | |
117 # request body sent in multiple DATA frames, each in its own packet | |
118 | |
119 $sess = new_session(); | |
120 $sid = new_stream($sess, { path => '/proxy2/t.html', body_more => 1 }); | |
121 h2_body($sess, 'TEST', { body_more => 1 }); | |
122 select undef, undef, undef, 0.1; | |
123 h2_body($sess, 'MOREDATA'); | |
124 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
125 | |
126 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
127 is(read_body_file($frame->{headers}->{'x-body-file'}), 'TESTMOREDATA', | |
128 'request body in multiple frames separately'); | |
129 | |
130 # request body with an empty DATA frame | |
131 # "zero size buf in output" alerts seen | |
132 | |
133 $sess = new_session(); | |
134 $sid = new_stream($sess, { path => '/proxy2/', body_more => 1 }); | |
135 h2_body($sess, ''); | |
136 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
137 | |
138 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
139 is($frame->{headers}->{':status'}, 200, 'request body - empty'); | |
140 | |
141 TODO: { | |
142 local $TODO = 'not yet'; | |
143 | |
144 ok($frame->{headers}{'x-body-file'}, 'request body - empty body file'); | |
145 | |
146 } | |
147 | |
148 TODO: { | |
149 todo_skip 'empty body file', 1 unless $frame->{headers}{'x-body-file'}; | |
150 | |
151 is(read_body_file($frame->{headers}{'x-body-file'}), '', | |
152 'request body - empty content'); | |
153 | |
154 } | |
155 | |
156 # same as above but proxied to ssl backend | |
157 | |
158 TODO: { | |
159 local $TODO = 'not yet'; | |
160 | |
161 $sess = new_session(); | |
162 $sid = new_stream($sess, { path => '/proxy_ssl/', body_more => 1 }); | |
163 h2_body($sess, ''); | |
164 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
165 | |
166 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
167 is($frame->{headers}->{':status'}, 200, 'request body - empty - proxy ssl'); | |
168 | |
169 } | |
170 | |
171 # malformed request body length not equal to content-length | |
172 | |
173 $sess = new_session(); | |
174 $sid = new_stream($sess, | |
175 { body_more => 1, headers => [ | |
176 { name => ':method', value => 'GET', mode => 0 }, | |
177 { name => ':scheme', value => 'http', mode => 0 }, | |
178 { name => ':path', value => '/client_max_body_size', mode => 1 }, | |
179 { name => ':authority', value => 'localhost', mode => 1 }, | |
180 { name => 'content-length', value => '5', mode => 1 }]}); | |
181 h2_body($sess, 'TEST'); | |
182 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
183 | |
184 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
185 is($frame->{headers}->{':status'}, 400, 'request body less than content-length'); | |
186 | |
187 $sid = new_stream($sess, | |
188 { body_more => 1, headers => [ | |
189 { name => ':method', value => 'GET', mode => 0 }, | |
190 { name => ':scheme', value => 'http', mode => 0 }, | |
191 { name => ':path', value => '/client_max_body_size', mode => 1 }, | |
192 { name => ':authority', value => 'localhost', mode => 1 }, | |
193 { name => 'content-length', value => '3', mode => 1 }]}); | |
194 h2_body($sess, 'TEST'); | |
195 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
196 | |
197 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
198 is($frame->{headers}->{':status'}, 400, 'request body more than content-length'); | |
199 | |
200 # client_max_body_size | |
201 | |
202 $sess = new_session(); | |
203 $sid = new_stream($sess, { path => '/client_max_body_size/t.html', | |
204 body_more => 1 }); | |
205 h2_body($sess, 'TESTTEST12'); | |
206 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
207 | |
208 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
209 is($frame->{headers}->{':status'}, 200, 'client_max_body_size - status'); | |
210 is(read_body_file($frame->{headers}->{'x-body-file'}), 'TESTTEST12', | |
211 'client_max_body_size - body'); | |
212 | |
213 # client_max_body_size - limited | |
214 | |
215 $sess = new_session(); | |
216 $sid = new_stream($sess, { path => '/client_max_body_size/t.html', | |
217 body_more => 1 }); | |
218 h2_body($sess, 'TESTTEST123'); | |
219 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
220 | |
221 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
222 is($frame->{headers}->{':status'}, 413, 'client_max_body_size - limited'); | |
223 | |
224 # client_max_body_size - many DATA frames | |
225 | |
226 $sess = new_session(); | |
227 $sid = new_stream($sess, { path => '/client_max_body_size/t.html', | |
228 body_more => 1 }); | |
229 h2_body($sess, 'TESTTEST12', { body_split => [2] }); | |
230 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
231 | |
232 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
233 is($frame->{headers}->{':status'}, 200, 'client_max_body_size many - status'); | |
234 is(read_body_file($frame->{headers}->{'x-body-file'}), 'TESTTEST12', | |
235 'client_max_body_size many - body'); | |
236 | |
237 # client_max_body_size - many DATA frames - limited | |
238 | |
239 $sess = new_session(); | |
240 $sid = new_stream($sess, { path => '/client_max_body_size/t.html', | |
241 body_more => 1 }); | |
242 h2_body($sess, 'TESTTEST123', { body_split => [2] }); | |
243 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
244 | |
245 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
246 is($frame->{headers}->{':status'}, 413, 'client_max_body_size many - limited'); | |
247 | |
248 # client_max_body_size - padded DATA | |
249 | |
250 $sess = new_session(); | |
251 $sid = new_stream($sess, { path => '/client_max_body_size/t.html', | |
252 body_more => 1 }); | |
253 h2_body($sess, 'TESTTEST12', { body_padding => 42 }); | |
254 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
255 | |
256 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
257 is($frame->{headers}->{':status'}, 200, 'client_max_body_size pad - status'); | |
258 is(read_body_file($frame->{headers}->{'x-body-file'}), 'TESTTEST12', | |
259 'client_max_body_size pad - body'); | |
260 | |
261 # client_max_body_size - padded DATA - limited | |
262 | |
263 $sess = new_session(); | |
264 $sid = new_stream($sess, { path => '/client_max_body_size/t.html', | |
265 body_more => 1 }); | |
266 h2_body($sess, 'TESTTEST123', { body_padding => 42 }); | |
267 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
268 | |
269 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
270 is($frame->{headers}->{':status'}, 413, 'client_max_body_size pad - limited'); | |
271 | |
272 # client_max_body_size - many padded DATA frames | |
273 | |
274 $sess = new_session(); | |
275 $sid = new_stream($sess, { path => '/client_max_body_size/t.html', | |
276 body_more => 1 }); | |
277 h2_body($sess, 'TESTTEST12', { body_padding => 42, body_split => [2] }); | |
278 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
279 | |
280 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
281 is($frame->{headers}->{':status'}, 200, | |
282 'client_max_body_size many pad - status'); | |
283 is(read_body_file($frame->{headers}->{'x-body-file'}), 'TESTTEST12', | |
284 'client_max_body_size many pad - body'); | |
285 | |
286 # client_max_body_size - many padded DATA frames - limited | |
287 | |
288 $sess = new_session(); | |
289 $sid = new_stream($sess, { path => '/client_max_body_size/t.html', | |
290 body_more => 1 }); | |
291 h2_body($sess, 'TESTTEST123', { body_padding => 42, body_split => [2] }); | |
292 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
293 | |
294 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
295 is($frame->{headers}->{':status'}, 413, | |
296 'client_max_body_size many pad - limited'); | |
297 | |
298 # request body without content-length | |
299 | |
300 $sess = new_session(); | |
301 $sid = new_stream($sess, { body_more => 1, headers => [ | |
302 { name => ':method', value => 'GET', mode => 2 }, | |
303 { name => ':scheme', value => 'http', mode => 2 }, | |
304 { name => ':path', value => '/client_max_body_size', mode => 2 }, | |
305 { name => ':authority', value => 'localhost', mode => 2 }]}); | |
306 h2_body($sess, 'TESTTEST12'); | |
307 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
308 | |
309 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
310 is($frame->{headers}->{':status'}, 200, | |
311 'request body without content-length - status'); | |
312 is(read_body_file($frame->{headers}->{'x-body-file'}), 'TESTTEST12', | |
313 'request body without content-length - body'); | |
314 | |
315 # request body without content-length - limited | |
316 | |
317 $sess = new_session(); | |
318 $sid = new_stream($sess, { body_more => 1, headers => [ | |
319 { name => ':method', value => 'GET', mode => 2 }, | |
320 { name => ':scheme', value => 'http', mode => 2 }, | |
321 { name => ':path', value => '/client_max_body_size', mode => 2 }, | |
322 { name => ':authority', value => 'localhost', mode => 2 }]}); | |
323 h2_body($sess, 'TESTTEST123'); | |
324 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
325 | |
326 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
327 is($frame->{headers}->{':status'}, 413, | |
328 'request body without content-length - limited'); | |
329 | |
330 # request body without content-length - many DATA frames | |
331 | |
332 $sess = new_session(); | |
333 $sid = new_stream($sess, { body_more => 1, headers => [ | |
334 { name => ':method', value => 'GET', mode => 2 }, | |
335 { name => ':scheme', value => 'http', mode => 2 }, | |
336 { name => ':path', value => '/client_max_body_size', mode => 2 }, | |
337 { name => ':authority', value => 'localhost', mode => 2 }]}); | |
338 h2_body($sess, 'TESTTEST12', { body_split => [2] }); | |
339 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
340 | |
341 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
342 is($frame->{headers}->{':status'}, 200, | |
343 'request body without content-length many - status'); | |
344 is(read_body_file($frame->{headers}->{'x-body-file'}), 'TESTTEST12', | |
345 'request body without content-length many - body'); | |
346 | |
347 # request body without content-length - many DATA frames - limited | |
348 | |
349 $sess = new_session(); | |
350 $sid = new_stream($sess, { body_more => 1, headers => [ | |
351 { name => ':method', value => 'GET', mode => 2 }, | |
352 { name => ':scheme', value => 'http', mode => 2 }, | |
353 { name => ':path', value => '/client_max_body_size', mode => 2 }, | |
354 { name => ':authority', value => 'localhost', mode => 2 }]}); | |
355 h2_body($sess, 'TESTTEST123', { body_split => [2] }); | |
356 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
357 | |
358 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
359 is($frame->{headers}->{':status'}, 413, | |
360 'request body without content-length many - limited'); | |
361 | |
362 # request body without content-length - padding | |
363 | |
364 $sess = new_session(); | |
365 $sid = new_stream($sess, { body_more => 1, headers => [ | |
366 { name => ':method', value => 'GET', mode => 2 }, | |
367 { name => ':scheme', value => 'http', mode => 2 }, | |
368 { name => ':path', value => '/client_max_body_size', mode => 2 }, | |
369 { name => ':authority', value => 'localhost', mode => 2 }]}); | |
370 h2_body($sess, 'TESTTEST12', { body_padding => 42 }); | |
371 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
372 | |
373 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
374 is($frame->{headers}->{':status'}, 200, | |
375 'request body without content-length pad - status'); | |
376 is(read_body_file($frame->{headers}->{'x-body-file'}), 'TESTTEST12', | |
377 'request body without content-length pad - body'); | |
378 | |
379 # request body without content-length - padding - limited | |
380 | |
381 $sess = new_session(); | |
382 $sid = new_stream($sess, { body_more => 1, headers => [ | |
383 { name => ':method', value => 'GET', mode => 2 }, | |
384 { name => ':scheme', value => 'http', mode => 2 }, | |
385 { name => ':path', value => '/client_max_body_size', mode => 2 }, | |
386 { name => ':authority', value => 'localhost', mode => 2 }]}); | |
387 h2_body($sess, 'TESTTEST123', { body_padding => 42 }); | |
388 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
389 | |
390 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
391 is($frame->{headers}->{':status'}, 413, | |
392 'request body without content-length pad - limited'); | |
393 | |
394 # request body without content-length - padding with many DATA frames | |
395 | |
396 $sess = new_session(); | |
397 $sid = new_stream($sess, { body_more => 1, headers => [ | |
398 { name => ':method', value => 'GET', mode => 2 }, | |
399 { name => ':scheme', value => 'http', mode => 2 }, | |
400 { name => ':path', value => '/client_max_body_size', mode => 2 }, | |
401 { name => ':authority', value => 'localhost', mode => 2 }]}); | |
402 h2_body($sess, 'TESTTEST', { body_padding => 42, body_split => [2] }); | |
403 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
404 | |
405 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
406 is($frame->{headers}->{':status'}, 200, | |
407 'request body without content-length many pad - status'); | |
408 is(read_body_file($frame->{headers}->{'x-body-file'}), 'TESTTEST', | |
409 'request body without content-length many pad - body'); | |
410 | |
411 # request body without content-length - padding with many DATA frames - limited | |
412 | |
413 $sess = new_session(); | |
414 $sid = new_stream($sess, { body_more => 1, headers => [ | |
415 { name => ':method', value => 'GET', mode => 2 }, | |
416 { name => ':scheme', value => 'http', mode => 2 }, | |
417 { name => ':path', value => '/client_max_body_size', mode => 2 }, | |
418 { name => ':authority', value => 'localhost', mode => 2 }]}); | |
419 h2_body($sess, 'TESTTEST123', { body_padding => 42, body_split => [2] }); | |
420 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
421 | |
422 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
423 is($frame->{headers}->{':status'}, 413, | |
424 'request body without content-length many pad - limited'); | |
425 | |
426 ############################################################################### | |
427 | |
428 sub read_body_file { | |
429 my ($path) = @_; | |
430 open FILE, $path or return "$!"; | |
431 local $/; | |
432 my $content = <FILE>; | |
433 close FILE; | |
434 return $content; | |
435 } | |
436 | |
437 ############################################################################### |