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 ###############################################################################