comparison h2_request_body_extra.t @ 1726:f66266cc82c8

Tests: additional HTTP/2 request body tests.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 30 Aug 2021 16:42:46 +0300
parents
children 236d038dc04a
comparison
equal deleted inserted replaced
1725:f4c79ee52d8f 1726:f66266cc82c8
1 #!/usr/bin/perl
2
3 # (C) Maxim Dounin
4 # (C) Nginx, Inc.
5
6 # Tests for HTTP/2 protocol with request body, additional tests.
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;
20
21 ###############################################################################
22
23 select STDERR; $| = 1;
24 select STDOUT; $| = 1;
25
26 my $t = Test::Nginx->new()->has(qw/http http_v2 proxy rewrite/);
27
28 $t->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 server {
41 listen 127.0.0.1:8080 http2;
42 listen 127.0.0.1:8081;
43 server_name localhost;
44
45 client_header_buffer_size 1k;
46 client_body_buffer_size 2k;
47
48 location / {
49 add_header X-Body $request_body;
50 add_header X-Body-File $request_body_file;
51 proxy_pass http://127.0.0.1:8082;
52 }
53
54 location /file {
55 client_body_in_file_only on;
56 add_header X-Body "$request_body";
57 add_header X-Body-File "$request_body_file";
58 proxy_pass http://127.0.0.1:8082;
59 }
60
61 location /single {
62 client_body_in_single_buffer on;
63 add_header X-Body "$request_body";
64 add_header X-Body-File "$request_body_file";
65 proxy_pass http://127.0.0.1:8082;
66 }
67
68 location /large {
69 client_max_body_size 1k;
70 proxy_pass http://127.0.0.1:8082;
71 }
72
73 location /unbuf/ {
74 add_header X-Unbuf-File "$request_body_file";
75 proxy_pass http://127.0.0.1:8081/;
76 proxy_request_buffering off;
77 proxy_http_version 1.1;
78 }
79 }
80
81 server {
82 listen 127.0.0.1:8082;
83 server_name localhost;
84 return 204;
85 }
86 }
87
88 EOF
89
90 plan(skip_all => 'not yet') unless $t->has_version('1.21.2');
91 $t->plan(50);
92
93 $t->run();
94
95 ###############################################################################
96
97 # below are basic body tests from body.t, slightly
98 # adapted to HTTP/2, repeated multiple times with variations:
99 #
100 # buffered vs. non-buffered, length vs. chunked,
101 # single frame vs. multiple frames
102 #
103 # some does not make sense in HTTP/2 (such as "body in two buffers"), but
104 # preserved for consistency and due to the fact that proxying via HTTP/1.1
105 # is used in unbuffered tests
106
107 unlike(http2_get('/'), qr/x-body:/ms, 'no body');
108
109 like(http2_get_body('/', '0123456789'),
110 qr/x-body: 0123456789$/ms, 'body');
111 like(http2_get_body('/', '0123456789' x 128),
112 qr/x-body: (0123456789){128}$/ms, 'body in two buffers');
113 like(http2_get_body('/', '0123456789' x 512),
114 qr/x-body-file/ms, 'body in file');
115 like(read_body_file(http2_get_body('/file', '0123456789' x 512)),
116 qr/^(0123456789){512}$/s, 'body in file only');
117 like(http2_get_body('/single', '0123456789' x 128),
118 qr/x-body: (0123456789){128}$/ms, 'body in single buffer');
119 like(http2_get_body('/large', '0123456789' x 128),
120 qr/:status: 413/, 'body too large');
121
122 # without Content-Length header
123
124 like(http2_get_body_nolen('/', '0123456789'),
125 qr/x-body: 0123456789$/ms, 'body nolen');
126 like(http2_get_body_nolen('/', '0123456789' x 128),
127 qr/x-body: (0123456789){128}$/ms, 'body nolen in two buffers');
128 like(http2_get_body_nolen('/', '0123456789' x 512),
129 qr/x-body-file/ms, 'body nolen in file');
130 like(read_body_file(http2_get_body_nolen('/file', '0123456789' x 512)),
131 qr/^(0123456789){512}$/s, 'body nolen in file only');
132 like(http2_get_body_nolen('/single', '0123456789' x 128),
133 qr/x-body: (0123456789){128}$/ms, 'body nolen in single buffer');
134 like(http2_get_body_nolen('/large', '0123456789' x 128),
135 qr/:status: 413/, 'body nolen too large');
136
137 # with multiple frames
138
139 like(http2_get_body_multi('/', '0123456789'),
140 qr/x-body: 0123456789$/ms, 'body multi');
141 like(http2_get_body_multi('/', '0123456789' x 128),
142 qr/x-body: (0123456789){128}$/ms, 'body multi in two buffers');
143 like(http2_get_body_multi('/', '0123456789' x 512),
144 qr/x-body-file/ms, 'body multi in file');
145 like(read_body_file(http2_get_body_multi('/file', '0123456789' x 512)),
146 qr/^(0123456789){512}$/s, 'body multi in file only');
147 like(http2_get_body_multi('/single', '0123456789' x 128),
148 qr/x-body: (0123456789){128}$/ms, 'body multi in single buffer');
149 like(http2_get_body_multi('/large', '0123456789' x 128),
150 qr/:status: 413/, 'body multi too large');
151
152 # with multiple frames and without Content-Length header
153
154 like(http2_get_body_multi_nolen('/', '0123456789'),
155 qr/x-body: 0123456789$/ms, 'body multi nolen');
156 like(http2_get_body_multi_nolen('/', '0123456789' x 128),
157 qr/x-body: (0123456789){128}/ms, 'body multi nolen in two buffers');
158 like(http2_get_body_multi_nolen('/', '0123456789' x 512),
159 qr/x-body-file/ms, 'body multi nolen in file');
160 like(read_body_file(http2_get_body_multi_nolen('/file', '0123456789' x 512)),
161 qr/^(0123456789){512}$/s, 'body multi nolen in file only');
162 like(http2_get_body_multi_nolen('/single', '0123456789' x 128),
163 qr/x-body: (0123456789){128}$/ms, 'body multi nolen in single buffer');
164 like(http2_get_body_multi_nolen('/large', '0123456789' x 128),
165 qr/:status: 413/, 'body multi nolen too large');
166
167 # unbuffered
168
169 unlike(http2_get('/unbuf/'), qr/x-body:/ms, 'no body unbuf');
170
171 like(http2_get_body('/unbuf/', '0123456789'),
172 qr/x-body: 0123456789$/ms, 'body unbuf');
173 like(http2_get_body('/unbuf/', '0123456789' x 128),
174 qr/x-body: (0123456789){128}$/ms, 'body unbuf in two buffers');
175 like(http2_get_body('/unbuf/', '0123456789' x 512),
176 qr/(?!.*x-unbuf-file.*)x-body-file/ms, 'body unbuf in file');
177 like(read_body_file(http2_get_body('/unbuf/file', '0123456789' x 512)),
178 qr/^(0123456789){512}$/s, 'body unbuf in file only');
179 like(http2_get_body('/unbuf/single', '0123456789' x 128),
180 qr/x-body: (0123456789){128}$/ms, 'body unbuf in single buffer');
181 like(http2_get_body('/unbuf/large', '0123456789' x 128),
182 qr/:status: 413/, 'body unbuf too large');
183
184 # unbuffered without Content-Length
185
186 like(http2_get_body_nolen('/unbuf/', '0123456789'),
187 qr/x-body: 0123456789$/ms, 'body unbuf nolen');
188 like(http2_get_body_nolen('/unbuf/', '0123456789' x 128),
189 qr/x-body: (0123456789){128}$/ms, 'body unbuf nolen in two buffers');
190 like(http2_get_body_nolen('/unbuf/', '0123456789' x 512),
191 qr/(?!.*x-unbuf-file.*)x-body-file/ms, 'body unbuf nolen in file');
192 like(read_body_file(http2_get_body_nolen('/unbuf/file', '0123456789' x 512)),
193 qr/^(0123456789){512}$/s, 'body unbuf nolen in file only');
194 like(http2_get_body_nolen('/unbuf/single', '0123456789' x 128),
195 qr/x-body: (0123456789){128}$/ms, 'body unbuf nolen in single buffer');
196 like(http2_get_body_nolen('/unbuf/large', '0123456789' x 128),
197 qr/:status: 413/, 'body unbuf nolen too large');
198
199 # unbuffered with multiple frames
200
201 like(http2_get_body_multi('/unbuf/', '0123456789'),
202 qr/x-body: 0123456789$/ms, 'body unbuf multi');
203 like(http2_get_body_multi('/unbuf/', '0123456789' x 128),
204 qr/x-body: (0123456789){128}$/ms, 'body unbuf multi in two buffers');
205 like(http2_get_body_multi('/unbuf/', '0123456789' x 512),
206 qr/(?!.*x-unbuf-file.*)x-body-file/ms, 'body unbuf multi in file');
207 like(read_body_file(http2_get_body_multi('/unbuf/file', '0123456789' x 512)),
208 qr/^(0123456789){512}$/s, 'body unbuf multi in file only');
209 like(http2_get_body_multi('/unbuf/single', '0123456789' x 128),
210 qr/x-body: (0123456789){128}$/ms, 'body unbuf multi in single buffer');
211 like(http2_get_body_multi('/unbuf/large', '0123456789' x 128),
212 qr/:status: 413/, 'body unbuf multi too large');
213
214 # unbuffered with multiple frames and without Content-Length
215
216 like(http2_get_body_multi_nolen('/unbuf/', '0123456789'),
217 qr/x-body: 0123456789$/ms, 'body unbuf multi nolen');
218 like(http2_get_body_multi_nolen('/unbuf/', '0123456789' x 128),
219 qr/x-body: (0123456789){128}$/ms,
220 'body unbuf multi nolen in two buffers');
221 like(http2_get_body_multi_nolen('/unbuf/', '0123456789' x 512),
222 qr/(?!.*x-unbuf-file.*)x-body-file/ms,
223 'body unbuf multi nolen in file');
224 like(read_body_file(http2_get_body_multi_nolen('/unbuf/file',
225 '0123456789' x 512)), qr/^(0123456789){512}$/s,
226 'body unbuf multi nolen in file only');
227 like(http2_get_body_multi_nolen('/unbuf/single', '0123456789' x 128),
228 qr/x-body: (0123456789){128}$/ms,
229 'body unbuf multi nolen in single buffer');
230 like(http2_get_body_multi_nolen('/unbuf/large', '0123456789' x 128),
231 qr/:status: 413/, 'body unbuf multi nolen too large');
232
233 ###############################################################################
234
235 sub http2_get {
236 my ($uri) = @_;
237
238 my $s = Test::Nginx::HTTP2->new();
239 my $sid = $s->new_stream({ path => $uri });
240 my $frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
241
242 my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
243
244 return join("\n", map { "$_: " . $frame->{headers}->{$_}; }
245 keys %{$frame->{headers}});
246 }
247
248 sub http2_get_body {
249 my ($uri, $body) = @_;
250
251 my $s = Test::Nginx::HTTP2->new();
252 my $sid = $s->new_stream({ path => $uri, body => $body });
253 my $frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
254
255 my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
256
257 return join("\n", map { "$_: " . $frame->{headers}->{$_}; }
258 keys %{$frame->{headers}});
259 }
260
261 sub http2_get_body_nolen {
262 my ($uri, $body) = @_;
263
264 my $s = Test::Nginx::HTTP2->new();
265 my $sid = $s->new_stream({ path => $uri, body_more => 1 });
266 $s->h2_body($body);
267 my $frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
268
269 my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
270
271 return join("\n", map { "$_: " . $frame->{headers}->{$_}; }
272 keys %{$frame->{headers}});
273 }
274
275 sub http2_get_body_multi {
276 my ($uri, $body) = @_;
277
278 my $s = Test::Nginx::HTTP2->new();
279 my $sid = $s->new_stream({
280 headers => [
281 { name => ':method', value => 'GET' },
282 { name => ':scheme', value => 'http' },
283 { name => ':path', value => $uri },
284 { name => ':authority', value => 'localhost' },
285 { name => 'content-length', value => length $body },
286 ],
287 body_more => 1
288 });
289 for my $b (split //, $body, 10) {
290 $s->h2_body($b, { body_more => 1 });
291 }
292 select undef, undef, undef, 0.1;
293 $s->h2_body('');
294 my $frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
295
296 my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
297
298 return join("\n", map { "$_: " . $frame->{headers}->{$_}; }
299 keys %{$frame->{headers}});
300 }
301
302 sub http2_get_body_multi_nolen {
303 my ($uri, $body) = @_;
304
305 my $s = Test::Nginx::HTTP2->new();
306 my $sid = $s->new_stream({ path => $uri, body_more => 1 });
307 for my $b (split //, $body, 10) {
308 $s->h2_body($b, { body_more => 1 });
309 }
310 select undef, undef, undef, 0.1;
311 $s->h2_body('');
312 my $frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
313
314 my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
315
316 return join("\n", map { "$_: " . $frame->{headers}->{$_}; }
317 keys %{$frame->{headers}});
318 }
319
320 sub read_body_file {
321 my ($r) = @_;
322 return '' unless $r =~ m/x-body-file: (.*)/;
323 open FILE, $1
324 or return "$!";
325 local $/;
326 my $content = <FILE>;
327 close FILE;
328 return $content;
329 }
330
331 ###############################################################################