Mercurial > hg > nginx-tests
annotate h2.t @ 680:85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Tue, 08 Sep 2015 15:12:23 +0300 |
parents | b60c1a207675 |
children | 96666f621dbc |
rev | line source |
---|---|
646 | 1 #!/usr/bin/perl |
2 | |
3 # (C) Sergey Kandaurov | |
4 # (C) Nginx, Inc. | |
5 | |
6 # Tests for HTTP/2 protocol [RFC7540]. | |
7 | |
8 ############################################################################### | |
9 | |
10 use warnings; | |
11 use strict; | |
12 | |
13 use Test::More; | |
14 | |
15 use IO::Select; | |
16 use Socket qw/ CRLF /; | |
17 | |
18 BEGIN { use FindBin; chdir($FindBin::Bin); } | |
19 | |
20 use lib 'lib'; | |
21 use Test::Nginx; | |
22 | |
23 ############################################################################### | |
24 | |
25 select STDERR; $| = 1; | |
26 select STDOUT; $| = 1; | |
27 | |
650
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
28 eval { require IO::Socket::SSL; }; |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
29 plan(skip_all => 'IO::Socket::SSL not installed') if $@; |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
30 eval { IO::Socket::SSL::SSL_VERIFY_NONE(); }; |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
31 plan(skip_all => 'IO::Socket::SSL too old') if $@; |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
32 |
646 | 33 my $t = Test::Nginx->new()->has(qw/http http_ssl http_v2 proxy cache/) |
650
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
34 ->has(qw/limit_conn rewrite realip shmem/) |
680
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
35 ->has_daemon('openssl')->plan(170); |
646 | 36 |
37 $t->write_file_expand('nginx.conf', <<'EOF'); | |
38 | |
39 %%TEST_GLOBALS%% | |
40 | |
41 daemon off; | |
42 | |
43 events { | |
44 } | |
45 | |
46 http { | |
47 %%TEST_GLOBALS_HTTP%% | |
48 | |
49 proxy_cache_path %%TESTDIR%%/cache keys_zone=NAME:1m; | |
50 limit_conn_zone $binary_remote_addr zone=conn:1m; | |
51 output_buffers 2 16k; | |
52 | |
53 server { | |
54 listen 127.0.0.1:8080 http2; | |
55 listen 127.0.0.1:8081; | |
56 listen 127.0.0.1:8082 proxy_protocol http2; | |
57 listen 127.0.0.1:8084 http2 ssl; | |
58 server_name localhost; | |
59 | |
60 ssl_certificate_key localhost.key; | |
61 ssl_certificate localhost.crt; | |
62 | |
63 location / { | |
64 add_header X-Header X-Foo; | |
65 add_header X-Sent-Foo $http_x_foo; | |
66 add_header X-Referer $http_referer; | |
67 return 200 'body'; | |
68 } | |
69 location /t { | |
70 } | |
71 location /t3.html { | |
72 limit_conn conn 1; | |
73 } | |
74 location /gzip.html { | |
75 gzip on; | |
76 gzip_min_length 0; | |
77 alias %%TESTDIR%%/t2.html; | |
78 } | |
680
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
79 location /frame_size { |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
80 http2_chunk_size 64k; |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
81 alias %%TESTDIR%%/t1.html; |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
82 output_buffers 2 1m; |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
83 } |
646 | 84 location /pp { |
85 set_real_ip_from 127.0.0.1/32; | |
86 real_ip_header proxy_protocol; | |
87 alias %%TESTDIR%%/t2.html; | |
88 add_header X-PP $remote_addr; | |
89 } | |
650
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
90 location /h2 { |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
91 return 200 $http2; |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
92 } |
651
9f66f0029dca
Tests: HTTP/2 tests for http2_chunk_size directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
650
diff
changeset
|
93 location /chunk_size { |
9f66f0029dca
Tests: HTTP/2 tests for http2_chunk_size directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
650
diff
changeset
|
94 http2_chunk_size 1; |
9f66f0029dca
Tests: HTTP/2 tests for http2_chunk_size directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
650
diff
changeset
|
95 return 200 'body'; |
9f66f0029dca
Tests: HTTP/2 tests for http2_chunk_size directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
650
diff
changeset
|
96 } |
646 | 97 location /redirect { |
98 error_page 405 /; | |
99 return 405; | |
100 } | |
101 location /return301 { | |
102 return 301; | |
103 } | |
104 location /return301_absolute { | |
105 return 301 text; | |
106 } | |
107 location /return301_relative { | |
108 return 301 /; | |
109 } | |
110 location /proxy/ { | |
111 add_header X-UC-a $upstream_cookie_a; | |
112 add_header X-UC-c $upstream_cookie_c; | |
113 proxy_pass http://127.0.0.1:8083/; | |
114 proxy_cache NAME; | |
115 proxy_cache_valid 1m; | |
652
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
116 proxy_set_header X-Cookie-a $cookie_a; |
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
117 proxy_set_header X-Cookie-c $cookie_c; |
646 | 118 } |
119 location /proxy2/ { | |
120 add_header X-Body "$request_body"; | |
121 proxy_pass http://127.0.0.1:8081/; | |
122 proxy_cache NAME; | |
123 proxy_cache_valid 1m; | |
124 } | |
125 location /proxy_buffering_off { | |
126 proxy_pass http://127.0.0.1:8081/; | |
127 proxy_cache NAME; | |
128 proxy_cache_valid 1m; | |
129 proxy_buffering off; | |
130 } | |
131 location /set-cookie { | |
132 add_header Set-Cookie a=b; | |
133 add_header Set-Cookie c=d; | |
134 return 200; | |
135 } | |
136 location /cookie { | |
137 add_header X-Cookie $http_cookie; | |
138 add_header X-Cookie-a $cookie_a; | |
139 add_header X-Cookie-c $cookie_c; | |
140 return 200; | |
141 } | |
142 } | |
143 | |
144 server { | |
145 listen 127.0.0.1:8085 http2; | |
146 server_name localhost; | |
147 return 200 first; | |
148 } | |
149 | |
150 server { | |
151 listen 127.0.0.1:8085 http2; | |
152 server_name localhost2; | |
153 return 200 second; | |
154 } | |
654
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
155 |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
156 server { |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
157 listen 127.0.0.1:8086 http2; |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
158 server_name localhost; |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
159 |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
160 http2_max_concurrent_streams 1; |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
161 } |
646 | 162 } |
163 | |
164 EOF | |
165 | |
166 $t->write_file('openssl.conf', <<EOF); | |
167 [ req ] | |
168 default_bits = 2048 | |
169 encrypt_key = no | |
170 distinguished_name = req_distinguished_name | |
171 [ req_distinguished_name ] | |
172 EOF | |
173 | |
174 my $d = $t->testdir(); | |
175 | |
176 foreach my $name ('localhost') { | |
177 system('openssl req -x509 -new ' | |
178 . "-config '$d/openssl.conf' -subj '/CN=$name/' " | |
179 . "-out '$d/$name.crt' -keyout '$d/$name.key' " | |
180 . ">>$d/openssl.out 2>&1") == 0 | |
181 or die "Can't create certificate for $name: $!\n"; | |
182 } | |
183 | |
184 $t->run_daemon(\&http_daemon); | |
185 $t->run()->waitforsocket('127.0.0.1:8083'); | |
186 | |
187 # file size is slightly beyond initial window size: 2**16 + 80 bytes | |
188 | |
189 $t->write_file('t1.html', | |
190 join('', map { sprintf "X%04dXXX", $_ } (1 .. 8202))); | |
191 $t->write_file('tbig.html', | |
192 join('', map { sprintf "X%04dXXX", $_ } (1 .. 8202))); | |
193 | |
194 $t->write_file('t2.html', 'SEE-THIS'); | |
195 $t->write_file('t3.html', 'SEE-THIS'); | |
196 | |
197 my %cframe = ( | |
198 0 => { name => 'DATA', value => \&data }, | |
199 1 => { name => 'HEADERS', value => \&headers }, | |
200 # 2 => { name => 'PRIORITY', value => \&priority }, | |
201 3 => { name => 'RST_STREAM', value => \&rst_stream }, | |
202 4 => { name => 'SETTINGS', value => \&settings }, | |
203 # 5 => { name => 'PUSH_PROIMSE', value => \&push_promise }, | |
204 6 => { name => 'PING', value => \&ping }, | |
205 7 => { name => 'GOAWAY', value => \&goaway }, | |
206 8 => { name => 'WINDOW_UPDATE', value => \&window_update }, | |
207 # 9 => { name => 'CONTINUATION', value => \&continuation }, | |
208 ); | |
209 | |
210 ############################################################################### | |
211 | |
212 # SETTINGS | |
213 | |
214 my $sess = new_session(); | |
215 my $frames = h2_read($sess, all => [ | |
216 { type => 'WINDOW_UPDATE' }, | |
217 { type => 'SETTINGS'} | |
218 ]); | |
219 | |
220 my ($frame) = grep { $_->{type} eq 'WINDOW_UPDATE' } @$frames; | |
221 ok($frame, 'WINDOW_UPDATE frame'); | |
222 is($frame->{flags}, 0, 'WINDOW_UPDATE zero flags'); | |
223 is($frame->{sid}, 0, 'WINDOW_UPDATE zero sid'); | |
224 is($frame->{length}, 4, 'WINDOW_UPDATE fixed length'); | |
225 | |
226 ($frame) = grep { $_->{type} eq 'SETTINGS' } @$frames; | |
227 ok($frame, 'SETTINGS frame'); | |
228 is($frame->{flags}, 0, 'SETTINGS flags'); | |
655
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
229 is($frame->{sid}, 0, 'SETTINGS stream'); |
646 | 230 |
231 h2_settings($sess, 1); | |
232 h2_settings($sess, 0); | |
233 | |
234 $frames = h2_read($sess, all => [{ type => 'SETTINGS' }]); | |
235 | |
236 ($frame) = grep { $_->{type} eq 'SETTINGS' } @$frames; | |
237 ok($frame, 'SETTINGS frame ack'); | |
238 is($frame->{flags}, 1, 'SETTINGS flags ack'); | |
239 | |
240 # PING | |
241 | |
242 h2_ping($sess, 'SEE-THIS'); | |
243 $frames = h2_read($sess, all => [{ type => 'PING' }]); | |
244 | |
245 ($frame) = grep { $_->{type} eq "PING" } @$frames; | |
246 ok($frame, 'PING frame'); | |
247 is($frame->{value}, 'SEE-THIS', 'PING payload'); | |
248 is($frame->{flags}, 1, 'PING flags ack'); | |
655
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
249 is($frame->{sid}, 0, 'PING stream'); |
646 | 250 |
251 # GET | |
252 | |
253 my $sid = new_stream($sess); | |
254 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
255 | |
256 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
257 ok($frame, 'HEADERS frame'); | |
258 is($frame->{sid}, $sid, 'HEADERS stream'); | |
259 is($frame->{headers}->{':status'}, 200, 'HEADERS status'); | |
260 is($frame->{headers}->{'x-header'}, 'X-Foo', 'HEADERS header'); | |
261 | |
262 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
263 ok($frame, 'DATA frame'); | |
264 is($frame->{length}, length 'body', 'DATA length'); | |
265 is($frame->{data}, 'body', 'DATA payload'); | |
266 | |
267 # GET in the new stream on same connection | |
268 | |
269 $sid = new_stream($sess); | |
270 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
271 | |
272 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
273 is($frame->{sid}, $sid, 'HEADERS stream 2'); | |
274 is($frame->{headers}->{':status'}, 200, 'HEADERS status 2'); | |
275 is($frame->{headers}->{'x-header'}, 'X-Foo', 'HEADERS header 2'); | |
276 | |
277 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
278 ok($frame, 'DATA frame 2'); | |
279 is($frame->{sid}, $sid, 'HEADERS stream 2'); | |
280 is($frame->{length}, length 'body', 'DATA length 2'); | |
281 is($frame->{data}, 'body', 'DATA payload 2'); | |
282 | |
283 # various HEADERS compression/encoding, see hpack() for mode details | |
284 | |
285 # 6.1. Indexed Header Field Representation | |
286 | |
287 $sid = new_stream($sess, { headers => [ | |
288 { name => ':method', value => 'GET', mode => 0 }, | |
289 { name => ':scheme', value => 'http', mode => 0 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
290 { name => ':path', value => '/', mode => 0 }, |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
291 { name => ':authority', value => 'localhost', mode => 1 }]}); |
646 | 292 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
293 | |
294 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
295 is($frame->{headers}->{':status'}, 200, 'indexed header field'); | |
296 | |
297 # 6.2.1. Literal Header Field with Incremental Indexing | |
298 | |
299 $sid = new_stream($sess, { headers => [ | |
300 { name => ':method', value => 'GET', mode => 1, huff => 0 }, | |
301 { name => ':scheme', value => 'http', mode => 1, huff => 0 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
302 { name => ':path', value => '/', mode => 1, huff => 0 }, |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
303 { name => ':authority', value => 'localhost', mode => 1, huff => 0 }]}); |
646 | 304 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
305 | |
306 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
307 is($frame->{headers}->{':status'}, 200, 'literal with indexing'); | |
308 | |
309 $sid = new_stream($sess, { headers => [ | |
310 { name => ':method', value => 'GET', mode => 1, huff => 1 }, | |
311 { name => ':scheme', value => 'http', mode => 1, huff => 1 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
312 { name => ':path', value => '/', mode => 1, huff => 1 }, |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
313 { name => ':authority', value => 'localhost', mode => 1, huff => 1 }]}); |
646 | 314 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
315 | |
316 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
317 is($frame->{headers}->{':status'}, 200, 'literal with indexing - huffman'); | |
318 | |
319 # 6.2.1. Literal Header Field with Incremental Indexing -- New Name | |
320 | |
321 $sid = new_stream($sess, { headers => [ | |
322 { name => ':method', value => 'GET', mode => 2, huff => 0 }, | |
323 { name => ':scheme', value => 'http', mode => 2, huff => 0 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
324 { name => ':path', value => '/', mode => 2, huff => 0 }, |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
325 { name => ':authority', value => 'localhost', mode => 2, huff => 0 }]}); |
646 | 326 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
327 | |
328 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
329 is($frame->{headers}->{':status'}, 200, 'literal with indexing - new'); | |
330 | |
331 $sid = new_stream($sess, { headers => [ | |
332 { name => ':method', value => 'GET', mode => 2, huff => 1 }, | |
333 { name => ':scheme', value => 'http', mode => 2, huff => 1 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
334 { name => ':path', value => '/', mode => 2, huff => 1 }, |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
335 { name => ':authority', value => 'localhost', mode => 2, huff => 1 }]}); |
646 | 336 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
337 | |
338 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
339 is($frame->{headers}->{':status'}, 200, 'literal with indexing - new huffman'); | |
340 | |
341 # 6.2.2. Literal Header Field without Indexing | |
342 | |
343 $sid = new_stream($sess, { headers => [ | |
344 { name => ':method', value => 'GET', mode => 3, huff => 0 }, | |
345 { name => ':scheme', value => 'http', mode => 3, huff => 0 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
346 { name => ':path', value => '/', mode => 3, huff => 0 }, |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
347 { name => ':authority', value => 'localhost', mode => 3, huff => 0 }]}); |
646 | 348 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
349 | |
350 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
351 is($frame->{headers}->{':status'}, 200, 'literal without indexing'); | |
352 | |
353 $sid = new_stream($sess, { headers => [ | |
354 { name => ':method', value => 'GET', mode => 3, huff => 1 }, | |
355 { name => ':scheme', value => 'http', mode => 3, huff => 1 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
356 { name => ':path', value => '/', mode => 3, huff => 1 }, |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
357 { name => ':authority', value => 'localhost', mode => 3, huff => 1 }]}); |
646 | 358 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
359 | |
360 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
361 is($frame->{headers}->{':status'}, 200, 'literal without indexing - huffman'); | |
362 | |
363 # 6.2.2. Literal Header Field without Indexing -- New Name | |
364 | |
365 $sid = new_stream($sess, { headers => [ | |
366 { name => ':method', value => 'GET', mode => 4, huff => 0 }, | |
367 { name => ':scheme', value => 'http', mode => 4, huff => 0 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
368 { name => ':path', value => '/', mode => 4, huff => 0 }, |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
369 { name => ':authority', value => 'localhost', mode => 4, huff => 0 }]}); |
646 | 370 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
371 | |
372 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
373 is($frame->{headers}->{':status'}, 200, 'literal without indexing - new'); | |
374 | |
375 $sid = new_stream($sess, { headers => [ | |
376 { name => ':method', value => 'GET', mode => 4, huff => 1 }, | |
377 { name => ':scheme', value => 'http', mode => 4, huff => 1 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
378 { name => ':path', value => '/', mode => 4, huff => 1 }, |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
379 { name => ':authority', value => 'localhost', mode => 4, huff => 1 }]}); |
646 | 380 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
381 | |
382 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
383 is($frame->{headers}->{':status'}, 200, 'literal without indexing - new huffman'); | |
384 | |
385 # 6.2.3. Literal Header Field Never Indexed | |
386 | |
387 $sid = new_stream($sess, { headers => [ | |
388 { name => ':method', value => 'GET', mode => 5, huff => 0 }, | |
389 { name => ':scheme', value => 'http', mode => 5, huff => 0 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
390 { name => ':path', value => '/', mode => 5, huff => 0 }, |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
391 { name => ':authority', value => 'localhost', mode => 5, huff => 0 }]}); |
646 | 392 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
393 | |
394 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
395 is($frame->{headers}->{':status'}, 200, 'literal never indexed'); | |
396 | |
397 $sid = new_stream($sess, { headers => [ | |
398 { name => ':method', value => 'GET', mode => 5, huff => 1 }, | |
399 { name => ':scheme', value => 'http', mode => 5, huff => 1 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
400 { name => ':path', value => '/', mode => 5, huff => 1 }, |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
401 { name => ':authority', value => 'localhost', mode => 5, huff => 1 }]}); |
646 | 402 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
403 | |
404 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
405 is($frame->{headers}->{':status'}, 200, 'literal never indexed - huffman'); | |
406 | |
407 # 6.2.2. Literal Header Field Never Indexed -- New Name | |
408 | |
409 $sid = new_stream($sess, { headers => [ | |
410 { name => ':method', value => 'GET', mode => 6, huff => 0 }, | |
411 { name => ':scheme', value => 'http', mode => 6, huff => 0 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
412 { name => ':path', value => '/', mode => 6, huff => 0 }, |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
413 { name => ':authority', value => 'localhost', mode => 6, huff => 0 }]}); |
646 | 414 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
415 | |
416 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
417 is($frame->{headers}->{':status'}, 200, 'literal never indexed - new'); | |
418 | |
419 $sid = new_stream($sess, { headers => [ | |
420 { name => ':method', value => 'GET', mode => 6, huff => 1 }, | |
421 { name => ':scheme', value => 'http', mode => 6, huff => 1 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
422 { name => ':path', value => '/', mode => 6, huff => 1 }, |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
423 { name => ':authority', value => 'localhost', mode => 6, huff => 1 }]}); |
646 | 424 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
425 | |
426 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
427 is($frame->{headers}->{':status'}, 200, 'literal never indexed - new huffman'); | |
428 | |
429 # reuse literal with indexing | |
430 | |
431 $sess = new_session(); | |
432 $sid = new_stream($sess, { headers => [ | |
433 { name => ':method', value => 'GET', mode => 0 }, | |
434 { name => ':scheme', value => 'http', mode => 0 }, | |
435 { name => ':path', value => '/', mode => 0 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
436 { name => ':authority', value => 'localhost', mode => 1 }, |
646 | 437 { name => 'referer', value => 'foo', mode => 1 }]}); |
438 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
439 | |
440 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
441 is($frame->{headers}->{'x-referer'}, 'foo', 'value with indexing - new'); | |
442 | |
443 $sid = new_stream($sess, { headers => [ | |
444 { name => ':method', value => 'GET', mode => 0 }, | |
445 { name => ':scheme', value => 'http', mode => 0 }, | |
446 { name => ':path', value => '/', mode => 0 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
447 { name => ':authority', value => 'localhost', mode => 0 }, |
646 | 448 { name => 'referer', value => 'foo', mode => 0 }]}); |
449 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
450 | |
451 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
452 is($frame->{headers}->{'x-referer'}, 'foo', 'value with indexing - indexed'); | |
453 | |
454 $sid = new_stream($sess, { headers => [ | |
455 { name => ':method', value => 'GET', mode => 0 }, | |
456 { name => ':scheme', value => 'http', mode => 0 }, | |
457 { name => ':path', value => '/', mode => 0 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
458 { name => ':authority', value => 'localhost', mode => 0 }, |
646 | 459 { name => 'x-foo', value => 'X-Bar', mode => 2 }]}); |
460 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
461 | |
462 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
463 is($frame->{headers}->{'x-sent-foo'}, 'X-Bar', 'name with indexing - new'); | |
464 | |
465 # reuse literal with indexing - reused name | |
466 | |
467 $sid = new_stream($sess, { headers => [ | |
468 { name => ':method', value => 'GET', mode => 0 }, | |
469 { name => ':scheme', value => 'http', mode => 0 }, | |
470 { name => ':path', value => '/', mode => 0 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
471 { name => ':authority', value => 'localhost', mode => 0 }, |
646 | 472 { name => 'x-foo', value => 'X-Bar', mode => 0 }]}); |
473 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
474 | |
475 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
476 is($frame->{headers}->{'x-sent-foo'}, 'X-Bar', 'name with indexing - indexed'); | |
477 | |
478 # 6.3. Dynamic Table Size Update | |
479 | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
480 # remove some indexed headers from the dynamic table |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
481 # by maintaining dynamic table space only for index 0 |
646 | 482 # 'x-foo' has index 0, and 'referer' has index 1 |
483 | |
484 $sid = new_stream($sess, { table_size => 61, headers => [ | |
485 { name => ':method', value => 'GET', mode => 0 }, | |
486 { name => ':scheme', value => 'http', mode => 0 }, | |
487 { name => ':path', value => '/', mode => 0 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
488 { name => 'x-foo', value => 'X-Bar', mode => 0 }, |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
489 { name => ':authority', value => 'localhost', mode => 1 }]}); |
646 | 490 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
491 | |
492 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
493 isnt($frame, undef, 'updated table size - remaining index'); | |
494 | |
495 $sid = new_stream($sess, { headers => [ | |
496 { name => ':method', value => 'GET', mode => 0 }, | |
497 { name => ':scheme', value => 'http', mode => 0 }, | |
498 { name => ':path', value => '/', mode => 0 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
499 { name => ':authority', value => 'localhost', mode => 1 }, |
646 | 500 { name => 'referer', value => 'foo', mode => 0 }]}); |
501 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
502 | |
503 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
672
66f94d6c5047
Tests: more HTTP/2 error handling tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
671
diff
changeset
|
504 is($frame, undef, 'invalid index'); |
646 | 505 |
506 # 5.4.1. Connection Error Handling | |
507 # An endpoint that encounters a connection error SHOULD first send a | |
508 # GOAWAY frame <..> | |
509 | |
510 TODO: { | |
511 local $TODO = 'not yet'; | |
512 | |
513 ($frame) = grep { $_->{type} eq "GOAWAY" } @$frames; | |
672
66f94d6c5047
Tests: more HTTP/2 error handling tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
671
diff
changeset
|
514 ok($frame, 'invalid index - GOAWAY'); |
646 | 515 |
516 } | |
517 | |
672
66f94d6c5047
Tests: more HTTP/2 error handling tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
671
diff
changeset
|
518 h2_ping($sess, 'SEE-THIS'); |
66f94d6c5047
Tests: more HTTP/2 error handling tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
671
diff
changeset
|
519 is(@{h2_read($sess, all => [{ type => 'PING' }])}, 0, 'invalid index - PING'); |
66f94d6c5047
Tests: more HTTP/2 error handling tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
671
diff
changeset
|
520 is($sess->{socket}->connected, undef, 'invalid index - connection close'); |
66f94d6c5047
Tests: more HTTP/2 error handling tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
671
diff
changeset
|
521 |
646 | 522 # HEAD |
523 | |
524 $sess = new_session(); | |
525 $sid = new_stream($sess, { method => 'HEAD' }); | |
526 $frames = h2_read($sess, all => [{ sid => $sid, fin => 0x4 }]); | |
527 | |
528 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
529 is($frame->{sid}, $sid, 'HEAD - HEADERS'); | |
530 is($frame->{headers}->{':status'}, 200, 'HEAD - HEADERS status'); | |
531 is($frame->{headers}->{'x-header'}, 'X-Foo', 'HEAD - HEADERS header'); | |
532 | |
533 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
534 is($frame, undef, 'HEAD - no body'); | |
535 | |
536 # GET with PROXY protocol | |
537 | |
538 my $proxy = 'PROXY TCP4 192.0.2.1 192.0.2.2 1234 5678' . CRLF; | |
539 $sess = new_session(8082, proxy => $proxy); | |
540 $sid = new_stream($sess, { path => '/pp' }); | |
541 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
542 | |
543 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
544 ok($frame, 'PROXY HEADERS frame'); | |
545 is($frame->{headers}->{'x-pp'}, '192.0.2.1', 'PROXY remote addr'); | |
546 | |
547 # range filter | |
548 | |
549 $sess = new_session(); | |
550 $sid = new_stream($sess, { headers => [ | |
551 { name => ':method', value => 'GET', mode => 0 }, | |
552 { name => ':scheme', value => 'http', mode => 0 }, | |
553 { name => ':path', value => '/t1.html', mode => 1 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
554 { name => ':authority', value => 'localhost', mode => 1 }, |
646 | 555 { name => 'range', value => 'bytes=10-19', mode => 1 }]}); |
556 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
557 | |
558 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
559 is($frame->{headers}->{':status'}, 206, 'range - HEADERS status'); | |
560 | |
561 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
562 is($frame->{length}, 10, 'range - DATA length'); | |
563 is($frame->{data}, '002XXXX000', 'range - DATA payload'); | |
564 | |
650
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
565 # $http2 |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
566 |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
567 $sess = new_session(); |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
568 $sid = new_stream($sess, { path => '/h2' }); |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
569 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
570 |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
571 ($frame) = grep { $_->{type} eq "DATA" } @$frames; |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
572 is($frame->{data}, 'h2c', 'http variable - h2c'); |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
573 |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
574 # SSL/TLS connection, NPN |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
575 |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
576 SKIP: { |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
577 eval { IO::Socket::SSL->can_npn() or die; }; |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
578 skip 'OpenSSL NPN support required', 1 if $@; |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
579 |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
580 $sess = new_session(8084, SSL => 1, npn => 'h2'); |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
581 $sid = new_stream($sess, { path => '/h2' }); |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
582 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
583 |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
584 ($frame) = grep { $_->{type} eq "DATA" } @$frames; |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
585 is($frame->{data}, 'h2', 'http variable - npn'); |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
586 |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
587 } |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
588 |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
589 # SSL/TLS connection, ALPN |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
590 |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
591 SKIP: { |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
592 eval { IO::Socket::SSL->can_alpn() or die; }; |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
593 skip 'OpenSSL ALPN support required', 1 if $@; |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
594 |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
595 $sess = new_session(8084, SSL => 1, alpn => 'h2'); |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
596 $sid = new_stream($sess, { path => '/h2' }); |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
597 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
598 |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
599 ($frame) = grep { $_->{type} eq "DATA" } @$frames; |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
600 is($frame->{data}, 'h2', 'http variable - alpn'); |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
601 |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
602 } |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
603 |
651
9f66f0029dca
Tests: HTTP/2 tests for http2_chunk_size directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
650
diff
changeset
|
604 # http2_chunk_size=1 |
9f66f0029dca
Tests: HTTP/2 tests for http2_chunk_size directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
650
diff
changeset
|
605 |
9f66f0029dca
Tests: HTTP/2 tests for http2_chunk_size directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
650
diff
changeset
|
606 $sess = new_session(); |
9f66f0029dca
Tests: HTTP/2 tests for http2_chunk_size directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
650
diff
changeset
|
607 $sid = new_stream($sess, { path => '/chunk_size' }); |
9f66f0029dca
Tests: HTTP/2 tests for http2_chunk_size directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
650
diff
changeset
|
608 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
9f66f0029dca
Tests: HTTP/2 tests for http2_chunk_size directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
650
diff
changeset
|
609 |
9f66f0029dca
Tests: HTTP/2 tests for http2_chunk_size directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
650
diff
changeset
|
610 my @data = grep { $_->{type} eq "DATA" } @$frames; |
9f66f0029dca
Tests: HTTP/2 tests for http2_chunk_size directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
650
diff
changeset
|
611 is(@data, 4, 'chunk_size frames'); |
9f66f0029dca
Tests: HTTP/2 tests for http2_chunk_size directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
650
diff
changeset
|
612 is(join(' ', map { $_->{data} } @data), 'b o d y', 'chunk_size data'); |
9f66f0029dca
Tests: HTTP/2 tests for http2_chunk_size directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
650
diff
changeset
|
613 is(join(' ', map { $_->{flags} } @data), '0 0 0 1', 'chunk_size flags'); |
9f66f0029dca
Tests: HTTP/2 tests for http2_chunk_size directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
650
diff
changeset
|
614 |
646 | 615 # CONTINUATION |
616 | |
650
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
617 $sess = new_session(); |
646 | 618 $sid = new_stream($sess, { continuation => 1, headers => [ |
619 { name => ':method', value => 'HEAD', mode => 1 }, | |
620 { name => ':scheme', value => 'http', mode => 0 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
621 { name => ':path', value => '/', mode => 0 }, |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
622 { name => ':authority', value => 'localhost', mode => 1 }]}); |
646 | 623 h2_continue($sess, $sid, { continuation => 1, headers => [ |
624 { name => 'x-foo', value => 'X-Bar', mode => 2 }]}); | |
625 h2_continue($sess, $sid, { headers => [ | |
626 { name => 'referer', value => 'foo', mode => 2 }]}); | |
627 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
628 | |
629 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
630 is($frame, undef, 'CONTINUATION - fragment 1'); | |
631 | |
632 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
633 is($frame->{headers}->{'x-sent-foo'}, 'X-Bar', 'CONTINUATION - fragment 2'); | |
634 is($frame->{headers}->{'x-referer'}, 'foo', 'CONTINUATION - fragment 3'); | |
635 | |
636 # frame padding | |
637 | |
638 $sess = new_session(); | |
639 $sid = new_stream($sess, { padding => 42, headers => [ | |
640 { name => ':method', value => 'GET', mode => 0 }, | |
641 { name => ':scheme', value => 'http', mode => 0 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
642 { name => ':path', value => '/', mode => 0 }, |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
643 { name => ':authority', value => 'localhost', mode => 1 }]}); |
646 | 644 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
645 | |
646 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
647 is($frame->{headers}->{':status'}, 200, 'padding - HEADERS status'); | |
648 | |
649 $sid = new_stream($sess, { headers => [ | |
650 { name => ':method', value => 'GET', mode => 0 }, | |
651 { name => ':scheme', value => 'http', mode => 0 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
652 { name => ':path', value => '/', mode => 0 }, |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
653 { name => ':authority', value => 'localhost', mode => 1 }]}); |
646 | 654 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
655 | |
656 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
657 is($frame->{headers}->{':status'}, 200, 'padding - next stream'); | |
658 | |
659 # request header field with multiple values | |
660 | |
661 # 8.1.2.5. Compressing the Cookie Header Field | |
662 # To allow for better compression efficiency, the Cookie header field | |
663 # MAY be split into separate header fields <..>. | |
664 | |
665 $sess = new_session(); | |
666 $sid = new_stream($sess, { headers => [ | |
667 { name => ':method', value => 'GET', mode => 0 }, | |
668 { name => ':scheme', value => 'http', mode => 0 }, | |
669 { name => ':path', value => '/cookie', mode => 2 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
670 { name => ':authority', value => 'localhost', mode => 1 }, |
646 | 671 { name => 'cookie', value => 'a=b', mode => 2}, |
672 { name => 'cookie', value => 'c=d', mode => 2}]}); | |
673 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
674 | |
675 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
676 is($frame->{headers}->{'x-cookie-a'}, 'b', | |
677 'multiple request header fields - cookie'); | |
678 is($frame->{headers}->{'x-cookie-c'}, 'd', | |
679 'multiple request header fields - cookie 2'); | |
680 is($frame->{headers}->{'x-cookie'}, 'a=b; c=d', | |
681 'multiple request header fields - semi-colon'); | |
682 | |
683 # request header field with multiple values to HTTP backend | |
684 | |
685 # 8.1.2.5. Compressing the Cookie Header Field | |
686 # these MUST be concatenated into a single octet string | |
687 # using the two-octet delimiter of 0x3B, 0x20 (the ASCII string "; ") | |
688 # before being passed into a non-HTTP/2 context, such as an HTTP/1.1 | |
689 # connection <..> | |
690 | |
691 $sess = new_session(); | |
692 $sid = new_stream($sess, { headers => [ | |
693 { name => ':method', value => 'GET', mode => 0 }, | |
694 { name => ':scheme', value => 'http', mode => 0 }, | |
695 { name => ':path', value => '/proxy/cookie', mode => 2 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
696 { name => ':authority', value => 'localhost', mode => 1 }, |
646 | 697 { name => 'cookie', value => 'a=b', mode => 2 }, |
698 { name => 'cookie', value => 'c=d', mode => 2 }]}); | |
699 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
700 | |
701 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
652
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
702 is($frame->{headers}->{'x-sent-cookie'}, 'a=b; c=d', |
646 | 703 'multiple request header fields proxied - semi-colon'); |
652
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
704 is($frame->{headers}->{'x-sent-cookie2'}, '', |
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
705 'multiple request header fields proxied - dublicate cookie'); |
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
706 is($frame->{headers}->{'x-sent-cookie-a'}, 'b', |
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
707 'multiple request header fields proxied - cookie 1'); |
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
708 is($frame->{headers}->{'x-sent-cookie-c'}, 'd', |
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
709 'multiple request header fields proxied - cookie 2'); |
646 | 710 |
711 # response header field with multiple values | |
712 | |
713 $sess = new_session(); | |
714 $sid = new_stream($sess, { path => '/set-cookie' }); | |
715 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
716 | |
717 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
718 is($frame->{headers}->{'set-cookie'}[0], 'a=b', | |
719 'multiple response header fields - cookie'); | |
720 is($frame->{headers}->{'set-cookie'}[1], 'c=d', | |
721 'multiple response header fields - cookie 2'); | |
722 | |
723 # response header field with multiple values from HTTP backend | |
724 | |
725 $sess = new_session(); | |
726 $sid = new_stream($sess, { path => '/proxy/set-cookie' }); | |
727 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
728 | |
729 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
730 is($frame->{headers}->{'set-cookie'}[0], 'a=b', | |
731 'multiple response header proxied - cookie'); | |
732 is($frame->{headers}->{'set-cookie'}[1], 'c=d', | |
733 'multiple response header proxied - cookie 2'); | |
734 is($frame->{headers}->{'x-uc-a'}, 'b', | |
735 'multiple response header proxied - upstream cookie'); | |
736 is($frame->{headers}->{'x-uc-c'}, 'd', | |
737 'multiple response header proxied - upstream cookie 2'); | |
738 | |
739 # internal redirect | |
740 | |
741 $sess = new_session(); | |
742 $sid = new_stream($sess, { path => '/redirect' }); | |
743 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
744 | |
745 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
746 is($frame->{headers}->{':status'}, 405, 'redirect - HEADERS'); | |
747 | |
748 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
749 ok($frame, 'redirect - DATA'); | |
750 is($frame->{data}, 'body', 'redirect - DATA payload'); | |
751 | |
752 # return 301 with absolute URI | |
753 | |
754 $sess = new_session(); | |
755 $sid = new_stream($sess, { path => '/return301_absolute' }); | |
756 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
757 | |
758 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
759 is($frame->{headers}->{':status'}, 301, 'return 301 absolute - status'); | |
760 is($frame->{headers}->{'location'}, 'text', 'return 301 absolute - location'); | |
761 | |
762 # return 301 with relative URI | |
763 | |
764 $sess = new_session(); | |
765 $sid = new_stream($sess, { path => '/return301_relative' }); | |
766 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
767 | |
768 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
769 is($frame->{headers}->{':status'}, 301, 'return 301 relative - status'); | |
770 is($frame->{headers}->{'location'}, 'http://127.0.0.1:8080/', | |
771 'return 301 relative - location'); | |
772 | |
773 # return 301 with relative URI and ':authority' request header field | |
774 | |
775 $sess = new_session(); | |
776 $sid = new_stream($sess, { headers => [ | |
777 { name => ':method', value => 'GET', mode => 0 }, | |
778 { name => ':scheme', value => 'http', mode => 0 }, | |
779 { name => ':path', value => '/return301_relative', mode => 2 }, | |
780 { name => ':authority', value => 'localhost', mode => 2 }]}); | |
781 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
782 | |
783 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
784 is($frame->{headers}->{':status'}, 301, | |
785 'return 301 relative - authority - status'); | |
786 is($frame->{headers}->{'location'}, 'http://localhost:8080/', | |
787 'return 301 relative - authority - location'); | |
788 | |
789 # return 301 with relative URI and 'host' request header field | |
790 | |
791 $sess = new_session(); | |
792 $sid = new_stream($sess, { headers => [ | |
793 { name => ':method', value => 'GET', mode => 0 }, | |
794 { name => ':scheme', value => 'http', mode => 0 }, | |
795 { name => ':path', value => '/return301_relative', mode => 2 }, | |
796 { name => 'host', value => 'localhost', mode => 2 }]}); | |
797 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
798 | |
799 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
800 is($frame->{headers}->{':status'}, 301, | |
801 'return 301 relative - host - status'); | |
802 is($frame->{headers}->{'location'}, 'http://localhost:8080/', | |
803 'return 301 relative - host - location'); | |
804 | |
805 # virtual host | |
806 | |
807 $sess = new_session(8085); | |
808 $sid = new_stream($sess, { headers => [ | |
809 { name => ':method', value => 'GET', mode => 0 }, | |
810 { name => ':scheme', value => 'http', mode => 0 }, | |
811 { name => ':path', value => '/', mode => 0 }, | |
812 { name => 'host', value => 'localhost', mode => 2 }]}); | |
813 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
814 | |
815 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
816 is($frame->{headers}->{':status'}, 200, | |
817 'virtual host - host - status'); | |
818 | |
819 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
820 is($frame->{data}, 'first', 'virtual host - host - DATA'); | |
821 | |
822 $sid = new_stream($sess, { headers => [ | |
823 { name => ':method', value => 'GET', mode => 0 }, | |
824 { name => ':scheme', value => 'http', mode => 0 }, | |
825 { name => ':path', value => '/', mode => 0 }, | |
826 { name => ':authority', value => 'localhost', mode => 2 }]}); | |
827 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
828 | |
829 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
830 is($frame->{headers}->{':status'}, 200, | |
831 'virtual host - authority - status'); | |
832 | |
833 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
834 is($frame->{data}, 'first', 'virtual host - authority - DATA'); | |
835 | |
836 # virtual host - second | |
837 | |
838 $sid = new_stream($sess, { headers => [ | |
839 { name => ':method', value => 'GET', mode => 0 }, | |
840 { name => ':scheme', value => 'http', mode => 0 }, | |
841 { name => ':path', value => '/', mode => 0 }, | |
842 { name => 'host', value => 'localhost2', mode => 2 }]}); | |
843 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
844 | |
845 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
846 is($frame->{headers}->{':status'}, 200, | |
847 'virtual host 2 - host - status'); | |
848 | |
849 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
850 is($frame->{data}, 'second', 'virtual host 2 - host - DATA'); | |
851 | |
852 $sid = new_stream($sess, { headers => [ | |
853 { name => ':method', value => 'GET', mode => 0 }, | |
854 { name => ':scheme', value => 'http', mode => 0 }, | |
855 { name => ':path', value => '/', mode => 0 }, | |
856 { name => ':authority', value => 'localhost2', mode => 2 }]}); | |
857 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
858 | |
859 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
860 is($frame->{headers}->{':status'}, 200, | |
861 'virtual host 2 - authority - status'); | |
862 | |
863 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
864 is($frame->{data}, 'second', 'virtual host 2 - authority - DATA'); | |
865 | |
866 # gzip tests for internal nginx version | |
867 | |
868 $sess = new_session(); | |
869 $sid = new_stream($sess, { headers => [ | |
870 { name => ':method', value => 'GET', mode => 0 }, | |
871 { name => ':scheme', value => 'http', mode => 0 }, | |
872 { name => ':path', value => '/gzip.html' }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
873 { name => ':authority', value => 'localhost', mode => 1 }, |
646 | 874 { name => 'accept-encoding', value => 'gzip' }]}); |
875 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
876 | |
877 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
878 is($frame->{headers}->{'content-encoding'}, 'gzip', 'gzip - encoding'); | |
879 | |
880 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
647
4e36550410b3
Tests: h2.t fixes for older perl versions, and gzip test.
Sergey Kandaurov <pluknet@nginx.com>
parents:
646
diff
changeset
|
881 gunzip_like($frame->{data}, qr/^SEE-THIS\Z/, 'gzip - DATA'); |
646 | 882 |
883 # simple proxy cache test | |
884 | |
885 $sess = new_session(); | |
886 $sid = new_stream($sess, { path => '/proxy2/t2.html?2' }); | |
887 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
888 | |
889 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
890 is($frame->{headers}->{':status'}, '200', 'proxy cache'); | |
891 | |
892 my $etag = $frame->{headers}->{'etag'}; | |
893 | |
894 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
895 is($frame->{length}, length 'SEE-THIS', 'proxy cache - DATA'); | |
896 is($frame->{data}, 'SEE-THIS', 'proxy cache - DATA payload'); | |
897 | |
898 $sid = new_stream($sess, { headers => [ | |
899 { name => ':method', value => 'GET', mode => 0 }, | |
900 { name => ':scheme', value => 'http', mode => 0 }, | |
901 { name => ':path', value => '/proxy2/t2.html?2' }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
902 { name => ':authority', value => 'localhost', mode => 1 }, |
646 | 903 { name => 'if-none-match', value => $etag }]}); |
904 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
905 | |
906 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
907 is($frame->{headers}->{':status'}, 304, 'proxy cache conditional'); | |
908 | |
909 # HEADERS could be received with fin, followed by DATA | |
910 | |
911 $sess = new_session(); | |
912 $sid = new_stream($sess, { path => '/proxy2/t2.html', method => 'HEAD' }); | |
913 | |
914 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
915 push @$frames, $_ for @{h2_read($sess, all => [{ sid => $sid }])}; | |
916 ok(!grep ({ $_->{type} eq "DATA" } @$frames), 'proxy cache HEAD - no body'); | |
917 | |
918 # HEAD on empty cache with proxy_buffering off | |
919 | |
920 $sess = new_session(); | |
921 $sid = new_stream($sess, | |
922 { path => '/proxy_buffering_off/t2.html?1', method => 'HEAD' }); | |
923 | |
924 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
925 push @$frames, $_ for @{h2_read($sess, all => [{ sid => $sid }])}; | |
926 ok(!grep ({ $_->{type} eq "DATA" } @$frames), | |
927 'proxy cache HEAD buffering off - no body'); | |
928 | |
929 # request body (uses proxied response) | |
930 | |
931 $sess = new_session(); | |
932 $sid = new_stream($sess, { path => '/proxy2/t2.html', body => 'TEST' }); | |
933 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
934 | |
935 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
936 is($frame->{headers}->{'x-body'}, 'TEST', 'request body'); | |
937 | |
938 # request body with padding (uses proxied response) | |
939 | |
940 $sess = new_session(); | |
941 $sid = new_stream($sess, | |
942 { path => '/proxy2/t2.html', body => 'TEST', body_padding => 42 }); | |
943 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
944 | |
945 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
946 is($frame->{headers}->{'x-body'}, 'TEST', 'request body with padding'); | |
947 | |
948 $sid = new_stream($sess); | |
949 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
950 | |
951 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
952 is($frame->{headers}->{':status'}, '200', 'request body with padding - next'); | |
953 | |
954 # initial window size, client side | |
955 | |
956 # 6.9.2. Initial Flow-Control Window Size | |
957 # When an HTTP/2 connection is first established, new streams are | |
958 # created with an initial flow-control window size of 65,535 octets. | |
959 # The connection flow-control window is also 65,535 octets. | |
960 | |
961 $sess = new_session(); | |
962 $sid = new_stream($sess, { path => '/t1.html' }); | |
963 $frames = h2_read($sess, all => [{ sid => $sid, length => 2**16 - 1 }]); | |
964 | |
965 # with the default http2_chunk_size, data is divided into 8 data frames | |
966 | |
651
9f66f0029dca
Tests: HTTP/2 tests for http2_chunk_size directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
650
diff
changeset
|
967 @data = grep { $_->{type} eq "DATA" } @$frames; |
646 | 968 my $lengths = join ' ', map { $_->{length} } @data; |
969 is($lengths, '8192 8192 8192 8192 8192 8192 8192 8191', | |
970 'iws - stream blocked on initial window size'); | |
971 | |
972 h2_ping($sess, 'SEE-THIS'); | |
973 $frames = h2_read($sess, all => [{ type => 'PING' }]); | |
974 | |
975 ($frame) = grep { $_->{type} eq "PING" && $_->{flags} & 0x1 } @$frames; | |
976 ok($frame, 'iws - PING not blocked'); | |
977 | |
978 h2_window($sess, 2**16, $sid); | |
979 $frames = h2_read($sess); | |
980 is(@$frames, 0, 'iws - updated stream window'); | |
981 | |
982 h2_window($sess, 2**16); | |
983 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
984 | |
985 # with the default output_buffers, the remain data would be split | |
986 # on buffers boundary into separate data frames | |
987 | |
988 @data = grep { $_->{type} eq "DATA" } @$frames; | |
989 my $sum = eval join '+', map { $_->{length} } @data; | |
990 is($sum, 81, 'iws - updated connection window'); | |
991 | |
992 # SETTINGS (initial window size, client side) | |
993 | |
994 # 6.9.2. Initial Flow-Control Window Size | |
995 # Both endpoints can adjust the initial window size for new streams by | |
996 # including a value for SETTINGS_INITIAL_WINDOW_SIZE in the SETTINGS | |
997 # frame that forms part of the connection preface. The connection | |
998 # flow-control window can only be changed using WINDOW_UPDATE frames. | |
999 | |
1000 $sess = new_session(); | |
1001 h2_settings($sess, 0, 0x4 => 2**17); | |
1002 h2_window($sess, 2**17); | |
1003 | |
1004 $sid = new_stream($sess, { path => '/t1.html' }); | |
1005 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
1006 | |
1007 @data = grep { $_->{type} eq "DATA" } @$frames; | |
1008 $sum = eval join '+', map { $_->{length} } @data; | |
1009 is($sum, 2**16 + 80, 'iws - increased'); | |
1010 | |
1011 # probe for negative available space in a flow control window | |
1012 | |
1013 # 6.9.2. Initial Flow-Control Window Size | |
1014 # A change to SETTINGS_INITIAL_WINDOW_SIZE can cause the available | |
1015 # space in a flow-control window to become negative. A sender MUST | |
1016 # track the negative flow-control window and MUST NOT send new flow- | |
1017 # controlled frames until it receives WINDOW_UPDATE frames that cause | |
1018 # the flow-control window to become positive. | |
1019 | |
1020 $sess = new_session(); | |
1021 $sid = new_stream($sess, { path => '/t1.html' }); | |
1022 h2_read($sess, all => [{ sid => $sid, length => 2**16 - 1 }]); | |
1023 | |
1024 h2_window($sess, 1); | |
1025 h2_settings($sess, 0, 0x4 => 42); | |
1026 h2_window($sess, 1024, $sid); | |
1027 | |
1028 $frames = h2_read($sess, all => [{ type => 'SETTINGS' }]); | |
1029 | |
1030 ($frame) = grep { $_->{type} eq 'SETTINGS' } @$frames; | |
1031 ok($frame, 'negative window - SETTINGS frame ack'); | |
1032 is($frame->{flags}, 1, 'negative window - SETTINGS flags ack'); | |
1033 | |
1034 ($frame) = grep { $_->{type} ne 'SETTINGS' } @$frames; | |
1035 is($frame, undef, 'negative window - no data'); | |
1036 | |
1037 # predefined window size, minus new iws settings, minus window update | |
1038 | |
1039 h2_window($sess, 2**16 - 1 - 42 - 1024, $sid); | |
1040 | |
1041 $frames = h2_read($sess); | |
1042 is(@$frames, 0, 'zero window - no data'); | |
1043 | |
1044 h2_window($sess, 1, $sid); | |
1045 | |
1046 $frames = h2_read($sess, all => [{ sid => $sid, length => 1 }]); | |
1047 is(@$frames, 1, 'positive window'); | |
1048 is(@$frames[0]->{type}, 'DATA', 'positive window - data'); | |
1049 is(@$frames[0]->{length}, 1, 'positive window - data length'); | |
1050 | |
680
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1051 # SETTINGS_MAX_FRAME_SIZE |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1052 |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1053 $sess = new_session(); |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1054 $sid = new_stream($sess, { path => '/frame_size' }); |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1055 h2_window($sess, 2**18, 1); |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1056 h2_window($sess, 2**18); |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1057 |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1058 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1059 @data = grep { $_->{type} eq "DATA" } @$frames; |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1060 is($data[0]->{length}, 2**14, 'max frame size - default'); |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1061 |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1062 $sess = new_session(); |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1063 h2_settings($sess, 0, 0x5 => 2**15); |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1064 $sid = new_stream($sess, { path => '/frame_size' }); |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1065 h2_window($sess, 2**18, 1); |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1066 h2_window($sess, 2**18); |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1067 |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1068 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1069 @data = grep { $_->{type} eq "DATA" } @$frames; |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1070 is($data[0]->{length}, 2**15, 'max frame size - custom'); |
85e368105c8b
Tests: added HTTP/2 tests for SETTINGS_MAX_FRAME_SIZE.
Sergey Kandaurov <pluknet@nginx.com>
parents:
679
diff
changeset
|
1071 |
646 | 1072 # stream multiplexing + WINDOW_UPDATE |
1073 | |
1074 $sess = new_session(); | |
1075 $sid = new_stream($sess, { path => '/t1.html' }); | |
1076 $frames = h2_read($sess, all => [{ sid => $sid, length => 2**16 - 1 }]); | |
1077 | |
1078 @data = grep { $_->{type} eq "DATA" } @$frames; | |
1079 $sum = eval join '+', map { $_->{length} } @data; | |
1080 is($sum, 2**16 - 1, 'multiple - stream1 data'); | |
1081 | |
1082 my $sid2 = new_stream($sess, { path => '/t1.html' }); | |
1083 $frames = h2_read($sess, all => [{ sid => $sid2, fin => 0x4 }]); | |
1084 | |
1085 @data = grep { $_->{type} eq "DATA" } @$frames; | |
1086 is(@data, 0, 'multiple - stream2 no data'); | |
1087 | |
1088 h2_window($sess, 2**17, $sid); | |
1089 h2_window($sess, 2**17, $sid2); | |
1090 h2_window($sess, 2**17); | |
1091 | |
1092 $frames = h2_read($sess, all => [ | |
1093 { sid => $sid, fin => 1 }, | |
1094 { sid => $sid2, fin => 1 } | |
1095 ]); | |
1096 | |
1097 @data = grep { $_->{type} eq "DATA" && $_->{sid} == $sid } @$frames; | |
1098 $sum = eval join '+', map { $_->{length} } @data; | |
1099 is($sum, 81, 'multiple - stream1 remain data'); | |
1100 | |
1101 @data = grep { $_->{type} eq "DATA" && $_->{sid} == $sid2 } @$frames; | |
1102 $sum = eval join '+', map { $_->{length} } @data; | |
1103 is($sum, 2**16 + 80, 'multiple - stream2 full data'); | |
1104 | |
1105 # stream muliplexing + PRIORITY frames | |
1106 | |
1107 $sess = new_session(); | |
1108 $sid = new_stream($sess, { path => '/t1.html' }); | |
1109 h2_read($sess, all => [{ sid => $sid, length => 2**16 - 1 }]); | |
1110 | |
1111 $sid2 = new_stream($sess, { path => '/t2.html' }); | |
1112 h2_read($sess, all => [{ sid => $sid2, fin => 0x4 }]); | |
1113 | |
1114 h2_priority($sess, 0, $sid); | |
1115 h2_priority($sess, 255, $sid2); | |
1116 | |
1117 h2_window($sess, 2**17, $sid); | |
1118 h2_window($sess, 2**17, $sid2); | |
1119 h2_window($sess, 2**17); | |
1120 | |
1121 $frames = h2_read($sess, all => [ | |
1122 { sid => $sid, fin => 1 }, | |
1123 { sid => $sid2, fin => 1 } | |
1124 ]); | |
1125 | |
1126 @data = grep { $_->{type} eq "DATA" } @$frames; | |
1127 is(join(' ', map { $_->{sid} } @data), "$sid2 $sid", 'weight - PRIORITY 1'); | |
1128 | |
1129 # and vice versa | |
1130 | |
1131 $sess = new_session(); | |
1132 $sid = new_stream($sess, { path => '/t1.html' }); | |
1133 h2_read($sess, all => [{ sid => $sid, length => 2**16 - 1 }]); | |
1134 | |
1135 $sid2 = new_stream($sess, { path => '/t2.html' }); | |
1136 h2_read($sess, all => [{ sid => $sid2, fin => 0x4 }]); | |
1137 | |
1138 h2_priority($sess, 255, $sid); | |
1139 h2_priority($sess, 0, $sid2); | |
1140 | |
1141 h2_window($sess, 2**17, $sid); | |
1142 h2_window($sess, 2**17, $sid2); | |
1143 h2_window($sess, 2**17); | |
1144 | |
1145 $frames = h2_read($sess, all => [ | |
1146 { sid => $sid, fin => 1 }, | |
1147 { sid => $sid2, fin => 1 } | |
1148 ]); | |
1149 | |
1150 @data = grep { $_->{type} eq "DATA" } @$frames; | |
1151 is(join(' ', map { $_->{sid} } @data), "$sid $sid2", 'weight - PRIORITY 2'); | |
1152 | |
1153 # stream muliplexing + HEADERS PRIORITY flag | |
1154 | |
1155 $sess = new_session(); | |
1156 $sid = new_stream($sess, { path => '/t1.html', prio => 0 }); | |
1157 h2_read($sess, all => [{ sid => $sid, length => 2**16 - 1 }]); | |
1158 | |
1159 $sid2 = new_stream($sess, { path => '/t2.html', prio => 255 }); | |
1160 h2_read($sess, all => [{ sid => $sid2, fin => 0x4 }]); | |
1161 | |
1162 h2_window($sess, 2**17, $sid); | |
1163 h2_window($sess, 2**17, $sid2); | |
1164 h2_window($sess, 2**17); | |
1165 | |
1166 $frames = h2_read($sess, all => [ | |
1167 { sid => $sid, fin => 1 }, | |
1168 { sid => $sid2, fin => 1 } | |
1169 ]); | |
1170 | |
1171 @data = grep { $_->{type} eq "DATA" } @$frames; | |
1172 my $sids = join ' ', map { $_->{sid} } @data; | |
1173 is($sids, "$sid2 $sid", 'weight - HEADERS PRIORITY 1'); | |
1174 | |
1175 # and vice versa | |
1176 | |
1177 $sess = new_session(); | |
1178 $sid = new_stream($sess, { path => '/t1.html', prio => 255 }); | |
1179 h2_read($sess, all => [{ sid => $sid, length => 2**16 - 1 }]); | |
1180 | |
1181 $sid2 = new_stream($sess, { path => '/t2.html', prio => 0 }); | |
1182 h2_read($sess, all => [{ sid => $sid2, fin => 0x4 }]); | |
1183 | |
1184 h2_window($sess, 2**17, $sid); | |
1185 h2_window($sess, 2**17, $sid2); | |
1186 h2_window($sess, 2**17); | |
1187 | |
1188 $frames = h2_read($sess, all => [ | |
1189 { sid => $sid, fin => 1 }, | |
1190 { sid => $sid2, fin => 1 } | |
1191 ]); | |
1192 | |
1193 @data = grep { $_->{type} eq "DATA" } @$frames; | |
1194 $sids = join ' ', map { $_->{sid} } @data; | |
1195 is($sids, "$sid $sid2", 'weight - HEADERS PRIORITY 2'); | |
1196 | |
1197 # 5.3.1. Stream Dependencies | |
1198 | |
1199 # PRIORITY frame | |
1200 | |
1201 $sess = new_session(); | |
1202 | |
1203 h2_priority($sess, 16, 3, 0); | |
1204 h2_priority($sess, 16, 1, 3); | |
1205 | |
1206 $sid = new_stream($sess, { path => '/t1.html' }); | |
1207 h2_read($sess, all => [{ sid => $sid, length => 2**16 - 1 }]); | |
1208 | |
1209 $sid2 = new_stream($sess, { path => '/t2.html' }); | |
1210 h2_read($sess, all => [{ sid => $sid2, fin => 0x4 }]); | |
1211 | |
1212 h2_window($sess, 2**17, $sid); | |
1213 h2_window($sess, 2**17, $sid2); | |
1214 h2_window($sess, 2**17); | |
1215 | |
1216 $frames = h2_read($sess, all => [ | |
1217 { sid => $sid, fin => 1 }, | |
1218 { sid => $sid2, fin => 1 }, | |
1219 ]); | |
1220 | |
1221 @data = grep { $_->{type} eq "DATA" } @$frames; | |
1222 $sids = join ' ', map { $_->{sid} } @data; | |
1223 is($sids, "$sid2 $sid", 'dependency - PRIORITY 1'); | |
1224 | |
1225 # and vice versa | |
1226 | |
1227 $sess = new_session(); | |
1228 | |
1229 h2_priority($sess, 16, 1, 0); | |
1230 h2_priority($sess, 16, 3, 1); | |
1231 | |
1232 $sid = new_stream($sess, { path => '/t1.html' }); | |
1233 h2_read($sess, all => [{ sid => $sid, length => 2**16 - 1 }]); | |
1234 | |
1235 $sid2 = new_stream($sess, { path => '/t2.html' }); | |
1236 h2_read($sess, all => [{ sid => $sid2, fin => 0x4 }]); | |
1237 | |
1238 h2_window($sess, 2**17, $sid); | |
1239 h2_window($sess, 2**17, $sid2); | |
1240 h2_window($sess, 2**17); | |
1241 | |
1242 $frames = h2_read($sess, all => [ | |
1243 { sid => $sid, fin => 1 }, | |
1244 { sid => $sid2, fin => 1 }, | |
1245 ]); | |
1246 | |
1247 @data = grep { $_->{type} eq "DATA" } @$frames; | |
1248 $sids = join ' ', map { $_->{sid} } @data; | |
1249 is($sids, "$sid $sid2", 'dependency - PRIORITY 2'); | |
1250 | |
1251 # HEADERS PRIORITY flag, reprioritize prior PRIORITY frame records | |
1252 | |
1253 $sess = new_session(); | |
1254 | |
1255 h2_priority($sess, 16, 1, 0); | |
1256 h2_priority($sess, 16, 3, 0); | |
1257 | |
1258 $sid = new_stream($sess, { path => '/t1.html', dep => 3 }); | |
1259 h2_read($sess, all => [{ sid => $sid, length => 2**16 - 1 }]); | |
1260 | |
1261 $sid2 = new_stream($sess, { path => '/t2.html' }); | |
1262 h2_read($sess, all => [{ sid => $sid2, fin => 0x4 }]); | |
1263 | |
1264 h2_window($sess, 2**17, $sid); | |
1265 h2_window($sess, 2**17, $sid2); | |
1266 h2_window($sess, 2**17); | |
1267 | |
1268 $frames = h2_read($sess, all => [ | |
1269 { sid => $sid, fin => 1 }, | |
1270 { sid => $sid2, fin => 1 }, | |
1271 ]); | |
1272 | |
1273 @data = grep { $_->{type} eq "DATA" } @$frames; | |
1274 $sids = join ' ', map { $_->{sid} } @data; | |
1275 is($sids, "$sid2 $sid", 'dependency - HEADERS PRIORITY 1'); | |
1276 | |
1277 # and vice versa | |
1278 | |
1279 $sess = new_session(); | |
1280 | |
1281 h2_priority($sess, 16, 1, 0); | |
1282 h2_priority($sess, 16, 3, 0); | |
1283 | |
1284 $sid = new_stream($sess, { path => '/t1.html' }); | |
1285 h2_read($sess, all => [{ sid => $sid, length => 2**16 - 1 }]); | |
1286 | |
1287 $sid2 = new_stream($sess, { path => '/t2.html', dep => 1 }); | |
1288 h2_read($sess, all => [{ sid => $sid2, fin => 0x4 }]); | |
1289 | |
1290 h2_window($sess, 2**17, $sid); | |
1291 h2_window($sess, 2**17, $sid2); | |
1292 h2_window($sess, 2**17); | |
1293 | |
1294 $frames = h2_read($sess, all => [ | |
1295 { sid => $sid, fin => 1 }, | |
1296 { sid => $sid2, fin => 1 }, | |
1297 ]); | |
1298 | |
1299 @data = grep { $_->{type} eq "DATA" } @$frames; | |
1300 $sids = join ' ', map { $_->{sid} } @data; | |
1301 is($sids, "$sid $sid2", 'dependency - HEADERS PRIORITY 2'); | |
1302 | |
662
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1303 # PRIORITY frame, weighted dependencies |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1304 |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1305 $sess = new_session(); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1306 |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1307 h2_priority($sess, 16, 5, 0); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1308 h2_priority($sess, 255, 1, 5); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1309 h2_priority($sess, 0, 3, 5); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1310 |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1311 $sid = new_stream($sess, { path => '/t1.html' }); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1312 h2_read($sess, all => [{ sid => $sid, length => 2**16 - 1 }]); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1313 |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1314 $sid2 = new_stream($sess, { path => '/t2.html' }); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1315 h2_read($sess, all => [{ sid => $sid2, fin => 0x4 }]); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1316 |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1317 my $sid3 = new_stream($sess, { path => '/t2.html' }); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1318 h2_read($sess, all => [{ sid => $sid2, fin => 0x4 }]); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1319 |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1320 h2_window($sess, 2**16, 1); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1321 h2_window($sess, 2**16, 3); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1322 h2_window($sess, 2**16, 5); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1323 h2_window($sess, 2**16); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1324 |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1325 $frames = h2_read($sess, all => [ |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1326 { sid => $sid, fin => 1 }, |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1327 { sid => $sid2, fin => 1 }, |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1328 { sid => $sid3, fin => 1 }, |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1329 ]); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1330 |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1331 @data = grep { $_->{type} eq "DATA" } @$frames; |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1332 $sids = join ' ', map { $_->{sid} } @data; |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1333 is($sids, "$sid3 $sid $sid2", 'weighted dependency - PRIORITY 1'); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1334 |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1335 # and vice versa |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1336 |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1337 $sess = new_session(); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1338 |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1339 h2_priority($sess, 16, 5, 0); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1340 h2_priority($sess, 0, 1, 5); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1341 h2_priority($sess, 255, 3, 5); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1342 |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1343 $sid = new_stream($sess, { path => '/t1.html' }); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1344 h2_read($sess, all => [{ sid => $sid, length => 2**16 - 1 }]); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1345 |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1346 $sid2 = new_stream($sess, { path => '/t2.html' }); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1347 h2_read($sess, all => [{ sid => $sid2, fin => 0x4 }]); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1348 |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1349 $sid3 = new_stream($sess, { path => '/t2.html' }); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1350 h2_read($sess, all => [{ sid => $sid2, fin => 0x4 }]); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1351 |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1352 h2_window($sess, 2**16, 1); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1353 h2_window($sess, 2**16, 3); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1354 h2_window($sess, 2**16, 5); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1355 h2_window($sess, 2**16); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1356 |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1357 $frames = h2_read($sess, all => [ |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1358 { sid => $sid, fin => 1 }, |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1359 { sid => $sid2, fin => 1 }, |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1360 { sid => $sid3, fin => 1 }, |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1361 ]); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1362 |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1363 @data = grep { $_->{type} eq "DATA" } @$frames; |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1364 $sids = join ' ', map { $_->{sid} } @data; |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1365 is($sids, "$sid3 $sid2 $sid", 'weighted dependency - PRIORITY 2'); |
07de3d202eb7
Tests: more HTTP/2 tests for streams priority.
Sergey Kandaurov <pluknet@nginx.com>
parents:
661
diff
changeset
|
1366 |
646 | 1367 # limit_conn |
1368 | |
1369 $sess = new_session(); | |
1370 h2_settings($sess, 0, 0x4 => 1); | |
1371 | |
1372 $sid = new_stream($sess, { path => '/t3.html' }); | |
1373 $frames = h2_read($sess, all => [{ sid => $sid, length => 1 }]); | |
1374 | |
1375 ($frame) = grep { $_->{type} eq "HEADERS" && $_->{sid} == $sid } @$frames; | |
1376 is($frame->{headers}->{':status'}, 200, 'limit_conn first stream'); | |
1377 | |
1378 $sid2 = new_stream($sess, { path => '/t3.html' }); | |
1379 $frames = h2_read($sess, all => [{ sid => $sid2, fin => 0 }]); | |
1380 | |
1381 ($frame) = grep { $_->{type} eq "HEADERS" && $_->{sid} == $sid2 } @$frames; | |
1382 is($frame->{headers}->{':status'}, 503, 'limit_conn rejected'); | |
1383 | |
1384 h2_settings($sess, 0, 0x4 => 2**16); | |
1385 | |
1386 h2_read($sess, all => [ | |
1387 { sid => $sid, fin => 1 }, | |
1388 { sid => $sid2, fin => 1 } | |
1389 ]); | |
1390 | |
1391 # limit_conn + client's RST_STREAM | |
1392 | |
1393 $sess = new_session(); | |
1394 h2_settings($sess, 0, 0x4 => 1); | |
1395 | |
1396 $sid = new_stream($sess, { path => '/t3.html' }); | |
1397 $frames = h2_read($sess, all => [{ sid => $sid, length => 1 }]); | |
1398 h2_rst($sess, $sid, 5); | |
1399 | |
1400 ($frame) = grep { $_->{type} eq "HEADERS" && $_->{sid} == $sid } @$frames; | |
1401 is($frame->{headers}->{':status'}, 200, 'RST_STREAM 1'); | |
1402 | |
1403 $sid2 = new_stream($sess, { path => '/t3.html' }); | |
1404 $frames = h2_read($sess, all => [{ sid => $sid2, fin => 0 }]); | |
1405 | |
1406 ($frame) = grep { $_->{type} eq "HEADERS" && $_->{sid} == $sid2 } @$frames; | |
1407 is($frame->{headers}->{':status'}, 200, 'RST_STREAM 2'); | |
1408 | |
654
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1409 # http2_max_concurrent_streams |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1410 |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1411 $sess = new_session(8086); |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1412 $frames = h2_read($sess, all => [{ type => 'SETTINGS' }]); |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1413 |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1414 ($frame) = grep { $_->{type} eq 'SETTINGS' } @$frames; |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1415 is($frame->{3}, 1, 'http2_max_concurrent_streams SETTINGS'); |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1416 |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1417 h2_window($sess, 2**18); |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1418 |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1419 $sid = new_stream($sess, { path => '/t1.html' }); |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1420 $frames = h2_read($sess, all => [{ sid => $sid, length => 2 ** 16 - 1 }]); |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1421 |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1422 ($frame) = grep { $_->{type} eq "HEADERS" && $_->{sid} == $sid } @$frames; |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1423 is($frame->{headers}->{':status'}, 200, 'http2_max_concurrent_streams'); |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1424 |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1425 $sid2 = new_stream($sess, { path => '/t1.html' }); |
667
0247e314e991
Tests: more HTTP/2 error handling tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
662
diff
changeset
|
1426 $frames = h2_read($sess, all => [{ type => 'RST_STREAM' }]); |
654
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1427 |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1428 ($frame) = grep { $_->{type} eq "HEADERS" && $_->{sid} == $sid2 } @$frames; |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1429 isnt($frame->{headers}->{':status'}, 200, 'http2_max_concurrent_streams 2'); |
a64fe1054fb4
Tests: HTTP/2 tests for http2_max_concurrent_streams directive.
Sergey Kandaurov <pluknet@nginx.com>
parents:
653
diff
changeset
|
1430 |
667
0247e314e991
Tests: more HTTP/2 error handling tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
662
diff
changeset
|
1431 ($frame) = grep { $_->{type} eq "RST_STREAM" && $_->{sid} == $sid2 } @$frames; |
0247e314e991
Tests: more HTTP/2 error handling tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
662
diff
changeset
|
1432 is($frame->{sid}, $sid2, 'http2_max_concurrent_streams RST_STREAM sid'); |
0247e314e991
Tests: more HTTP/2 error handling tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
662
diff
changeset
|
1433 is($frame->{length}, 4, 'http2_max_concurrent_streams RST_STREAM length'); |
0247e314e991
Tests: more HTTP/2 error handling tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
662
diff
changeset
|
1434 is($frame->{flags}, 0, 'http2_max_concurrent_streams RST_STREAM flags'); |
0247e314e991
Tests: more HTTP/2 error handling tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
662
diff
changeset
|
1435 is($frame->{code}, 7, 'http2_max_concurrent_streams RST_STREAM code'); |
0247e314e991
Tests: more HTTP/2 error handling tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
662
diff
changeset
|
1436 |
661
c99c30afc1c9
Tests: one more test for http2_max_concurrent_streams.
Sergey Kandaurov <pluknet@nginx.com>
parents:
660
diff
changeset
|
1437 h2_window($sess, 2**16, $sid); |
c99c30afc1c9
Tests: one more test for http2_max_concurrent_streams.
Sergey Kandaurov <pluknet@nginx.com>
parents:
660
diff
changeset
|
1438 h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
c99c30afc1c9
Tests: one more test for http2_max_concurrent_streams.
Sergey Kandaurov <pluknet@nginx.com>
parents:
660
diff
changeset
|
1439 |
c99c30afc1c9
Tests: one more test for http2_max_concurrent_streams.
Sergey Kandaurov <pluknet@nginx.com>
parents:
660
diff
changeset
|
1440 $sid = new_stream($sess, { path => '/t2.html' }); |
c99c30afc1c9
Tests: one more test for http2_max_concurrent_streams.
Sergey Kandaurov <pluknet@nginx.com>
parents:
660
diff
changeset
|
1441 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
c99c30afc1c9
Tests: one more test for http2_max_concurrent_streams.
Sergey Kandaurov <pluknet@nginx.com>
parents:
660
diff
changeset
|
1442 |
c99c30afc1c9
Tests: one more test for http2_max_concurrent_streams.
Sergey Kandaurov <pluknet@nginx.com>
parents:
660
diff
changeset
|
1443 ($frame) = grep { $_->{type} eq "HEADERS" && $_->{sid} == $sid } @$frames; |
c99c30afc1c9
Tests: one more test for http2_max_concurrent_streams.
Sergey Kandaurov <pluknet@nginx.com>
parents:
660
diff
changeset
|
1444 is($frame->{headers}->{':status'}, 200, 'http2_max_concurrent_streams 3'); |
c99c30afc1c9
Tests: one more test for http2_max_concurrent_streams.
Sergey Kandaurov <pluknet@nginx.com>
parents:
660
diff
changeset
|
1445 |
646 | 1446 |
1447 # some invalid cases below | |
1448 | |
675
42de9efd11ee
Tests: added HTTP/2 test for request header with newline.
Sergey Kandaurov <pluknet@nginx.com>
parents:
673
diff
changeset
|
1449 # ensure that request header field value with newline doesn't get split |
677
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1450 # |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1451 # 10.3. Intermediary Encapsulation Attacks |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1452 # Any request or response that contains a character not permitted |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1453 # in a header field value MUST be treated as malformed. |
675
42de9efd11ee
Tests: added HTTP/2 test for request header with newline.
Sergey Kandaurov <pluknet@nginx.com>
parents:
673
diff
changeset
|
1454 |
42de9efd11ee
Tests: added HTTP/2 test for request header with newline.
Sergey Kandaurov <pluknet@nginx.com>
parents:
673
diff
changeset
|
1455 $sess = new_session(); |
42de9efd11ee
Tests: added HTTP/2 test for request header with newline.
Sergey Kandaurov <pluknet@nginx.com>
parents:
673
diff
changeset
|
1456 $sid = new_stream($sess, { headers => [ |
42de9efd11ee
Tests: added HTTP/2 test for request header with newline.
Sergey Kandaurov <pluknet@nginx.com>
parents:
673
diff
changeset
|
1457 { name => ':method', value => 'GET', mode => 0 }, |
42de9efd11ee
Tests: added HTTP/2 test for request header with newline.
Sergey Kandaurov <pluknet@nginx.com>
parents:
673
diff
changeset
|
1458 { name => ':scheme', value => 'http', mode => 0 }, |
42de9efd11ee
Tests: added HTTP/2 test for request header with newline.
Sergey Kandaurov <pluknet@nginx.com>
parents:
673
diff
changeset
|
1459 { name => ':path', value => '/proxy2/', mode => 1 }, |
42de9efd11ee
Tests: added HTTP/2 test for request header with newline.
Sergey Kandaurov <pluknet@nginx.com>
parents:
673
diff
changeset
|
1460 { name => ':authority', value => 'localhost', mode => 1 }, |
42de9efd11ee
Tests: added HTTP/2 test for request header with newline.
Sergey Kandaurov <pluknet@nginx.com>
parents:
673
diff
changeset
|
1461 { name => 'x-foo', value => "x-bar\r\nreferer:see-this", mode => 2 }]}); |
42de9efd11ee
Tests: added HTTP/2 test for request header with newline.
Sergey Kandaurov <pluknet@nginx.com>
parents:
673
diff
changeset
|
1462 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
42de9efd11ee
Tests: added HTTP/2 test for request header with newline.
Sergey Kandaurov <pluknet@nginx.com>
parents:
673
diff
changeset
|
1463 |
677
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1464 # 10.3. Intermediary Encapsulation Attacks |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1465 # An intermediary therefore cannot translate an HTTP/2 request or response |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1466 # containing an invalid field name into an HTTP/1.1 message. |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1467 |
675
42de9efd11ee
Tests: added HTTP/2 test for request header with newline.
Sergey Kandaurov <pluknet@nginx.com>
parents:
673
diff
changeset
|
1468 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
42de9efd11ee
Tests: added HTTP/2 test for request header with newline.
Sergey Kandaurov <pluknet@nginx.com>
parents:
673
diff
changeset
|
1469 isnt($frame->{headers}->{'x-referer'}, 'see-this', 'newline in request header'); |
42de9efd11ee
Tests: added HTTP/2 test for request header with newline.
Sergey Kandaurov <pluknet@nginx.com>
parents:
673
diff
changeset
|
1470 |
677
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1471 # 8.1.2.6. Malformed Requests and Responses |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1472 # For malformed requests, a server MAY send an HTTP response prior to |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1473 # closing or resetting the stream. |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1474 |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1475 is($frame->{headers}->{':status'}, 400, 'newline in request header - status'); |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1476 |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1477 # 8.1.2.6. Malformed Requests and Responses |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1478 # Malformed requests or responses that are detected MUST be treated |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1479 # as a stream error (Section 5.4.2) of type PROTOCOL_ERROR. |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1480 |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1481 TODO: { |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1482 local $TODO = 'not yet'; |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1483 |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1484 ($frame) = grep { $_->{type} eq "RST_STREAM" } @$frames; |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1485 is($frame->{sid}, $sid, 'newline in request header - RST_STREAM sid'); |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1486 is($frame->{length}, 4, 'newline in request header - RST_STREAM length'); |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1487 is($frame->{flags}, 0, 'newline in request header - RST_STREAM flags'); |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1488 is($frame->{code}, 1, 'newline in request header - RST_STREAM code'); |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1489 |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1490 } |
5d258aa5ebc5
Tests: more HTTP/2 tests for newline in request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
675
diff
changeset
|
1491 |
646 | 1492 # GOAWAY on SYN_STREAM with even StreamID |
1493 | |
1494 TODO: { | |
1495 local $TODO = 'not yet'; | |
1496 | |
1497 $sess = new_session(); | |
1498 new_stream($sess, { path => '/' }, 2); | |
1499 $frames = h2_read($sess, all => [{ type => 'GOAWAY' }]); | |
1500 | |
1501 ($frame) = grep { $_->{type} eq "GOAWAY" } @$frames; | |
1502 ok($frame, 'even stream - GOAWAY frame'); | |
1503 is($frame->{code}, 1, 'even stream - error code'); | |
669
0c442e551ba1
Tests: corrected HTTP/2 tests for GOAWAY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
668
diff
changeset
|
1504 is($frame->{last_sid}, 0, 'even stream - last stream'); |
646 | 1505 |
1506 } | |
1507 | |
1508 # GOAWAY on SYN_STREAM with backward StreamID | |
1509 | |
669
0c442e551ba1
Tests: corrected HTTP/2 tests for GOAWAY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
668
diff
changeset
|
1510 # 5.1.1. Stream Identifiers |
0c442e551ba1
Tests: corrected HTTP/2 tests for GOAWAY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
668
diff
changeset
|
1511 # The first use of a new stream identifier implicitly closes all |
0c442e551ba1
Tests: corrected HTTP/2 tests for GOAWAY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
668
diff
changeset
|
1512 # streams in the "idle" state <..> with a lower-valued stream identifier. |
0c442e551ba1
Tests: corrected HTTP/2 tests for GOAWAY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
668
diff
changeset
|
1513 |
646 | 1514 TODO: { |
1515 local $TODO = 'not yet'; | |
1516 | |
1517 $sess = new_session(); | |
1518 $sid = new_stream($sess, { path => '/' }, 3); | |
1519 h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
1520 | |
1521 $sid2 = new_stream($sess, { path => '/' }, 1); | |
1522 $frames = h2_read($sess, all => [{ type => 'GOAWAY' }]); | |
1523 | |
1524 ($frame) = grep { $_->{type} eq "GOAWAY" } @$frames; | |
1525 ok($frame, 'backward stream - GOAWAY frame'); | |
1526 is($frame->{code}, 1, 'backward stream - error code'); | |
669
0c442e551ba1
Tests: corrected HTTP/2 tests for GOAWAY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
668
diff
changeset
|
1527 is($frame->{last_sid}, $sid, 'backward stream - last stream'); |
646 | 1528 |
1529 } | |
1530 | |
669
0c442e551ba1
Tests: corrected HTTP/2 tests for GOAWAY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
668
diff
changeset
|
1531 # GOAWAY on the second SYN_STREAM with same StreamID |
646 | 1532 |
1533 TODO: { | |
1534 local $TODO = 'not yet'; | |
1535 | |
1536 $sess = new_session(); | |
1537 $sid = new_stream($sess, { path => '/' }); | |
1538 h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | |
1539 | |
1540 $sid2 = new_stream($sess, { path => '/' }, $sid); | |
669
0c442e551ba1
Tests: corrected HTTP/2 tests for GOAWAY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
668
diff
changeset
|
1541 $frames = h2_read($sess, all => [{ type => 'GOAWAY' }]); |
0c442e551ba1
Tests: corrected HTTP/2 tests for GOAWAY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
668
diff
changeset
|
1542 |
0c442e551ba1
Tests: corrected HTTP/2 tests for GOAWAY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
668
diff
changeset
|
1543 ($frame) = grep { $_->{type} eq "GOAWAY" } @$frames; |
0c442e551ba1
Tests: corrected HTTP/2 tests for GOAWAY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
668
diff
changeset
|
1544 ok($frame, 'dup stream - GOAWAY frame'); |
646 | 1545 is($frame->{code}, 1, 'dup stream - error code'); |
669
0c442e551ba1
Tests: corrected HTTP/2 tests for GOAWAY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
668
diff
changeset
|
1546 is($frame->{last_sid}, $sid, 'dup stream - last stream'); |
646 | 1547 |
1548 } | |
1549 | |
1550 # missing mandatory request header ':scheme' | |
1551 | |
1552 TODO: { | |
1553 local $TODO = 'not yet'; | |
1554 | |
1555 $sess = new_session(); | |
1556 $sid = new_stream($sess, { headers => [ | |
1557 { name => ':method', value => 'GET', mode => 0 }, | |
653
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
1558 { name => ':path', value => '/', mode => 0 }, |
5ad620022234
Tests: HTTP/2 tests adapted to send ':authority' where needed.
Sergey Kandaurov <pluknet@nginx.com>
parents:
652
diff
changeset
|
1559 { name => ':authority', value => 'localhost', mode => 1 }]}); |
646 | 1560 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
1561 | |
1562 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | |
1563 is($frame->{headers}->{':status'}, 400, 'incomplete headers'); | |
1564 | |
1565 } | |
1566 | |
673
9d6c865c2869
Tests: HTTP/2 regression test for empty authority request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
672
diff
changeset
|
1567 # empty request header ':authority' |
9d6c865c2869
Tests: HTTP/2 regression test for empty authority request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
672
diff
changeset
|
1568 |
9d6c865c2869
Tests: HTTP/2 regression test for empty authority request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
672
diff
changeset
|
1569 $sess = new_session(); |
9d6c865c2869
Tests: HTTP/2 regression test for empty authority request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
672
diff
changeset
|
1570 $sid = new_stream($sess, { headers => [ |
9d6c865c2869
Tests: HTTP/2 regression test for empty authority request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
672
diff
changeset
|
1571 { name => ':method', value => 'GET', mode => 0 }, |
9d6c865c2869
Tests: HTTP/2 regression test for empty authority request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
672
diff
changeset
|
1572 { name => ':scheme', value => 'http', mode => 0 }, |
9d6c865c2869
Tests: HTTP/2 regression test for empty authority request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
672
diff
changeset
|
1573 { name => ':path', value => '/', mode => 0 }, |
9d6c865c2869
Tests: HTTP/2 regression test for empty authority request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
672
diff
changeset
|
1574 { name => ':authority', value => '', mode => 0 }]}); |
9d6c865c2869
Tests: HTTP/2 regression test for empty authority request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
672
diff
changeset
|
1575 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); |
9d6c865c2869
Tests: HTTP/2 regression test for empty authority request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
672
diff
changeset
|
1576 |
9d6c865c2869
Tests: HTTP/2 regression test for empty authority request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
672
diff
changeset
|
1577 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
9d6c865c2869
Tests: HTTP/2 regression test for empty authority request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
672
diff
changeset
|
1578 is($frame->{headers}->{':status'}, 400, 'empty authority'); |
9d6c865c2869
Tests: HTTP/2 regression test for empty authority request header.
Sergey Kandaurov <pluknet@nginx.com>
parents:
672
diff
changeset
|
1579 |
646 | 1580 # GOAWAY - force closing a connection by server |
1581 | |
1582 $sid = new_stream($sess, { path => 't1.html' }); | |
1583 h2_read($sess, all => [{ sid => $sid, length => 2**16 - 1 }]); | |
1584 | |
1585 $t->stop(); | |
1586 | |
1587 TODO: { | |
1588 local $TODO = 'not yet'; | |
1589 | |
1590 $frames = h2_read($sess, all => [{ type => 'GOAWAY' }]); | |
1591 | |
1592 ($frame) = grep { $_->{type} eq "GOAWAY" } @$frames; | |
1593 ok($frame, 'GOAWAY on connection close'); | |
1594 | |
1595 } | |
1596 | |
1597 ############################################################################### | |
1598 | |
1599 sub h2_ping { | |
1600 my ($sess, $payload) = @_; | |
1601 | |
1602 raw_write($sess->{socket}, pack("x2C2x5a8", 8, 0x6, $payload)); | |
1603 } | |
1604 | |
1605 sub h2_rst { | |
1606 my ($sess, $stream, $error) = @_; | |
1607 | |
1608 raw_write($sess->{socket}, pack("x2C2xNN", 4, 0x3, $stream, $error)); | |
1609 } | |
1610 | |
1611 sub h2_priority { | |
1612 my ($sess, $w, $stream, $dep) = @_; | |
1613 | |
1614 $stream = 0 unless defined $stream; | |
1615 $dep = 0 unless defined $dep; | |
1616 raw_write($sess->{socket}, pack("x2C2xNNC", 5, 0x2, $stream, $dep, $w)); | |
1617 } | |
1618 | |
1619 sub h2_window { | |
1620 my ($sess, $win, $stream) = @_; | |
1621 | |
1622 $stream = 0 unless defined $stream; | |
1623 raw_write($sess->{socket}, pack("x2C2xNN", 4, 0x8, $stream, $win)); | |
1624 } | |
1625 | |
1626 sub h2_settings { | |
1627 my ($sess, $ack, %extra) = @_; | |
1628 | |
1629 my $len = 6 * keys %extra; | |
1630 my $buf = pack_length($len) . pack "CCx4", 0x4, $ack ? 0x1 : 0x0; | |
1631 $buf .= join '', map { pack "nN", $_, $extra{$_} } keys %extra; | |
1632 raw_write($sess->{socket}, $buf); | |
1633 } | |
1634 | |
1635 sub h2_continue { | |
1636 my ($ctx, $stream, $uri) = @_; | |
1637 | |
1638 $uri->{h2_continue} = 1; | |
1639 return new_stream($ctx, $uri, $stream); | |
1640 } | |
1641 | |
1642 sub new_stream { | |
1643 my ($ctx, $uri, $stream) = @_; | |
1644 my ($input, $buf); | |
1645 my ($d, $status); | |
1646 | |
1647 my $host = $uri->{host} || '127.0.0.1:8080'; | |
1648 my $method = $uri->{method} || 'GET'; | |
1649 my $scheme = $uri->{scheme} || 'http'; | |
1650 my $path = $uri->{path} || '/'; | |
1651 my $headers = $uri->{headers}; | |
1652 my $body = $uri->{body}; | |
1653 my $prio = $uri->{prio}; | |
1654 my $dep = $uri->{dep}; | |
1655 | |
1656 my $pad = defined $uri->{padding} ? $uri->{padding} : 0; | |
1657 my $padlen = defined $uri->{padding} ? 1 : 0; | |
1658 my $bpad = defined $uri->{body_padding} ? $uri->{body_padding} : 0; | |
1659 my $bpadlen = defined $uri->{body_padding} ? 1 : 0; | |
1660 | |
1661 my $type = defined $uri->{h2_continue} ? 0x9 : 0x1; | |
1662 my $flags = defined $uri->{continuation} ? 0x0 : 0x4; | |
1663 $flags |= 0x1 unless defined $body; | |
1664 $flags |= 0x8 if $padlen; | |
1665 $flags |= 0x20 if defined $dep || defined $prio; | |
1666 | |
1667 if ($stream) { | |
1668 $ctx->{last_stream} = $stream; | |
1669 } else { | |
1670 $ctx->{last_stream} += 2; | |
1671 } | |
1672 | |
1673 $buf = pack("xxx"); # Length stub | |
1674 $buf .= pack("CC", $type, $flags); # END_HEADERS | |
1675 $buf .= pack("N", $ctx->{last_stream}); # Stream-ID | |
1676 | |
1677 $dep = 0 if defined $prio and not defined $dep; | |
1678 $prio = 16 if defined $dep and not defined $prio; | |
1679 | |
1680 unless ($headers) { | |
1681 $input = hpack($ctx, ":method", $method); | |
1682 $input .= hpack($ctx, ":scheme", $scheme); | |
1683 $input .= hpack($ctx, ":path", $path); | |
1684 $input .= hpack($ctx, ":authority", $host); | |
1685 $input .= hpack($ctx, "content-length", length($body)) if $body; | |
1686 | |
1687 } else { | |
1688 $input = join '', map { | |
1689 hpack($ctx, $_->{name}, $_->{value}, | |
1690 mode => $_->{mode}, huff => $_->{huff}) | |
1691 } @$headers if $headers; | |
1692 } | |
1693 | |
1694 # 5.1. Integer Representation | |
1695 | |
1696 sub intpack { | |
1697 my $d = shift; | |
1698 return pack('B8', '001' . sprintf("%5b", $d)) if $d < 31; | |
1699 | |
1700 my $o = '00111111'; | |
1701 $d -= 31; | |
1702 while ($d >= 128) { | |
1703 $o .= sprintf("%8b", $d % 128 + 128); | |
1704 $d /= 128; | |
1705 } | |
1706 $o .= sprintf("%08b", $d); | |
1707 return pack('B*', $o); | |
1708 } | |
1709 | |
1710 $input = intpack($uri->{table_size}) . $input | |
1711 if defined $uri->{table_size}; | |
1712 | |
1713 # set length, attach headers, padding, priority | |
1714 | |
1715 my $hlen = length($input) + $pad + $padlen; | |
1716 $hlen += 5 if $flags & 0x20; | |
1717 $buf |= pack_length($hlen); | |
1718 | |
1719 $buf .= pack 'C', $pad if $padlen; # Pad Length? | |
1720 $buf .= pack 'NC', $dep, $prio if $flags & 0x20; | |
1721 $buf .= $input; | |
1722 $buf .= (pack 'C', 0) x $pad if $padlen; # Padding | |
1723 | |
1724 if (defined $body) { | |
1725 $buf .= pack_length(length($body) + $bpad + $bpadlen); | |
1726 my $flags = $bpadlen ? 0x8 : 0x0; | |
1727 $buf .= pack 'CC', 0x0, 0x1 | $flags; # DATA, END_STREAM | |
1728 $buf .= pack 'N', $ctx->{last_stream}; | |
1729 $buf .= pack 'C', $bpad if $bpadlen; # DATA Pad Length? | |
1730 $buf .= $body; | |
1731 $buf .= (pack 'C', 0) x $bpad if $bpadlen; # DATA Padding | |
1732 } | |
1733 | |
1734 raw_write($ctx->{socket}, $buf); | |
1735 return $ctx->{last_stream}; | |
1736 } | |
1737 | |
1738 sub h2_read { | |
1739 my ($sess, %extra) = @_; | |
1740 my (@got); | |
1741 my $s = $sess->{socket}; | |
1742 my $buf = ''; | |
1743 | |
1744 while (1) { | |
1745 $buf = raw_read($s, $buf, 9); | |
1746 last unless length $buf; | |
1747 | |
1748 my $length = unpack_length($buf); | |
1749 my $type = unpack('x3C', $buf); | |
1750 my $flags = unpack('x4C', $buf); | |
1751 | |
655
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
1752 my $stream = unpack "x5 B32", $buf; |
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
1753 substr($stream, 0, 1) = 0; |
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
1754 $stream = unpack("N", pack("B32", $stream)); |
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
1755 |
679
b60c1a207675
Tests: fixed HTTP/2 tests with large frames.
Sergey Kandaurov <pluknet@nginx.com>
parents:
677
diff
changeset
|
1756 $buf = raw_read($s, $buf, $length + 9); |
646 | 1757 last unless length $buf; |
1758 | |
655
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
1759 $buf = substr($buf, 9); |
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
1760 |
646 | 1761 my $frame = $cframe{$type}{value}($sess, $buf, $length); |
1762 $frame->{length} = $length; | |
1763 $frame->{type} = $cframe{$type}{name}; | |
1764 $frame->{flags} = $flags; | |
655
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
1765 $frame->{sid} = $stream; |
646 | 1766 push @got, $frame; |
1767 | |
655
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
1768 $buf = substr($buf, $length); |
646 | 1769 |
1770 last unless test_fin($got[-1], $extra{all}); | |
1771 }; | |
1772 return \@got; | |
1773 } | |
1774 | |
1775 sub test_fin { | |
1776 my ($frame, $all) = @_; | |
1777 my @test = @{$all}; | |
1778 | |
1779 # wait for the specified DATA length | |
1780 | |
1781 for (@test) { | |
1782 if ($_->{length} && $frame->{type} eq 'DATA') { | |
1783 # check also for StreamID if needed | |
1784 | |
1785 if (!$_->{sid} || $_->{sid} == $frame->{sid}) { | |
1786 $_->{length} -= $frame->{length}; | |
1787 } | |
1788 } | |
1789 } | |
1790 @test = grep { !(defined $_->{length} && $_->{length} == 0) } @test; | |
1791 | |
1792 # wait for the fin flag | |
1793 | |
1794 @test = grep { !(defined $_->{fin} | |
1795 && $_->{sid} == $frame->{sid} && $_->{fin} & $frame->{flags}) | |
1796 } @test if defined $frame->{flags}; | |
1797 | |
1798 # wait for the specified frame | |
1799 | |
1800 @test = grep { !($_->{type} && $_->{type} eq $frame->{type}) } @test; | |
1801 | |
1802 @{$all} = @test; | |
1803 } | |
1804 | |
1805 sub headers { | |
1806 my ($ctx, $buf, $len) = @_; | |
655
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
1807 return { headers => hunpack($ctx, $buf, $len) }; |
646 | 1808 } |
1809 | |
1810 sub data { | |
1811 my ($ctx, $buf, $len) = @_; | |
655
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
1812 return { data => substr($buf, 0, $len) }; |
646 | 1813 } |
1814 | |
1815 sub settings { | |
1816 my ($ctx, $buf, $len) = @_; | |
1817 my %payload; | |
655
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
1818 my $skip = 0; |
646 | 1819 |
1820 for (1 .. $len / 6) { | |
1821 my $id = hex unpack "\@$skip n", $buf; $skip += 2; | |
1822 $payload{$id} = unpack "\@$skip N", $buf; $skip += 4; | |
1823 } | |
1824 return \%payload; | |
1825 } | |
1826 | |
1827 sub ping { | |
1828 my ($ctx, $buf, $len) = @_; | |
670
944b87756cab
Tests: fixed GOAWAY and PING frames parsing in HTTP/2 tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
669
diff
changeset
|
1829 return { value => unpack "A$len", $buf }; |
646 | 1830 } |
1831 | |
1832 sub rst_stream { | |
1833 my ($ctx, $buf, $len) = @_; | |
655
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
1834 return { code => unpack "N", $buf }; |
646 | 1835 } |
1836 | |
1837 sub goaway { | |
1838 my ($ctx, $buf, $len) = @_; | |
1839 my %payload; | |
655
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
1840 |
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
1841 my $stream = unpack "B32", $buf; |
646 | 1842 substr($stream, 0, 1) = 0; |
1843 $stream = unpack("N", pack("B32", $stream)); | |
1844 $payload{last_sid} = $stream; | |
655
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
1845 |
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
1846 $len -= 4; |
670
944b87756cab
Tests: fixed GOAWAY and PING frames parsing in HTTP/2 tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
669
diff
changeset
|
1847 $payload{code} = unpack "x4 N", $buf; |
944b87756cab
Tests: fixed GOAWAY and PING frames parsing in HTTP/2 tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
669
diff
changeset
|
1848 $payload{debug} = unpack "x8 A$len", $buf; |
646 | 1849 return \%payload; |
1850 } | |
1851 | |
1852 sub window_update { | |
1853 my ($ctx, $buf, $len) = @_; | |
655
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
1854 my $value = unpack "B32", $buf; |
646 | 1855 substr($value, 0, 1) = 0; |
655
75ecd26b8831
Tests: HTTP/2 tests cleanup.
Sergey Kandaurov <pluknet@nginx.com>
parents:
654
diff
changeset
|
1856 return { wdelta => unpack("N", pack("B32", $value)) }; |
646 | 1857 } |
1858 | |
1859 sub pack_length { | |
1860 pack 'c3', unpack 'xc3', pack 'N', $_[0]; | |
1861 } | |
1862 | |
1863 sub unpack_length { | |
1864 unpack 'N', pack 'xc3', unpack 'c3', $_[0]; | |
1865 } | |
1866 | |
1867 sub raw_read { | |
1868 my ($s, $buf, $len) = @_; | |
1869 my $got = ''; | |
1870 | |
1871 while (length($buf) < $len && IO::Select->new($s)->can_read(1)) { | |
650
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
1872 $s->sysread($got, 16384) or last; |
646 | 1873 log_in($got); |
1874 $buf .= $got; | |
1875 } | |
1876 return $buf; | |
1877 } | |
1878 | |
1879 sub raw_write { | |
1880 my ($s, $message) = @_; | |
1881 | |
1882 local $SIG{PIPE} = 'IGNORE'; | |
1883 | |
1884 while (IO::Select->new($s)->can_write(0.4)) { | |
1885 log_out($message); | |
1886 my $n = $s->syswrite($message); | |
1887 last unless $n; | |
1888 $message = substr($message, $n); | |
1889 last unless length $message; | |
1890 } | |
1891 } | |
1892 | |
1893 sub new_session { | |
1894 my ($port, %extra) = @_; | |
1895 my ($s); | |
1896 | |
650
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
1897 $s = new_socket($port, %extra); |
646 | 1898 |
1899 if ($extra{proxy}) { | |
1900 raw_write($s, $extra{proxy}); | |
1901 } | |
1902 | |
1903 # preface | |
1904 | |
1905 raw_write($s, 'PRI * HTTP/2.0' . CRLF . CRLF . 'SM' . CRLF . CRLF); | |
1906 | |
1907 return { socket => $s, last_stream => -1, | |
1908 dynamic_encode => [ static_table() ], | |
1909 dynamic_decode => [ static_table() ], | |
1910 static_table_size => scalar @{[static_table()]} }; | |
1911 } | |
1912 | |
1913 sub new_socket { | |
650
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
1914 my ($port, %extra) = @_; |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
1915 my $npn = $extra{'npn'}; |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
1916 my $alpn = $extra{'alpn'}; |
646 | 1917 my $s; |
1918 | |
1919 $port = 8080 unless defined $port; | |
1920 | |
1921 eval { | |
1922 local $SIG{ALRM} = sub { die "timeout\n" }; | |
1923 local $SIG{PIPE} = sub { die "sigpipe\n" }; | |
1924 alarm(2); | |
1925 $s = IO::Socket::INET->new( | |
1926 Proto => 'tcp', | |
1927 PeerAddr => "127.0.0.1:$port", | |
1928 ); | |
650
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
1929 IO::Socket::SSL->start_SSL($s, |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
1930 SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE(), |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
1931 SSL_npn_protocols => $npn ? [ $npn ] : undef, |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
1932 SSL_alpn_protocols => $alpn ? [ $alpn ] : undef, |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
1933 SSL_error_trap => sub { die $_[1] } |
8a2cf558b8ae
Tests: HTTP/2 tests for $http2 variable.
Sergey Kandaurov <pluknet@nginx.com>
parents:
647
diff
changeset
|
1934 ) if $extra{'SSL'}; |
646 | 1935 alarm(0); |
1936 }; | |
1937 alarm(0); | |
1938 | |
1939 if ($@) { | |
1940 log_in("died: $@"); | |
1941 return undef; | |
1942 } | |
1943 | |
1944 return $s; | |
1945 } | |
1946 | |
1947 sub static_table { | |
1948 [ '', '' ], # unused | |
1949 [ ':authority', '' ], | |
1950 [ ':method', 'GET' ], | |
1951 [ ':method', 'POST' ], | |
1952 [ ':path', '/' ], | |
1953 [ ':path', '/index.html' ], | |
1954 [ ':scheme', 'http' ], | |
1955 [ ':scheme', 'https' ], | |
1956 [ ':status', '200' ], | |
1957 [ ':status', '204' ], | |
1958 [ ':status', '206' ], | |
1959 [ ':status', '304' ], | |
1960 [ ':status', '400' ], | |
1961 [ ':status', '404' ], | |
1962 [ ':status', '500' ], | |
1963 [ 'accept-charset', '' ], | |
1964 [ 'accept-encoding', 'gzip, deflate' ], | |
1965 [ 'accept-language', '' ], | |
1966 [ 'accept-ranges', '' ], | |
1967 [ 'accept', '' ], | |
1968 [ 'access-control-allow-origin', | |
1969 '' ], | |
1970 [ 'age', '' ], | |
1971 [ 'allow', '' ], | |
1972 [ 'authorization', '' ], | |
1973 [ 'cache-control', '' ], | |
1974 [ 'content-disposition', | |
1975 '' ], | |
1976 [ 'content-encoding', '' ], | |
1977 [ 'content-language', '' ], | |
1978 [ 'content-length', '' ], | |
1979 [ 'content-location', '' ], | |
1980 [ 'content-range', '' ], | |
1981 [ 'content-type', '' ], | |
1982 [ 'cookie', '' ], | |
1983 [ 'date', '' ], | |
1984 [ 'etag', '' ], | |
1985 [ 'expect', '' ], | |
1986 [ 'expires', '' ], | |
1987 [ 'from', '' ], | |
1988 [ 'host', '' ], | |
1989 [ 'if-match', '' ], | |
1990 [ 'if-modified-since', '' ], | |
1991 [ 'if-none-match', '' ], | |
1992 [ 'if-range', '' ], | |
1993 [ 'if-unmodified-since', | |
1994 '' ], | |
1995 [ 'last-modified', '' ], | |
1996 [ 'link', '' ], | |
1997 [ 'location', '' ], | |
1998 [ 'max-forwards', '' ], | |
1999 [ 'proxy-authenticate', '' ], | |
2000 [ 'proxy-authorization', | |
2001 '' ], | |
2002 [ 'range', '' ], | |
2003 [ 'referer', '' ], | |
2004 [ 'refresh', '' ], | |
2005 [ 'retry-after', '' ], | |
2006 [ 'server', '' ], | |
2007 [ 'set-cookie', '' ], | |
2008 [ 'strict-transport-security', | |
2009 '' ], | |
2010 [ 'transfer-encoding', '' ], | |
2011 [ 'user-agent', '' ], | |
2012 [ 'vary', '' ], | |
2013 [ 'via', '' ], | |
2014 [ 'www-authenticate', '' ], | |
2015 } | |
2016 | |
2017 sub hpack { | |
2018 my ($ctx, $name, $value, %extra) = @_; | |
671
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2019 my $table = $ctx->{dynamic_encode}; |
646 | 2020 my $mode = defined $extra{mode} ? $extra{mode} : 1; |
2021 my $huff = $extra{huff}; | |
2022 | |
2023 my ($index, $buf) = 0; | |
2024 | |
2025 # 6.1. Indexed Header Field Representation | |
2026 | |
2027 if ($mode == 0) { | |
671
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2028 ++$index until $index > $#$table |
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2029 or $table->[$index][0] eq $name |
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2030 and $table->[$index][1] eq $value; |
646 | 2031 $buf = pack('B*', '1' . sprintf("%7b", $index)); |
2032 } | |
2033 | |
2034 # 6.2.1. Literal Header Field with Incremental Indexing | |
2035 | |
2036 if ($mode == 1) { | |
671
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2037 splice @$table, $ctx->{static_table_size}, 0, [ $name, $value ]; |
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2038 |
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2039 ++$index until $index > $#$table |
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2040 or $table->[$index][0] eq $name; |
646 | 2041 my $value = $huff ? huff($value) : $value; |
2042 | |
2043 $buf = pack('B*', '01' . sprintf("%6b", $index) | |
2044 . ($huff ? '1' : '0') . sprintf("%7b", length($value))); | |
2045 $buf .= $value; | |
2046 } | |
2047 | |
2048 # 6.2.1. Literal Header Field with Incremental Indexing -- New Name | |
2049 | |
2050 if ($mode == 2) { | |
671
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2051 splice @$table, $ctx->{static_table_size}, 0, [ $name, $value ]; |
646 | 2052 |
2053 my $name = $huff ? huff($name) : $name; | |
2054 my $value = $huff ? huff($value) : $value; | |
2055 my $hbit = ($huff ? '1' : '0'); | |
2056 | |
2057 $buf = pack('B*', '01000000'); | |
2058 $buf .= pack('B*', $hbit . sprintf("%7b", length($name))); | |
2059 $buf .= $name; | |
2060 $buf .= pack('B*', $hbit . sprintf("%7b", length($value))); | |
2061 $buf .= $value; | |
2062 } | |
2063 | |
2064 # 6.2.2. Literal Header Field without Indexing | |
2065 | |
2066 if ($mode == 3) { | |
671
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2067 ++$index until $index > $#$table |
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2068 or $table->[$index][0] eq $name; |
646 | 2069 my $value = $huff ? huff($value) : $value; |
2070 | |
2071 $buf = pack('B*', '0000' . sprintf("%4b", $index) | |
2072 . ($huff ? '1' : '0') . sprintf("%7b", length($value))); | |
2073 $buf .= $value; | |
2074 } | |
2075 | |
2076 # 6.2.2. Literal Header Field without Indexing -- New Name | |
2077 | |
2078 if ($mode == 4) { | |
2079 my $name = $huff ? huff($name) : $name; | |
2080 my $value = $huff ? huff($value) : $value; | |
2081 my $hbit = ($huff ? '1' : '0'); | |
2082 | |
2083 $buf = pack('B*', '00000000'); | |
2084 $buf .= pack('B*', $hbit . sprintf("%7b", length($name))); | |
2085 $buf .= $name; | |
2086 $buf .= pack('B*', $hbit . sprintf("%7b", length($value))); | |
2087 $buf .= $value; | |
2088 } | |
2089 | |
2090 # 6.2.3. Literal Header Field Never Indexed | |
2091 | |
2092 if ($mode == 5) { | |
671
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2093 ++$index until $index > $#$table |
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2094 or $table->[$index][0] eq $name; |
646 | 2095 my $value = $huff ? huff($value) : $value; |
2096 | |
2097 $buf = pack('B*', '0001' . sprintf("%4b", $index) | |
2098 . ($huff ? '1' : '0') . sprintf("%7b", length($value))); | |
2099 $buf .= $value; | |
2100 } | |
2101 | |
2102 # 6.2.3. Literal Header Field Never Indexed -- New Name | |
2103 | |
2104 if ($mode == 6) { | |
2105 my $name = $huff ? huff($name) : $name; | |
2106 my $value = $huff ? huff($value) : $value; | |
2107 my $hbit = ($huff ? '1' : '0'); | |
2108 | |
2109 $buf = pack('B*', '00010000'); | |
2110 $buf .= pack('B*', $hbit . sprintf("%7b", length($name))); | |
2111 $buf .= $name; | |
2112 $buf .= pack('B*', $hbit . sprintf("%7b", length($value))); | |
2113 $buf .= $value; | |
2114 } | |
2115 | |
2116 return $buf; | |
2117 } | |
2118 | |
2119 sub hunpack { | |
2120 my ($ctx, $data, $length) = @_; | |
671
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2121 my $table = $ctx->{dynamic_decode}; |
646 | 2122 my %headers; |
2123 my $skip = 0; | |
2124 my ($name, $value); | |
2125 | |
2126 sub index { | |
2127 my ($b, $i) = @_; | |
2128 unpack("C", pack("B8", '0' x $i . substr($b, $i, 8 - $i))); | |
2129 } | |
2130 | |
2131 sub field { | |
2132 my ($b, $s) = @_; | |
2133 my $len = unpack("\@$s B8", $b); | |
2134 my $huff = substr($len, 0, 1) ? 1 : 0; | |
2135 $len = unpack("C", pack("B8", '0' . substr($len, 1, 8))); | |
2136 $s++; | |
2137 | |
2138 my $field = substr($b, $s, $len); | |
2139 $field = $huff ? dehuff($field) : $field; | |
2140 $s += $len; | |
2141 return ($field, $s); | |
2142 } | |
2143 | |
2144 sub add { | |
2145 my ($h, $n, $v) = @_; | |
2146 return $h->{$n} = $v unless exists $h->{$n}; | |
2147 $h->{$n} = [ $h->{$n} ]; | |
647
4e36550410b3
Tests: h2.t fixes for older perl versions, and gzip test.
Sergey Kandaurov <pluknet@nginx.com>
parents:
646
diff
changeset
|
2148 push @{$h->{$n}}, $v; |
646 | 2149 } |
2150 | |
2151 while ($skip < $length) { | |
2152 my $ib = unpack("\@$skip B8", $data); | |
2153 | |
2154 if (substr($ib, 0, 1) eq '1') { | |
2155 my $index = &index($ib, 1); | |
671
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2156 add(\%headers, |
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2157 $table->[$index][0], $table->[$index][1]); |
646 | 2158 $skip += 1; |
2159 next; | |
2160 } | |
2161 | |
2162 if (substr($ib, 0, 2) eq '01') { | |
671
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2163 $name = $table->[&index($ib, 2)][0]; |
646 | 2164 $skip++; |
2165 | |
2166 ($name, $skip) = field($data, $skip) unless $name; | |
2167 ($value, $skip) = field($data, $skip); | |
2168 | |
671
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2169 splice @$table, |
646 | 2170 $ctx->{static_table_size}, 0, [ $name, $value ]; |
2171 add(\%headers, $name, $value); | |
2172 next; | |
2173 } | |
2174 | |
2175 if (substr($ib, 0, 4) eq '0000') { | |
671
0c70eb166a3a
Tests: in HTTP/2 tests, always access a dynamic table by reference.
Sergey Kandaurov <pluknet@nginx.com>
parents:
670
diff
changeset
|
2176 $name = $table->[&index($ib, 4)][0]; |
646 | 2177 $skip++; |
2178 | |
2179 ($name, $skip) = field($data, $skip) unless $name; | |
2180 ($value, $skip) = field($data, $skip); | |
2181 | |
2182 add(\%headers, $name, $value); | |
2183 next; | |
2184 } | |
2185 } | |
2186 | |
2187 return \%headers; | |
2188 } | |
2189 | |
2190 sub huff_code { scalar { | |
2191 pack('C', 0) => '1111111111000', | |
2192 pack('C', 1) => '11111111111111111011000', | |
2193 pack('C', 2) => '1111111111111111111111100010', | |
2194 pack('C', 3) => '1111111111111111111111100011', | |
2195 pack('C', 4) => '1111111111111111111111100100', | |
2196 pack('C', 5) => '1111111111111111111111100101', | |
2197 pack('C', 6) => '1111111111111111111111100110', | |
2198 pack('C', 7) => '1111111111111111111111100111', | |
2199 pack('C', 8) => '1111111111111111111111101000', | |
2200 pack('C', 9) => '111111111111111111101010', | |
2201 pack('C', 10) => '111111111111111111111111111100', | |
2202 pack('C', 11) => '1111111111111111111111101001', | |
2203 pack('C', 12) => '1111111111111111111111101010', | |
2204 pack('C', 13) => '111111111111111111111111111101', | |
2205 pack('C', 14) => '1111111111111111111111101011', | |
2206 pack('C', 15) => '1111111111111111111111101100', | |
2207 pack('C', 16) => '1111111111111111111111101101', | |
2208 pack('C', 17) => '1111111111111111111111101110', | |
2209 pack('C', 18) => '1111111111111111111111101111', | |
2210 pack('C', 19) => '1111111111111111111111110000', | |
2211 pack('C', 20) => '1111111111111111111111110001', | |
2212 pack('C', 21) => '1111111111111111111111110010', | |
2213 pack('C', 22) => '111111111111111111111111111110', | |
2214 pack('C', 23) => '1111111111111111111111110011', | |
2215 pack('C', 24) => '1111111111111111111111110100', | |
2216 pack('C', 25) => '1111111111111111111111110101', | |
2217 pack('C', 26) => '1111111111111111111111110110', | |
2218 pack('C', 27) => '1111111111111111111111110111', | |
2219 pack('C', 28) => '1111111111111111111111111000', | |
2220 pack('C', 29) => '1111111111111111111111111001', | |
2221 pack('C', 30) => '1111111111111111111111111010', | |
2222 pack('C', 31) => '1111111111111111111111111011', | |
2223 pack('C', 32) => '010100', | |
2224 pack('C', 33) => '1111111000', | |
2225 pack('C', 34) => '1111111001', | |
2226 pack('C', 35) => '111111111010', | |
2227 pack('C', 36) => '1111111111001', | |
2228 pack('C', 37) => '010101', | |
2229 pack('C', 38) => '11111000', | |
2230 pack('C', 39) => '11111111010', | |
2231 pack('C', 40) => '1111111010', | |
2232 pack('C', 41) => '1111111011', | |
2233 pack('C', 42) => '11111001', | |
2234 pack('C', 43) => '11111111011', | |
2235 pack('C', 44) => '11111010', | |
2236 pack('C', 45) => '010110', | |
2237 pack('C', 46) => '010111', | |
2238 pack('C', 47) => '011000', | |
2239 pack('C', 48) => '00000', | |
2240 pack('C', 49) => '00001', | |
2241 pack('C', 50) => '00010', | |
2242 pack('C', 51) => '011001', | |
2243 pack('C', 52) => '011010', | |
2244 pack('C', 53) => '011011', | |
2245 pack('C', 54) => '011100', | |
2246 pack('C', 55) => '011101', | |
2247 pack('C', 56) => '011110', | |
2248 pack('C', 57) => '011111', | |
2249 pack('C', 58) => '1011100', | |
2250 pack('C', 59) => '11111011', | |
2251 pack('C', 60) => '111111111111100', | |
2252 pack('C', 61) => '100000', | |
2253 pack('C', 62) => '111111111011', | |
2254 pack('C', 63) => '1111111100', | |
2255 pack('C', 64) => '1111111111010', | |
2256 pack('C', 65) => '100001', | |
2257 pack('C', 66) => '1011101', | |
2258 pack('C', 67) => '1011110', | |
2259 pack('C', 68) => '1011111', | |
2260 pack('C', 69) => '1100000', | |
2261 pack('C', 70) => '1100001', | |
2262 pack('C', 71) => '1100010', | |
2263 pack('C', 72) => '1100011', | |
2264 pack('C', 73) => '1100100', | |
2265 pack('C', 74) => '1100101', | |
2266 pack('C', 75) => '1100110', | |
2267 pack('C', 76) => '1100111', | |
2268 pack('C', 77) => '1101000', | |
2269 pack('C', 78) => '1101001', | |
2270 pack('C', 79) => '1101010', | |
2271 pack('C', 80) => '1101011', | |
2272 pack('C', 81) => '1101100', | |
2273 pack('C', 82) => '1101101', | |
2274 pack('C', 83) => '1101110', | |
2275 pack('C', 84) => '1101111', | |
2276 pack('C', 85) => '1110000', | |
2277 pack('C', 86) => '1110001', | |
2278 pack('C', 87) => '1110010', | |
2279 pack('C', 88) => '11111100', | |
2280 pack('C', 89) => '1110011', | |
2281 pack('C', 90) => '11111101', | |
2282 pack('C', 91) => '1111111111011', | |
2283 pack('C', 92) => '1111111111111110000', | |
2284 pack('C', 93) => '1111111111100', | |
2285 pack('C', 94) => '11111111111100', | |
2286 pack('C', 95) => '100010', | |
2287 pack('C', 96) => '111111111111101', | |
2288 pack('C', 97) => '00011', | |
2289 pack('C', 98) => '100011', | |
2290 pack('C', 99) => '00100', | |
2291 pack('C', 100) => '100100', | |
2292 pack('C', 101) => '00101', | |
2293 pack('C', 102) => '100101', | |
2294 pack('C', 103) => '100110', | |
2295 pack('C', 104) => '100111', | |
2296 pack('C', 105) => '00110', | |
2297 pack('C', 106) => '1110100', | |
2298 pack('C', 107) => '1110101', | |
2299 pack('C', 108) => '101000', | |
2300 pack('C', 109) => '101001', | |
2301 pack('C', 110) => '101010', | |
2302 pack('C', 111) => '00111', | |
2303 pack('C', 112) => '101011', | |
2304 pack('C', 113) => '1110110', | |
2305 pack('C', 114) => '101100', | |
2306 pack('C', 115) => '01000', | |
2307 pack('C', 116) => '01001', | |
2308 pack('C', 117) => '101101', | |
2309 pack('C', 118) => '1110111', | |
2310 pack('C', 119) => '1111000', | |
2311 pack('C', 120) => '1111001', | |
2312 pack('C', 121) => '1111010', | |
2313 pack('C', 122) => '1111011', | |
2314 pack('C', 123) => '111111111111110', | |
2315 pack('C', 124) => '11111111100', | |
2316 pack('C', 125) => '11111111111101', | |
2317 pack('C', 126) => '1111111111101', | |
2318 pack('C', 127) => '1111111111111111111111111100', | |
2319 pack('C', 128) => '11111111111111100110', | |
2320 pack('C', 129) => '1111111111111111010010', | |
2321 pack('C', 130) => '11111111111111100111', | |
2322 pack('C', 131) => '11111111111111101000', | |
2323 pack('C', 132) => '1111111111111111010011', | |
2324 pack('C', 133) => '1111111111111111010100', | |
2325 pack('C', 134) => '1111111111111111010101', | |
2326 pack('C', 135) => '11111111111111111011001', | |
2327 pack('C', 136) => '1111111111111111010110', | |
2328 pack('C', 137) => '11111111111111111011010', | |
2329 pack('C', 138) => '11111111111111111011011', | |
2330 pack('C', 139) => '11111111111111111011100', | |
2331 pack('C', 140) => '11111111111111111011101', | |
2332 pack('C', 141) => '11111111111111111011110', | |
2333 pack('C', 142) => '111111111111111111101011', | |
2334 pack('C', 143) => '11111111111111111011111', | |
2335 pack('C', 144) => '111111111111111111101100', | |
2336 pack('C', 145) => '111111111111111111101101', | |
2337 pack('C', 146) => '1111111111111111010111', | |
2338 pack('C', 147) => '11111111111111111100000', | |
2339 pack('C', 148) => '111111111111111111101110', | |
2340 pack('C', 149) => '11111111111111111100001', | |
2341 pack('C', 150) => '11111111111111111100010', | |
2342 pack('C', 151) => '11111111111111111100011', | |
2343 pack('C', 152) => '11111111111111111100100', | |
2344 pack('C', 153) => '111111111111111011100', | |
2345 pack('C', 154) => '1111111111111111011000', | |
2346 pack('C', 155) => '11111111111111111100101', | |
2347 pack('C', 156) => '1111111111111111011001', | |
2348 pack('C', 157) => '11111111111111111100110', | |
2349 pack('C', 158) => '11111111111111111100111', | |
2350 pack('C', 159) => '111111111111111111101111', | |
2351 pack('C', 160) => '1111111111111111011010', | |
2352 pack('C', 161) => '111111111111111011101', | |
2353 pack('C', 162) => '11111111111111101001', | |
2354 pack('C', 163) => '1111111111111111011011', | |
2355 pack('C', 164) => '1111111111111111011100', | |
2356 pack('C', 165) => '11111111111111111101000', | |
2357 pack('C', 166) => '11111111111111111101001', | |
2358 pack('C', 167) => '111111111111111011110', | |
2359 pack('C', 168) => '11111111111111111101010', | |
2360 pack('C', 169) => '1111111111111111011101', | |
2361 pack('C', 170) => '1111111111111111011110', | |
2362 pack('C', 171) => '111111111111111111110000', | |
2363 pack('C', 172) => '111111111111111011111', | |
2364 pack('C', 173) => '1111111111111111011111', | |
2365 pack('C', 174) => '11111111111111111101011', | |
2366 pack('C', 175) => '11111111111111111101100', | |
2367 pack('C', 176) => '111111111111111100000', | |
2368 pack('C', 177) => '111111111111111100001', | |
2369 pack('C', 178) => '1111111111111111100000', | |
2370 pack('C', 179) => '111111111111111100010', | |
2371 pack('C', 180) => '11111111111111111101101', | |
2372 pack('C', 181) => '1111111111111111100001', | |
2373 pack('C', 182) => '11111111111111111101110', | |
2374 pack('C', 183) => '11111111111111111101111', | |
2375 pack('C', 184) => '11111111111111101010', | |
2376 pack('C', 185) => '1111111111111111100010', | |
2377 pack('C', 186) => '1111111111111111100011', | |
2378 pack('C', 187) => '1111111111111111100100', | |
2379 pack('C', 188) => '11111111111111111110000', | |
2380 pack('C', 189) => '1111111111111111100101', | |
2381 pack('C', 190) => '1111111111111111100110', | |
2382 pack('C', 191) => '11111111111111111110001', | |
2383 pack('C', 192) => '11111111111111111111100000', | |
2384 pack('C', 193) => '11111111111111111111100001', | |
2385 pack('C', 194) => '11111111111111101011', | |
2386 pack('C', 195) => '1111111111111110001', | |
2387 pack('C', 196) => '1111111111111111100111', | |
2388 pack('C', 197) => '11111111111111111110010', | |
2389 pack('C', 198) => '1111111111111111101000', | |
2390 pack('C', 199) => '1111111111111111111101100', | |
2391 pack('C', 200) => '11111111111111111111100010', | |
2392 pack('C', 201) => '11111111111111111111100011', | |
2393 pack('C', 202) => '11111111111111111111100100', | |
2394 pack('C', 203) => '111111111111111111111011110', | |
2395 pack('C', 204) => '111111111111111111111011111', | |
2396 pack('C', 205) => '11111111111111111111100101', | |
2397 pack('C', 206) => '111111111111111111110001', | |
2398 pack('C', 207) => '1111111111111111111101101', | |
2399 pack('C', 208) => '1111111111111110010', | |
2400 pack('C', 209) => '111111111111111100011', | |
2401 pack('C', 210) => '11111111111111111111100110', | |
2402 pack('C', 211) => '111111111111111111111100000', | |
2403 pack('C', 212) => '111111111111111111111100001', | |
2404 pack('C', 213) => '11111111111111111111100111', | |
2405 pack('C', 214) => '111111111111111111111100010', | |
2406 pack('C', 215) => '111111111111111111110010', | |
2407 pack('C', 216) => '111111111111111100100', | |
2408 pack('C', 217) => '111111111111111100101', | |
2409 pack('C', 218) => '11111111111111111111101000', | |
2410 pack('C', 219) => '11111111111111111111101001', | |
2411 pack('C', 220) => '1111111111111111111111111101', | |
2412 pack('C', 221) => '111111111111111111111100011', | |
2413 pack('C', 222) => '111111111111111111111100100', | |
2414 pack('C', 223) => '111111111111111111111100101', | |
2415 pack('C', 224) => '11111111111111101100', | |
2416 pack('C', 225) => '111111111111111111110011', | |
2417 pack('C', 226) => '11111111111111101101', | |
2418 pack('C', 227) => '111111111111111100110', | |
2419 pack('C', 228) => '1111111111111111101001', | |
2420 pack('C', 229) => '111111111111111100111', | |
2421 pack('C', 230) => '111111111111111101000', | |
2422 pack('C', 231) => '11111111111111111110011', | |
2423 pack('C', 232) => '1111111111111111101010', | |
2424 pack('C', 233) => '1111111111111111101011', | |
2425 pack('C', 234) => '1111111111111111111101110', | |
2426 pack('C', 235) => '1111111111111111111101111', | |
2427 pack('C', 236) => '111111111111111111110100', | |
2428 pack('C', 237) => '111111111111111111110101', | |
2429 pack('C', 238) => '11111111111111111111101010', | |
2430 pack('C', 239) => '11111111111111111110100', | |
2431 pack('C', 240) => '11111111111111111111101011', | |
2432 pack('C', 241) => '111111111111111111111100110', | |
2433 pack('C', 242) => '11111111111111111111101100', | |
2434 pack('C', 243) => '11111111111111111111101101', | |
2435 pack('C', 244) => '111111111111111111111100111', | |
2436 pack('C', 245) => '111111111111111111111101000', | |
2437 pack('C', 246) => '111111111111111111111101001', | |
2438 pack('C', 247) => '111111111111111111111101010', | |
2439 pack('C', 248) => '111111111111111111111101011', | |
2440 pack('C', 249) => '1111111111111111111111111110', | |
2441 pack('C', 250) => '111111111111111111111101100', | |
2442 pack('C', 251) => '111111111111111111111101101', | |
2443 pack('C', 252) => '111111111111111111111101110', | |
2444 pack('C', 253) => '111111111111111111111101111', | |
2445 pack('C', 254) => '111111111111111111111110000', | |
2446 pack('C', 255) => '11111111111111111111101110', | |
2447 '_eos' => '111111111111111111111111111111', | |
2448 }}; | |
2449 | |
2450 sub huff { | |
2451 my ($string) = @_; | |
2452 my $code = &huff_code; | |
2453 | |
2454 my $ret = join '', map { $code->{$_} } (split //, $string); | |
2455 my $len = length($ret) + (8 - length($ret) % 8); | |
2456 $ret .= $code->{_eos}; | |
2457 | |
2458 return pack("B$len", $ret); | |
2459 } | |
2460 | |
2461 sub dehuff { | |
2462 my ($string) = @_; | |
2463 my $code = &huff_code; | |
2464 my %decode = reverse %$code; | |
2465 | |
2466 my $ret = ''; my $c = ''; | |
2467 for (split //, unpack('B*', $string)) { | |
2468 $c .= $_; | |
2469 next unless exists $decode{$c}; | |
2470 last if $decode{$c} eq '_eos'; | |
2471 | |
2472 $ret .= $decode{$c}; | |
2473 $c = ''; | |
2474 } | |
2475 | |
2476 return $ret; | |
2477 } | |
2478 | |
2479 ############################################################################### | |
2480 | |
647
4e36550410b3
Tests: h2.t fixes for older perl versions, and gzip test.
Sergey Kandaurov <pluknet@nginx.com>
parents:
646
diff
changeset
|
2481 sub gunzip_like { |
4e36550410b3
Tests: h2.t fixes for older perl versions, and gzip test.
Sergey Kandaurov <pluknet@nginx.com>
parents:
646
diff
changeset
|
2482 my ($in, $re, $name) = @_; |
646 | 2483 |
2484 SKIP: { | |
2485 eval { require IO::Uncompress::Gunzip; }; | |
2486 Test::More::skip( | |
2487 "IO::Uncompress::Gunzip not installed", 1) if $@; | |
2488 | |
2489 my $out; | |
2490 | |
2491 IO::Uncompress::Gunzip::gunzip(\$in => \$out); | |
2492 | |
647
4e36550410b3
Tests: h2.t fixes for older perl versions, and gzip test.
Sergey Kandaurov <pluknet@nginx.com>
parents:
646
diff
changeset
|
2493 like($out, $re, $name); |
646 | 2494 } |
2495 } | |
2496 | |
2497 ############################################################################### | |
2498 | |
2499 # for tests with multiple header fields | |
2500 | |
2501 sub http_daemon { | |
2502 my $server = IO::Socket::INET->new( | |
2503 Proto => 'tcp', | |
2504 LocalHost => '127.0.0.1', | |
2505 LocalPort => 8083, | |
2506 Listen => 5, | |
2507 Reuse => 1 | |
2508 ) | |
2509 or die "Can't create listening socket: $!\n"; | |
2510 | |
2511 local $SIG{PIPE} = 'IGNORE'; | |
2512 | |
2513 while (my $client = $server->accept()) { | |
2514 $client->autoflush(1); | |
2515 | |
2516 my $headers = ''; | |
2517 my $uri = ''; | |
2518 | |
2519 while (<$client>) { | |
2520 $headers .= $_; | |
2521 last if (/^\x0d?\x0a?$/); | |
2522 } | |
2523 | |
2524 next if $headers eq ''; | |
2525 $uri = $1 if $headers =~ /^\S+\s+([^ ]+)\s+HTTP/i; | |
2526 | |
2527 if ($uri eq '/cookie') { | |
2528 | |
652
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
2529 my ($cookie, $cookie2) = $headers =~ /Cookie: (.+)/ig; |
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
2530 $cookie2 = '' unless defined $cookie2; |
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
2531 |
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
2532 my ($cookie_a, $cookie_c) = ('', ''); |
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
2533 $cookie_a = $1 if $headers =~ /X-Cookie-a: (.+)/i; |
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
2534 $cookie_c = $1 if $headers =~ /X-Cookie-c: (.+)/i; |
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
2535 |
646 | 2536 print $client <<EOF; |
2537 HTTP/1.1 200 OK | |
2538 Connection: close | |
652
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
2539 X-Sent-Cookie: $cookie |
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
2540 X-Sent-Cookie2: $cookie2 |
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
2541 X-Sent-Cookie-a: $cookie_a |
5a85ad9382a3
Tests: more Cookie tests for HTTP/2.
Sergey Kandaurov <pluknet@nginx.com>
parents:
651
diff
changeset
|
2542 X-Sent-Cookie-c: $cookie_c |
646 | 2543 |
2544 EOF | |
2545 | |
2546 } elsif ($uri eq '/set-cookie') { | |
2547 | |
2548 print $client <<EOF; | |
2549 HTTP/1.1 200 OK | |
2550 Connection: close | |
2551 Set-Cookie: a=b | |
2552 Set-Cookie: c=d | |
2553 | |
2554 EOF | |
2555 | |
2556 } | |
2557 | |
2558 } continue { | |
2559 close $client; | |
2560 } | |
2561 } | |
2562 | |
2563 ############################################################################### |