Mercurial > hg > nginx-tests
comparison h2_headers.t @ 948:4dc302d8e04f
Tests: changed HTTP2 package to act as a class.
Stopped exporting any subroutines. A subset of them now act as class methods.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Fri, 17 Jun 2016 11:36:33 +0300 |
parents | d73bef563aea |
children | e9064d691790 |
comparison
equal
deleted
inserted
replaced
947:b9e42c554ba7 | 948:4dc302d8e04f |
---|---|
15 | 15 |
16 BEGIN { use FindBin; chdir($FindBin::Bin); } | 16 BEGIN { use FindBin; chdir($FindBin::Bin); } |
17 | 17 |
18 use lib 'lib'; | 18 use lib 'lib'; |
19 use Test::Nginx; | 19 use Test::Nginx; |
20 use Test::Nginx::HTTP2 qw/ :DEFAULT :frame /; | 20 use Test::Nginx::HTTP2; |
21 | 21 |
22 ############################################################################### | 22 ############################################################################### |
23 | 23 |
24 select STDERR; $| = 1; | 24 select STDERR; $| = 1; |
25 select STDOUT; $| = 1; | 25 select STDOUT; $| = 1; |
124 | 124 |
125 ############################################################################### | 125 ############################################################################### |
126 | 126 |
127 # 6.1. Indexed Header Field Representation | 127 # 6.1. Indexed Header Field Representation |
128 | 128 |
129 my $sess = new_session(); | 129 my $s = Test::Nginx::HTTP2->new(); |
130 my $sid = new_stream($sess, { headers => [ | 130 my $sid = $s->new_stream({ headers => [ |
131 { name => ':method', value => 'GET', mode => 0 }, | 131 { name => ':method', value => 'GET', mode => 0 }, |
132 { name => ':scheme', value => 'http', mode => 0 }, | 132 { name => ':scheme', value => 'http', mode => 0 }, |
133 { name => ':path', value => '/', mode => 0 }, | 133 { name => ':path', value => '/', mode => 0 }, |
134 { name => ':authority', value => 'localhost', mode => 1 }]}); | 134 { name => ':authority', value => 'localhost', mode => 1 }]}); |
135 my $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 135 my $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
136 | 136 |
137 my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 137 my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
138 is($frame->{headers}->{':status'}, 200, 'indexed header field'); | 138 is($frame->{headers}->{':status'}, 200, 'indexed header field'); |
139 | 139 |
140 # 6.2.1. Literal Header Field with Incremental Indexing | 140 # 6.2.1. Literal Header Field with Incremental Indexing |
141 | 141 |
142 $sess = new_session(); | 142 $s = Test::Nginx::HTTP2->new(); |
143 $sid = new_stream($sess, { headers => [ | 143 $sid = $s->new_stream({ headers => [ |
144 { name => ':method', value => 'GET', mode => 1, huff => 0 }, | 144 { name => ':method', value => 'GET', mode => 1, huff => 0 }, |
145 { name => ':scheme', value => 'http', mode => 1, huff => 0 }, | 145 { name => ':scheme', value => 'http', mode => 1, huff => 0 }, |
146 { name => ':path', value => '/', mode => 1, huff => 0 }, | 146 { name => ':path', value => '/', mode => 1, huff => 0 }, |
147 { name => ':authority', value => 'localhost', mode => 1, huff => 0 }]}); | 147 { name => ':authority', value => 'localhost', mode => 1, huff => 0 }]}); |
148 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 148 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
149 | 149 |
150 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 150 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
151 is($frame->{headers}->{':status'}, 200, 'literal with indexing'); | 151 is($frame->{headers}->{':status'}, 200, 'literal with indexing'); |
152 | 152 |
153 $sess = new_session(); | 153 $s = Test::Nginx::HTTP2->new(); |
154 $sid = new_stream($sess, { headers => [ | 154 $sid = $s->new_stream({ headers => [ |
155 { name => ':method', value => 'GET', mode => 1, huff => 1 }, | 155 { name => ':method', value => 'GET', mode => 1, huff => 1 }, |
156 { name => ':scheme', value => 'http', mode => 1, huff => 1 }, | 156 { name => ':scheme', value => 'http', mode => 1, huff => 1 }, |
157 { name => ':path', value => '/', mode => 1, huff => 1 }, | 157 { name => ':path', value => '/', mode => 1, huff => 1 }, |
158 { name => ':authority', value => 'localhost', mode => 1, huff => 1 }]}); | 158 { name => ':authority', value => 'localhost', mode => 1, huff => 1 }]}); |
159 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 159 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
160 | 160 |
161 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 161 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
162 is($frame->{headers}->{':status'}, 200, 'literal with indexing - huffman'); | 162 is($frame->{headers}->{':status'}, 200, 'literal with indexing - huffman'); |
163 | 163 |
164 # 6.2.1. Literal Header Field with Incremental Indexing -- New Name | 164 # 6.2.1. Literal Header Field with Incremental Indexing -- New Name |
165 | 165 |
166 $sess = new_session(); | 166 $s = Test::Nginx::HTTP2->new(); |
167 $sid = new_stream($sess, { headers => [ | 167 $sid = $s->new_stream({ headers => [ |
168 { name => ':method', value => 'GET', mode => 2, huff => 0 }, | 168 { name => ':method', value => 'GET', mode => 2, huff => 0 }, |
169 { name => ':scheme', value => 'http', mode => 2, huff => 0 }, | 169 { name => ':scheme', value => 'http', mode => 2, huff => 0 }, |
170 { name => ':path', value => '/', mode => 2, huff => 0 }, | 170 { name => ':path', value => '/', mode => 2, huff => 0 }, |
171 { name => ':authority', value => 'localhost', mode => 2, huff => 0 }]}); | 171 { name => ':authority', value => 'localhost', mode => 2, huff => 0 }]}); |
172 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 172 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
173 | 173 |
174 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 174 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
175 is($frame->{headers}->{':status'}, 200, 'literal with indexing - new'); | 175 is($frame->{headers}->{':status'}, 200, 'literal with indexing - new'); |
176 | 176 |
177 $sess = new_session(); | 177 $s = Test::Nginx::HTTP2->new(); |
178 $sid = new_stream($sess, { headers => [ | 178 $sid = $s->new_stream({ headers => [ |
179 { name => ':method', value => 'GET', mode => 2, huff => 1 }, | 179 { name => ':method', value => 'GET', mode => 2, huff => 1 }, |
180 { name => ':scheme', value => 'http', mode => 2, huff => 1 }, | 180 { name => ':scheme', value => 'http', mode => 2, huff => 1 }, |
181 { name => ':path', value => '/', mode => 2, huff => 1 }, | 181 { name => ':path', value => '/', mode => 2, huff => 1 }, |
182 { name => ':authority', value => 'localhost', mode => 2, huff => 1 }]}); | 182 { name => ':authority', value => 'localhost', mode => 2, huff => 1 }]}); |
183 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 183 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
184 | 184 |
185 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 185 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
186 is($frame->{headers}->{':status'}, 200, 'literal with indexing - new huffman'); | 186 is($frame->{headers}->{':status'}, 200, 'literal with indexing - new huffman'); |
187 | 187 |
188 # 6.2.2. Literal Header Field without Indexing | 188 # 6.2.2. Literal Header Field without Indexing |
189 | 189 |
190 $sess = new_session(); | 190 $s = Test::Nginx::HTTP2->new(); |
191 $sid = new_stream($sess, { headers => [ | 191 $sid = $s->new_stream({ headers => [ |
192 { name => ':method', value => 'GET', mode => 3, huff => 0 }, | 192 { name => ':method', value => 'GET', mode => 3, huff => 0 }, |
193 { name => ':scheme', value => 'http', mode => 3, huff => 0 }, | 193 { name => ':scheme', value => 'http', mode => 3, huff => 0 }, |
194 { name => ':path', value => '/', mode => 3, huff => 0 }, | 194 { name => ':path', value => '/', mode => 3, huff => 0 }, |
195 { name => ':authority', value => 'localhost', mode => 3, huff => 0 }]}); | 195 { name => ':authority', value => 'localhost', mode => 3, huff => 0 }]}); |
196 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 196 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
197 | 197 |
198 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 198 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
199 is($frame->{headers}->{':status'}, 200, 'literal without indexing'); | 199 is($frame->{headers}->{':status'}, 200, 'literal without indexing'); |
200 | 200 |
201 $sess = new_session(); | 201 $s = Test::Nginx::HTTP2->new(); |
202 $sid = new_stream($sess, { headers => [ | 202 $sid = $s->new_stream({ headers => [ |
203 { name => ':method', value => 'GET', mode => 3, huff => 1 }, | 203 { name => ':method', value => 'GET', mode => 3, huff => 1 }, |
204 { name => ':scheme', value => 'http', mode => 3, huff => 1 }, | 204 { name => ':scheme', value => 'http', mode => 3, huff => 1 }, |
205 { name => ':path', value => '/', mode => 3, huff => 1 }, | 205 { name => ':path', value => '/', mode => 3, huff => 1 }, |
206 { name => ':authority', value => 'localhost', mode => 3, huff => 1 }]}); | 206 { name => ':authority', value => 'localhost', mode => 3, huff => 1 }]}); |
207 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 207 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
208 | 208 |
209 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 209 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
210 is($frame->{headers}->{':status'}, 200, 'literal without indexing - huffman'); | 210 is($frame->{headers}->{':status'}, 200, 'literal without indexing - huffman'); |
211 | 211 |
212 $sess = new_session(); | 212 $s = Test::Nginx::HTTP2->new(); |
213 $sid = new_stream($sess, { headers => [ | 213 $sid = $s->new_stream({ headers => [ |
214 { name => ':method', value => 'GET', mode => 3, huff => 0 }, | 214 { name => ':method', value => 'GET', mode => 3, huff => 0 }, |
215 { name => ':scheme', value => 'http', mode => 3, huff => 0 }, | 215 { name => ':scheme', value => 'http', mode => 3, huff => 0 }, |
216 { name => ':path', value => '/', mode => 3, huff => 0 }, | 216 { name => ':path', value => '/', mode => 3, huff => 0 }, |
217 { name => ':authority', value => 'localhost', mode => 3, huff => 0 }, | 217 { name => ':authority', value => 'localhost', mode => 3, huff => 0 }, |
218 { name => 'referer', value => 'foo', mode => 3, huff => 0 }]}); | 218 { name => 'referer', value => 'foo', mode => 3, huff => 0 }]}); |
219 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 219 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
220 | 220 |
221 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 221 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
222 is($frame->{headers}->{':status'}, 200, | 222 is($frame->{headers}->{':status'}, 200, |
223 'literal without indexing - multibyte index'); | 223 'literal without indexing - multibyte index'); |
224 is($frame->{headers}->{'x-referer'}, 'foo', | 224 is($frame->{headers}->{'x-referer'}, 'foo', |
225 'literal without indexing - multibyte index value'); | 225 'literal without indexing - multibyte index value'); |
226 | 226 |
227 # 6.2.2. Literal Header Field without Indexing -- New Name | 227 # 6.2.2. Literal Header Field without Indexing -- New Name |
228 | 228 |
229 $sess = new_session(); | 229 $s = Test::Nginx::HTTP2->new(); |
230 $sid = new_stream($sess, { headers => [ | 230 $sid = $s->new_stream({ headers => [ |
231 { name => ':method', value => 'GET', mode => 4, huff => 0 }, | 231 { name => ':method', value => 'GET', mode => 4, huff => 0 }, |
232 { name => ':scheme', value => 'http', mode => 4, huff => 0 }, | 232 { name => ':scheme', value => 'http', mode => 4, huff => 0 }, |
233 { name => ':path', value => '/', mode => 4, huff => 0 }, | 233 { name => ':path', value => '/', mode => 4, huff => 0 }, |
234 { name => ':authority', value => 'localhost', mode => 4, huff => 0 }]}); | 234 { name => ':authority', value => 'localhost', mode => 4, huff => 0 }]}); |
235 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 235 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
236 | 236 |
237 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 237 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
238 is($frame->{headers}->{':status'}, 200, 'literal without indexing - new'); | 238 is($frame->{headers}->{':status'}, 200, 'literal without indexing - new'); |
239 | 239 |
240 $sess = new_session(); | 240 $s = Test::Nginx::HTTP2->new(); |
241 $sid = new_stream($sess, { headers => [ | 241 $sid = $s->new_stream({ headers => [ |
242 { name => ':method', value => 'GET', mode => 4, huff => 1 }, | 242 { name => ':method', value => 'GET', mode => 4, huff => 1 }, |
243 { name => ':scheme', value => 'http', mode => 4, huff => 1 }, | 243 { name => ':scheme', value => 'http', mode => 4, huff => 1 }, |
244 { name => ':path', value => '/', mode => 4, huff => 1 }, | 244 { name => ':path', value => '/', mode => 4, huff => 1 }, |
245 { name => ':authority', value => 'localhost', mode => 4, huff => 1 }]}); | 245 { name => ':authority', value => 'localhost', mode => 4, huff => 1 }]}); |
246 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 246 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
247 | 247 |
248 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 248 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
249 is($frame->{headers}->{':status'}, 200, | 249 is($frame->{headers}->{':status'}, 200, |
250 'literal without indexing - new huffman'); | 250 'literal without indexing - new huffman'); |
251 | 251 |
252 # 6.2.3. Literal Header Field Never Indexed | 252 # 6.2.3. Literal Header Field Never Indexed |
253 | 253 |
254 $sess = new_session(); | 254 $s = Test::Nginx::HTTP2->new(); |
255 $sid = new_stream($sess, { headers => [ | 255 $sid = $s->new_stream({ headers => [ |
256 { name => ':method', value => 'GET', mode => 5, huff => 0 }, | 256 { name => ':method', value => 'GET', mode => 5, huff => 0 }, |
257 { name => ':scheme', value => 'http', mode => 5, huff => 0 }, | 257 { name => ':scheme', value => 'http', mode => 5, huff => 0 }, |
258 { name => ':path', value => '/', mode => 5, huff => 0 }, | 258 { name => ':path', value => '/', mode => 5, huff => 0 }, |
259 { name => ':authority', value => 'localhost', mode => 5, huff => 0 }]}); | 259 { name => ':authority', value => 'localhost', mode => 5, huff => 0 }]}); |
260 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 260 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
261 | 261 |
262 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 262 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
263 is($frame->{headers}->{':status'}, 200, 'literal never indexed'); | 263 is($frame->{headers}->{':status'}, 200, 'literal never indexed'); |
264 | 264 |
265 $sess = new_session(); | 265 $s = Test::Nginx::HTTP2->new(); |
266 $sid = new_stream($sess, { headers => [ | 266 $sid = $s->new_stream({ headers => [ |
267 { name => ':method', value => 'GET', mode => 5, huff => 1 }, | 267 { name => ':method', value => 'GET', mode => 5, huff => 1 }, |
268 { name => ':scheme', value => 'http', mode => 5, huff => 1 }, | 268 { name => ':scheme', value => 'http', mode => 5, huff => 1 }, |
269 { name => ':path', value => '/', mode => 5, huff => 1 }, | 269 { name => ':path', value => '/', mode => 5, huff => 1 }, |
270 { name => ':authority', value => 'localhost', mode => 5, huff => 1 }]}); | 270 { name => ':authority', value => 'localhost', mode => 5, huff => 1 }]}); |
271 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 271 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
272 | 272 |
273 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 273 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
274 is($frame->{headers}->{':status'}, 200, 'literal never indexed - huffman'); | 274 is($frame->{headers}->{':status'}, 200, 'literal never indexed - huffman'); |
275 | 275 |
276 $sess = new_session(); | 276 $s = Test::Nginx::HTTP2->new(); |
277 $sid = new_stream($sess, { headers => [ | 277 $sid = $s->new_stream({ headers => [ |
278 { name => ':method', value => 'GET', mode => 5, huff => 0 }, | 278 { name => ':method', value => 'GET', mode => 5, huff => 0 }, |
279 { name => ':scheme', value => 'http', mode => 5, huff => 0 }, | 279 { name => ':scheme', value => 'http', mode => 5, huff => 0 }, |
280 { name => ':path', value => '/', mode => 5, huff => 0 }, | 280 { name => ':path', value => '/', mode => 5, huff => 0 }, |
281 { name => ':authority', value => 'localhost', mode => 5, huff => 0 }, | 281 { name => ':authority', value => 'localhost', mode => 5, huff => 0 }, |
282 { name => 'referer', value => 'foo', mode => 5, huff => 0 }]}); | 282 { name => 'referer', value => 'foo', mode => 5, huff => 0 }]}); |
283 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 283 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
284 | 284 |
285 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 285 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
286 is($frame->{headers}->{':status'}, 200, | 286 is($frame->{headers}->{':status'}, 200, |
287 'literal never indexed - multibyte index'); | 287 'literal never indexed - multibyte index'); |
288 is($frame->{headers}->{'x-referer'}, 'foo', | 288 is($frame->{headers}->{'x-referer'}, 'foo', |
289 'literal never indexed - multibyte index value'); | 289 'literal never indexed - multibyte index value'); |
290 | 290 |
291 # 6.2.3. Literal Header Field Never Indexed -- New Name | 291 # 6.2.3. Literal Header Field Never Indexed -- New Name |
292 | 292 |
293 $sess = new_session(); | 293 $s = Test::Nginx::HTTP2->new(); |
294 $sid = new_stream($sess, { headers => [ | 294 $sid = $s->new_stream({ headers => [ |
295 { name => ':method', value => 'GET', mode => 6, huff => 0 }, | 295 { name => ':method', value => 'GET', mode => 6, huff => 0 }, |
296 { name => ':scheme', value => 'http', mode => 6, huff => 0 }, | 296 { name => ':scheme', value => 'http', mode => 6, huff => 0 }, |
297 { name => ':path', value => '/', mode => 6, huff => 0 }, | 297 { name => ':path', value => '/', mode => 6, huff => 0 }, |
298 { name => ':authority', value => 'localhost', mode => 6, huff => 0 }]}); | 298 { name => ':authority', value => 'localhost', mode => 6, huff => 0 }]}); |
299 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 299 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
300 | 300 |
301 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 301 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
302 is($frame->{headers}->{':status'}, 200, 'literal never indexed - new'); | 302 is($frame->{headers}->{':status'}, 200, 'literal never indexed - new'); |
303 | 303 |
304 $sess = new_session(); | 304 $s = Test::Nginx::HTTP2->new(); |
305 $sid = new_stream($sess, { headers => [ | 305 $sid = $s->new_stream({ headers => [ |
306 { name => ':method', value => 'GET', mode => 6, huff => 1 }, | 306 { name => ':method', value => 'GET', mode => 6, huff => 1 }, |
307 { name => ':scheme', value => 'http', mode => 6, huff => 1 }, | 307 { name => ':scheme', value => 'http', mode => 6, huff => 1 }, |
308 { name => ':path', value => '/', mode => 6, huff => 1 }, | 308 { name => ':path', value => '/', mode => 6, huff => 1 }, |
309 { name => ':authority', value => 'localhost', mode => 6, huff => 1 }]}); | 309 { name => ':authority', value => 'localhost', mode => 6, huff => 1 }]}); |
310 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 310 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
311 | 311 |
312 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 312 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
313 is($frame->{headers}->{':status'}, 200, 'literal never indexed - new huffman'); | 313 is($frame->{headers}->{':status'}, 200, 'literal never indexed - new huffman'); |
314 | 314 |
315 # reuse literal with multibyte indexing | 315 # reuse literal with multibyte indexing |
316 | 316 |
317 $sess = new_session(); | 317 $s = Test::Nginx::HTTP2->new(); |
318 $sid = new_stream($sess, { headers => [ | 318 $sid = $s->new_stream({ headers => [ |
319 { name => ':method', value => 'GET', mode => 0 }, | 319 { name => ':method', value => 'GET', mode => 0 }, |
320 { name => ':scheme', value => 'http', mode => 0 }, | 320 { name => ':scheme', value => 'http', mode => 0 }, |
321 { name => ':path', value => '/', mode => 0 }, | 321 { name => ':path', value => '/', mode => 0 }, |
322 { name => ':authority', value => 'localhost', mode => 1 }, | 322 { name => ':authority', value => 'localhost', mode => 1 }, |
323 { name => 'referer', value => 'foo', mode => 1 }]}); | 323 { name => 'referer', value => 'foo', mode => 1 }]}); |
324 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 324 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
325 | 325 |
326 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 326 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
327 is($frame->{headers}->{'x-referer'}, 'foo', 'value with indexing - new'); | 327 is($frame->{headers}->{'x-referer'}, 'foo', 'value with indexing - new'); |
328 | 328 |
329 $sid = new_stream($sess, { headers => [ | 329 $sid = $s->new_stream({ headers => [ |
330 { name => ':method', value => 'GET', mode => 0 }, | 330 { name => ':method', value => 'GET', mode => 0 }, |
331 { name => ':scheme', value => 'http', mode => 0 }, | 331 { name => ':scheme', value => 'http', mode => 0 }, |
332 { name => ':path', value => '/', mode => 0 }, | 332 { name => ':path', value => '/', mode => 0 }, |
333 { name => ':authority', value => 'localhost', mode => 0 }, | 333 { name => ':authority', value => 'localhost', mode => 0 }, |
334 { name => 'referer', value => 'foo', mode => 0 }]}); | 334 { name => 'referer', value => 'foo', mode => 0 }]}); |
335 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 335 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
336 | 336 |
337 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 337 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
338 is($frame->{headers}->{'x-referer'}, 'foo', 'value with indexing - indexed'); | 338 is($frame->{headers}->{'x-referer'}, 'foo', 'value with indexing - indexed'); |
339 | 339 |
340 $sess = new_session(); | 340 $s = Test::Nginx::HTTP2->new(); |
341 $sid = new_stream($sess, { headers => [ | 341 $sid = $s->new_stream({ headers => [ |
342 { name => ':method', value => 'GET', mode => 0 }, | 342 { name => ':method', value => 'GET', mode => 0 }, |
343 { name => ':scheme', value => 'http', mode => 0 }, | 343 { name => ':scheme', value => 'http', mode => 0 }, |
344 { name => ':path', value => '/', mode => 0 }, | 344 { name => ':path', value => '/', mode => 0 }, |
345 { name => ':authority', value => 'localhost', mode => 1 }, | 345 { name => ':authority', value => 'localhost', mode => 1 }, |
346 { name => 'x-foo', value => 'X-Bar', mode => 2 }]}); | 346 { name => 'x-foo', value => 'X-Bar', mode => 2 }]}); |
347 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 347 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
348 | 348 |
349 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 349 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
350 is($frame->{headers}->{'x-sent-foo'}, 'X-Bar', 'name with indexing - new'); | 350 is($frame->{headers}->{'x-sent-foo'}, 'X-Bar', 'name with indexing - new'); |
351 | 351 |
352 # reuse literal with multibyte indexing - reused name | 352 # reuse literal with multibyte indexing - reused name |
353 | 353 |
354 $sid = new_stream($sess, { headers => [ | 354 $sid = $s->new_stream({ headers => [ |
355 { name => ':method', value => 'GET', mode => 0 }, | 355 { name => ':method', value => 'GET', mode => 0 }, |
356 { name => ':scheme', value => 'http', mode => 0 }, | 356 { name => ':scheme', value => 'http', mode => 0 }, |
357 { name => ':path', value => '/', mode => 0 }, | 357 { name => ':path', value => '/', mode => 0 }, |
358 { name => ':authority', value => 'localhost', mode => 0 }, | 358 { name => ':authority', value => 'localhost', mode => 0 }, |
359 { name => 'x-foo', value => 'X-Bar', mode => 0 }]}); | 359 { name => 'x-foo', value => 'X-Bar', mode => 0 }]}); |
360 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 360 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
361 | 361 |
362 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 362 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
363 is($frame->{headers}->{'x-sent-foo'}, 'X-Bar', 'name with indexing - indexed'); | 363 is($frame->{headers}->{'x-sent-foo'}, 'X-Bar', 'name with indexing - indexed'); |
364 | 364 |
365 # reuse literal with multibyte indexing - reused name only | 365 # reuse literal with multibyte indexing - reused name only |
366 | 366 |
367 $sid = new_stream($sess, { headers => [ | 367 $sid = $s->new_stream({ headers => [ |
368 { name => ':method', value => 'GET', mode => 0 }, | 368 { name => ':method', value => 'GET', mode => 0 }, |
369 { name => ':scheme', value => 'http', mode => 0 }, | 369 { name => ':scheme', value => 'http', mode => 0 }, |
370 { name => ':path', value => '/', mode => 0 }, | 370 { name => ':path', value => '/', mode => 0 }, |
371 { name => ':authority', value => 'localhost', mode => 0 }, | 371 { name => ':authority', value => 'localhost', mode => 0 }, |
372 { name => 'x-foo', value => 'X-Baz', mode => 1 }]}); | 372 { name => 'x-foo', value => 'X-Baz', mode => 1 }]}); |
373 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 373 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
374 | 374 |
375 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 375 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
376 is($frame->{headers}->{'x-sent-foo'}, 'X-Baz', | 376 is($frame->{headers}->{'x-sent-foo'}, 'X-Baz', |
377 'name with indexing - indexed name'); | 377 'name with indexing - indexed name'); |
378 | 378 |
379 # response header field with characters not suitable for huffman encoding | 379 # response header field with characters not suitable for huffman encoding |
380 | 380 |
381 $sess = new_session(); | 381 $s = Test::Nginx::HTTP2->new(); |
382 $sid = new_stream($sess, { headers => [ | 382 $sid = $s->new_stream({ headers => [ |
383 { name => ':method', value => 'GET', mode => 0 }, | 383 { name => ':method', value => 'GET', mode => 0 }, |
384 { name => ':scheme', value => 'http', mode => 0 }, | 384 { name => ':scheme', value => 'http', mode => 0 }, |
385 { name => ':path', value => '/', mode => 0 }, | 385 { name => ':path', value => '/', mode => 0 }, |
386 { name => ':authority', value => 'localhost', mode => 1 }, | 386 { name => ':authority', value => 'localhost', mode => 1 }, |
387 { name => 'x-foo', value => '{{{{{', mode => 2 }]}); | 387 { name => 'x-foo', value => '{{{{{', mode => 2 }]}); |
388 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 388 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
389 | 389 |
390 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 390 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
391 is($frame->{headers}->{'x-sent-foo'}, '{{{{{', 'rare chars'); | 391 is($frame->{headers}->{'x-sent-foo'}, '{{{{{', 'rare chars'); |
392 like($sess->{headers}, qr/\Q{{{{{/, 'rare chars - no huffman encoding'); | 392 like($s->{headers}, qr/\Q{{{{{/, 'rare chars - no huffman encoding'); |
393 | 393 |
394 # response header field with huffman encoding | 394 # response header field with huffman encoding |
395 # NB: implementation detail, not obligated | 395 # NB: implementation detail, not obligated |
396 | 396 |
397 $sess = new_session(); | 397 $s = Test::Nginx::HTTP2->new(); |
398 $sid = new_stream($sess, { headers => [ | 398 $sid = $s->new_stream({ headers => [ |
399 { name => ':method', value => 'GET', mode => 0 }, | 399 { name => ':method', value => 'GET', mode => 0 }, |
400 { name => ':scheme', value => 'http', mode => 0 }, | 400 { name => ':scheme', value => 'http', mode => 0 }, |
401 { name => ':path', value => '/', mode => 0 }, | 401 { name => ':path', value => '/', mode => 0 }, |
402 { name => ':authority', value => 'localhost', mode => 1 }, | 402 { name => ':authority', value => 'localhost', mode => 1 }, |
403 { name => 'x-foo', value => 'aaaaa', mode => 2 }]}); | 403 { name => 'x-foo', value => 'aaaaa', mode => 2 }]}); |
404 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 404 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
405 | 405 |
406 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 406 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
407 is($frame->{headers}->{'x-sent-foo'}, 'aaaaa', 'well known chars'); | 407 is($frame->{headers}->{'x-sent-foo'}, 'aaaaa', 'well known chars'); |
408 | 408 |
409 TODO: { | 409 TODO: { |
410 local $TODO = 'not yet' unless $t->has_version('1.9.12'); | 410 local $TODO = 'not yet' unless $t->has_version('1.9.12'); |
411 | 411 |
412 unlike($sess->{headers}, qr/aaaaa/, 'well known chars - huffman encoding'); | 412 unlike($s->{headers}, qr/aaaaa/, 'well known chars - huffman encoding'); |
413 | 413 |
414 } | 414 } |
415 | 415 |
416 # response header field with huffman encoding - complete table mod \0, CR, LF | 416 # response header field with huffman encoding - complete table mod \0, CR, LF |
417 # first saturate with short-encoded characters (NB: implementation detail) | 417 # first saturate with short-encoded characters (NB: implementation detail) |
418 | 418 |
419 my $field = pack "C*", ((map { 97 } (1 .. 862)), 1 .. 9, 11, 12, 14 .. 255); | 419 my $field = pack "C*", ((map { 97 } (1 .. 862)), 1 .. 9, 11, 12, 14 .. 255); |
420 | 420 |
421 $sess = new_session(); | 421 $s = Test::Nginx::HTTP2->new(); |
422 $sid = new_stream($sess, { headers => [ | 422 $sid = $s->new_stream({ headers => [ |
423 { name => ':method', value => 'GET', mode => 0 }, | 423 { name => ':method', value => 'GET', mode => 0 }, |
424 { name => ':scheme', value => 'http', mode => 0 }, | 424 { name => ':scheme', value => 'http', mode => 0 }, |
425 { name => ':path', value => '/', mode => 0 }, | 425 { name => ':path', value => '/', mode => 0 }, |
426 { name => ':authority', value => 'localhost', mode => 1 }, | 426 { name => ':authority', value => 'localhost', mode => 1 }, |
427 { name => 'x-foo', value => $field, mode => 2 }]}); | 427 { name => 'x-foo', value => $field, mode => 2 }]}); |
428 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 428 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
429 | 429 |
430 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 430 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
431 is($frame->{headers}->{'x-sent-foo'}, $field, 'all chars'); | 431 is($frame->{headers}->{'x-sent-foo'}, $field, 'all chars'); |
432 | 432 |
433 TODO: { | 433 TODO: { |
434 local $TODO = 'not yet' unless $t->has_version('1.9.12'); | 434 local $TODO = 'not yet' unless $t->has_version('1.9.12'); |
435 | 435 |
436 unlike($sess->{headers}, qr/abcde/, 'all chars - huffman encoding'); | 436 unlike($s->{headers}, qr/abcde/, 'all chars - huffman encoding'); |
437 | 437 |
438 } | 438 } |
439 | 439 |
440 # 6.3. Dynamic Table Size Update | 440 # 6.3. Dynamic Table Size Update |
441 | 441 |
442 # remove some indexed headers from the dynamic table | 442 # remove some indexed headers from the dynamic table |
443 # by maintaining dynamic table space only for index 0 | 443 # by maintaining dynamic table space only for index 0 |
444 # 'x-foo' has index 0, and 'referer' has index 1 | 444 # 'x-foo' has index 0, and 'referer' has index 1 |
445 | 445 |
446 $sess = new_session(); | 446 $s = Test::Nginx::HTTP2->new(); |
447 $sid = new_stream($sess, { headers => [ | 447 $sid = $s->new_stream({ headers => [ |
448 { name => ':method', value => 'GET', mode => 0 }, | 448 { name => ':method', value => 'GET', mode => 0 }, |
449 { name => ':scheme', value => 'http', mode => 0 }, | 449 { name => ':scheme', value => 'http', mode => 0 }, |
450 { name => ':path', value => '/', mode => 0 }, | 450 { name => ':path', value => '/', mode => 0 }, |
451 { name => ':authority', value => 'localhost', mode => 1 }, | 451 { name => ':authority', value => 'localhost', mode => 1 }, |
452 { name => 'referer', value => 'foo', mode => 1 }, | 452 { name => 'referer', value => 'foo', mode => 1 }, |
453 { name => 'x-foo', value => 'X-Bar', mode => 2 }]}); | 453 { name => 'x-foo', value => 'X-Bar', mode => 2 }]}); |
454 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 454 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
455 | 455 |
456 $sid = new_stream($sess, { table_size => 61, headers => [ | 456 $sid = $s->new_stream({ table_size => 61, headers => [ |
457 { name => ':method', value => 'GET', mode => 0 }, | 457 { name => ':method', value => 'GET', mode => 0 }, |
458 { name => ':scheme', value => 'http', mode => 0 }, | 458 { name => ':scheme', value => 'http', mode => 0 }, |
459 { name => ':path', value => '/', mode => 0 }, | 459 { name => ':path', value => '/', mode => 0 }, |
460 { name => 'x-foo', value => 'X-Bar', mode => 0 }, | 460 { name => 'x-foo', value => 'X-Bar', mode => 0 }, |
461 { name => ':authority', value => 'localhost', mode => 1 }]}); | 461 { name => ':authority', value => 'localhost', mode => 1 }]}); |
462 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 462 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
463 | 463 |
464 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 464 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
465 isnt($frame, undef, 'updated table size - remaining index'); | 465 isnt($frame, undef, 'updated table size - remaining index'); |
466 | 466 |
467 $sid = new_stream($sess, { headers => [ | 467 $sid = $s->new_stream({ headers => [ |
468 { name => ':method', value => 'GET', mode => 0 }, | 468 { name => ':method', value => 'GET', mode => 0 }, |
469 { name => ':scheme', value => 'http', mode => 0 }, | 469 { name => ':scheme', value => 'http', mode => 0 }, |
470 { name => ':path', value => '/', mode => 0 }, | 470 { name => ':path', value => '/', mode => 0 }, |
471 { name => ':authority', value => 'localhost', mode => 1 }, | 471 { name => ':authority', value => 'localhost', mode => 1 }, |
472 { name => 'referer', value => 'foo', mode => 0 }]}); | 472 { name => 'referer', value => 'foo', mode => 0 }]}); |
473 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 473 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
474 | 474 |
475 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 475 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
476 is($frame, undef, 'invalid index'); | 476 is($frame, undef, 'invalid index'); |
477 | 477 |
478 # 5.4.1. Connection Error Handling | 478 # 5.4.1. Connection Error Handling |
497 | 497 |
498 # RFC 7541, 6.1 Indexed Header Field Representation | 498 # RFC 7541, 6.1 Indexed Header Field Representation |
499 # The index value of 0 is not used. It MUST be treated as a decoding | 499 # The index value of 0 is not used. It MUST be treated as a decoding |
500 # error if found in an indexed header field representation. | 500 # error if found in an indexed header field representation. |
501 | 501 |
502 $sess = new_session(); | 502 $s = Test::Nginx::HTTP2->new(); |
503 $sid = new_stream($sess, { headers => [ | 503 $sid = $s->new_stream({ headers => [ |
504 { name => ':method', value => 'GET', mode => 0 }, | 504 { name => ':method', value => 'GET', mode => 0 }, |
505 { name => ':scheme', value => 'http', mode => 0 }, | 505 { name => ':scheme', value => 'http', mode => 0 }, |
506 { name => ':path', value => '/', mode => 0 }, | 506 { name => ':path', value => '/', mode => 0 }, |
507 { name => ':authority', value => 'localhost', mode => 1 }, | 507 { name => ':authority', value => 'localhost', mode => 1 }, |
508 { name => '', value => '', mode => 0 }]}); | 508 { name => '', value => '', mode => 0 }]}); |
509 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 509 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
510 | 510 |
511 ok($frame, 'zero index - GOAWAY'); | 511 ok($frame, 'zero index - GOAWAY'); |
512 is($frame->{code}, 9, 'zero index - GOAWAY COMPRESSION_ERROR'); | 512 is($frame->{code}, 9, 'zero index - GOAWAY COMPRESSION_ERROR'); |
513 | 513 |
514 # invalid table size update | 514 # invalid table size update |
515 | 515 |
516 $sess = new_session(); | 516 $s = Test::Nginx::HTTP2->new(); |
517 $sid = new_stream($sess, { table_size => 4097, headers => [ | 517 $sid = $s->new_stream({ table_size => 4097, headers => [ |
518 { name => ':method', value => 'GET', mode => 0 }, | 518 { name => ':method', value => 'GET', mode => 0 }, |
519 { name => ':scheme', value => 'http', mode => 0 }, | 519 { name => ':scheme', value => 'http', mode => 0 }, |
520 { name => ':path', value => '/', mode => 0 }, | 520 { name => ':path', value => '/', mode => 0 }, |
521 { name => 'x-foo', value => 'X-Bar', mode => 0 }, | 521 { name => 'x-foo', value => 'X-Bar', mode => 0 }, |
522 { name => ':authority', value => 'localhost', mode => 1 }]}); | 522 { name => ':authority', value => 'localhost', mode => 1 }]}); |
523 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 523 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
524 | 524 |
525 ($frame) = grep { $_->{type} eq "GOAWAY" } @$frames; | 525 ($frame) = grep { $_->{type} eq "GOAWAY" } @$frames; |
526 ok($frame, 'invalid table size - GOAWAY'); | 526 ok($frame, 'invalid table size - GOAWAY'); |
527 is($frame->{last_sid}, $sid, 'invalid table size - GOAWAY last stream'); | 527 is($frame->{last_sid}, $sid, 'invalid table size - GOAWAY last stream'); |
528 is($frame->{code}, 9, 'invalid table size - GOAWAY COMPRESSION_ERROR'); | 528 is($frame->{code}, 9, 'invalid table size - GOAWAY COMPRESSION_ERROR'); |
531 | 531 |
532 # 8.1.2.5. Compressing the Cookie Header Field | 532 # 8.1.2.5. Compressing the Cookie Header Field |
533 # To allow for better compression efficiency, the Cookie header field | 533 # To allow for better compression efficiency, the Cookie header field |
534 # MAY be split into separate header fields <..>. | 534 # MAY be split into separate header fields <..>. |
535 | 535 |
536 $sess = new_session(); | 536 $s = Test::Nginx::HTTP2->new(); |
537 $sid = new_stream($sess, { headers => [ | 537 $sid = $s->new_stream({ headers => [ |
538 { name => ':method', value => 'GET', mode => 0 }, | 538 { name => ':method', value => 'GET', mode => 0 }, |
539 { name => ':scheme', value => 'http', mode => 0 }, | 539 { name => ':scheme', value => 'http', mode => 0 }, |
540 { name => ':path', value => '/cookie', mode => 2 }, | 540 { name => ':path', value => '/cookie', mode => 2 }, |
541 { name => ':authority', value => 'localhost', mode => 1 }, | 541 { name => ':authority', value => 'localhost', mode => 1 }, |
542 { name => 'cookie', value => 'a=b', mode => 2}, | 542 { name => 'cookie', value => 'a=b', mode => 2}, |
543 { name => 'cookie', value => 'c=d', mode => 2}]}); | 543 { name => 'cookie', value => 'c=d', mode => 2}]}); |
544 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 544 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
545 | 545 |
546 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 546 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
547 is($frame->{headers}->{'x-cookie-a'}, 'b', | 547 is($frame->{headers}->{'x-cookie-a'}, 'b', |
548 'multiple request header fields - cookie'); | 548 'multiple request header fields - cookie'); |
549 is($frame->{headers}->{'x-cookie-c'}, 'd', | 549 is($frame->{headers}->{'x-cookie-c'}, 'd', |
557 # these MUST be concatenated into a single octet string | 557 # these MUST be concatenated into a single octet string |
558 # using the two-octet delimiter of 0x3B, 0x20 (the ASCII string "; ") | 558 # using the two-octet delimiter of 0x3B, 0x20 (the ASCII string "; ") |
559 # before being passed into a non-HTTP/2 context, such as an HTTP/1.1 | 559 # before being passed into a non-HTTP/2 context, such as an HTTP/1.1 |
560 # connection <..> | 560 # connection <..> |
561 | 561 |
562 $sess = new_session(); | 562 $s = Test::Nginx::HTTP2->new(); |
563 $sid = new_stream($sess, { headers => [ | 563 $sid = $s->new_stream({ headers => [ |
564 { name => ':method', value => 'GET', mode => 0 }, | 564 { name => ':method', value => 'GET', mode => 0 }, |
565 { name => ':scheme', value => 'http', mode => 0 }, | 565 { name => ':scheme', value => 'http', mode => 0 }, |
566 { name => ':path', value => '/proxy/cookie', mode => 2 }, | 566 { name => ':path', value => '/proxy/cookie', mode => 2 }, |
567 { name => ':authority', value => 'localhost', mode => 1 }, | 567 { name => ':authority', value => 'localhost', mode => 1 }, |
568 { name => 'cookie', value => 'a=b', mode => 2 }, | 568 { name => 'cookie', value => 'a=b', mode => 2 }, |
569 { name => 'cookie', value => 'c=d', mode => 2 }]}); | 569 { name => 'cookie', value => 'c=d', mode => 2 }]}); |
570 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 570 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
571 | 571 |
572 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 572 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
573 is($frame->{headers}->{'x-sent-cookie'}, 'a=b; c=d', | 573 is($frame->{headers}->{'x-sent-cookie'}, 'a=b; c=d', |
574 'multiple request header fields proxied - semi-colon'); | 574 'multiple request header fields proxied - semi-colon'); |
575 is($frame->{headers}->{'x-sent-cookie2'}, '', | 575 is($frame->{headers}->{'x-sent-cookie2'}, '', |
579 is($frame->{headers}->{'x-sent-cookie-c'}, 'd', | 579 is($frame->{headers}->{'x-sent-cookie-c'}, 'd', |
580 'multiple request header fields proxied - cookie 2'); | 580 'multiple request header fields proxied - cookie 2'); |
581 | 581 |
582 # response header field with multiple values | 582 # response header field with multiple values |
583 | 583 |
584 $sess = new_session(); | 584 $s = Test::Nginx::HTTP2->new(); |
585 $sid = new_stream($sess, { path => '/set-cookie' }); | 585 $sid = $s->new_stream({ path => '/set-cookie' }); |
586 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 586 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
587 | 587 |
588 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 588 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
589 is($frame->{headers}->{'set-cookie'}[0], 'a=b', | 589 is($frame->{headers}->{'set-cookie'}[0], 'a=b', |
590 'multiple response header fields - cookie'); | 590 'multiple response header fields - cookie'); |
591 is($frame->{headers}->{'set-cookie'}[1], 'c=d', | 591 is($frame->{headers}->{'set-cookie'}[1], 'c=d', |
592 'multiple response header fields - cookie 2'); | 592 'multiple response header fields - cookie 2'); |
593 | 593 |
594 # response header field with multiple values from HTTP backend | 594 # response header field with multiple values from HTTP backend |
595 | 595 |
596 $sess = new_session(); | 596 $s = Test::Nginx::HTTP2->new(); |
597 $sid = new_stream($sess, { path => '/proxy/set-cookie' }); | 597 $sid = $s->new_stream({ path => '/proxy/set-cookie' }); |
598 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 598 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
599 | 599 |
600 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 600 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
601 is($frame->{headers}->{'set-cookie'}[0], 'a=b', | 601 is($frame->{headers}->{'set-cookie'}[0], 'a=b', |
602 'multiple response header proxied - cookie'); | 602 'multiple response header proxied - cookie'); |
603 is($frame->{headers}->{'set-cookie'}[1], 'c=d', | 603 is($frame->{headers}->{'set-cookie'}[1], 'c=d', |
609 | 609 |
610 # CONTINUATION in response | 610 # CONTINUATION in response |
611 # put three long header fields (not less than SETTINGS_MAX_FRAME_SIZE/2) | 611 # put three long header fields (not less than SETTINGS_MAX_FRAME_SIZE/2) |
612 # to break header block into separate frames, one such field per frame | 612 # to break header block into separate frames, one such field per frame |
613 | 613 |
614 $sess = new_session(); | 614 $s = Test::Nginx::HTTP2->new(); |
615 $sid = new_stream($sess, { path => '/continuation?h=' . 'x' x 2**13 }); | 615 $sid = $s->new_stream({ path => '/continuation?h=' . 'x' x 2**13 }); |
616 | 616 |
617 $frames = h2_read($sess, all => [{ sid => $sid, fin => 0x4 }]); | 617 $frames = $s->read(all => [{ sid => $sid, fin => 0x4 }]); |
618 my @data = grep { $_->{type} =~ "HEADERS|CONTINUATION" } @$frames; | 618 my @data = grep { $_->{type} =~ "HEADERS|CONTINUATION" } @$frames; |
619 is(@{$data[-1]->{headers}{'x-longheader'}}, 3, | 619 is(@{$data[-1]->{headers}{'x-longheader'}}, 3, |
620 'response CONTINUATION - headers'); | 620 'response CONTINUATION - headers'); |
621 is($data[-1]->{headers}{'x-longheader'}[0], 'x' x 2**13, | 621 is($data[-1]->{headers}{'x-longheader'}[0], 'x' x 2**13, |
622 'response CONTINUATION - header 1'); | 622 'response CONTINUATION - header 1'); |
627 @data = sort { $a <=> $b } map { $_->{length} } @data; | 627 @data = sort { $a <=> $b } map { $_->{length} } @data; |
628 cmp_ok($data[-1], '<=', 2**14, 'response CONTINUATION - max frame size'); | 628 cmp_ok($data[-1], '<=', 2**14, 'response CONTINUATION - max frame size'); |
629 | 629 |
630 # same but without response DATA frames | 630 # same but without response DATA frames |
631 | 631 |
632 $sess = new_session(); | 632 $s = Test::Nginx::HTTP2->new(); |
633 $sid = new_stream($sess, { path => '/continuation/204?h=' . 'x' x 2**13 }); | 633 $sid = $s->new_stream({ path => '/continuation/204?h=' . 'x' x 2**13 }); |
634 | 634 |
635 $frames = h2_read($sess, all => [{ sid => $sid, fin => 0x4 }]); | 635 $frames = $s->read(all => [{ sid => $sid, fin => 0x4 }]); |
636 @data = grep { $_->{type} =~ "HEADERS|CONTINUATION" } @$frames; | 636 @data = grep { $_->{type} =~ "HEADERS|CONTINUATION" } @$frames; |
637 is(@{$data[-1]->{headers}{'x-longheader'}}, 3, | 637 is(@{$data[-1]->{headers}{'x-longheader'}}, 3, |
638 'no body CONTINUATION - headers'); | 638 'no body CONTINUATION - headers'); |
639 is($data[-1]->{headers}{'x-longheader'}[0], 'x' x 2**13, | 639 is($data[-1]->{headers}{'x-longheader'}[0], 'x' x 2**13, |
640 'no body CONTINUATION - header 1'); | 640 'no body CONTINUATION - header 1'); |
645 @data = sort { $a <=> $b } map { $_->{length} } @data; | 645 @data = sort { $a <=> $b } map { $_->{length} } @data; |
646 cmp_ok($data[-1], '<=', 2**14, 'no body CONTINUATION - max frame size'); | 646 cmp_ok($data[-1], '<=', 2**14, 'no body CONTINUATION - max frame size'); |
647 | 647 |
648 # response header block is always split by SETTINGS_MAX_FRAME_SIZE | 648 # response header block is always split by SETTINGS_MAX_FRAME_SIZE |
649 | 649 |
650 $sess = new_session(); | 650 $s = Test::Nginx::HTTP2->new(); |
651 $sid = new_stream($sess, { path => '/continuation?h=' . 'x' x 2**15 }); | 651 $sid = $s->new_stream({ path => '/continuation?h=' . 'x' x 2**15 }); |
652 | 652 |
653 $frames = h2_read($sess, all => [{ sid => $sid, fin => 0x4 }]); | 653 $frames = $s->read(all => [{ sid => $sid, fin => 0x4 }]); |
654 @data = grep { $_->{type} =~ "HEADERS|CONTINUATION" } @$frames; | 654 @data = grep { $_->{type} =~ "HEADERS|CONTINUATION" } @$frames; |
655 @data = sort { $a <=> $b } map { $_->{length} } @data; | 655 @data = sort { $a <=> $b } map { $_->{length} } @data; |
656 cmp_ok($data[-1], '<=', 2**14, 'response header frames limited'); | 656 cmp_ok($data[-1], '<=', 2**14, 'response header frames limited'); |
657 | 657 |
658 # response header frame sent in parts | 658 # response header frame sent in parts |
659 | 659 |
660 TODO: { | 660 TODO: { |
661 local $TODO = 'not yet' unless $t->has_version('1.9.7'); | 661 local $TODO = 'not yet' unless $t->has_version('1.9.7'); |
662 | 662 |
663 $sess = new_session(8082); | 663 $s = Test::Nginx::HTTP2->new(8082); |
664 h2_settings($sess, 0, 0x5 => 2**17); | 664 $s->h2_settings(0, 0x5 => 2**17); |
665 | 665 |
666 $sid = new_stream($sess, { path => '/frame_size?h=' . 'x' x 2**15 }); | 666 $sid = $s->new_stream({ path => '/frame_size?h=' . 'x' x 2**15 }); |
667 $frames = h2_read($sess, all => [{ sid => $sid, fin => 0x4 }]); | 667 $frames = $s->read(all => [{ sid => $sid, fin => 0x4 }]); |
668 | 668 |
669 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 669 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
670 ok($frame, 'response header - parts'); | 670 ok($frame, 'response header - parts'); |
671 | 671 |
672 SKIP: { | 672 SKIP: { |
677 | 677 |
678 } | 678 } |
679 | 679 |
680 # response header block split and sent in parts | 680 # response header block split and sent in parts |
681 | 681 |
682 $sess = new_session(8082); | 682 $s = Test::Nginx::HTTP2->new(8082); |
683 $sid = new_stream($sess, { path => '/continuation?h=' . 'x' x 2**15 }); | 683 $sid = $s->new_stream({ path => '/continuation?h=' . 'x' x 2**15 }); |
684 $frames = h2_read($sess, all => [{ sid => $sid, fin => 0x4 }]); | 684 $frames = $s->read(all => [{ sid => $sid, fin => 0x4 }]); |
685 | 685 |
686 @data = grep { $_->{type} =~ "HEADERS|CONTINUATION" } @$frames; | 686 @data = grep { $_->{type} =~ "HEADERS|CONTINUATION" } @$frames; |
687 my ($lengths) = sort { $b <=> $a } map { $_->{length} } @data; | 687 my ($lengths) = sort { $b <=> $a } map { $_->{length} } @data; |
688 cmp_ok($lengths, '<=', 16384, 'response header split - max size'); | 688 cmp_ok($lengths, '<=', 16384, 'response header split - max size'); |
689 | 689 |
692 | 692 |
693 } | 693 } |
694 | 694 |
695 # max_field_size - header field name | 695 # max_field_size - header field name |
696 | 696 |
697 $sess = new_session(8084); | 697 $s = Test::Nginx::HTTP2->new(8084); |
698 $sid = new_stream($sess, { headers => [ | 698 $sid = $s->new_stream({ headers => [ |
699 { name => ':method', value => 'GET', mode => 0 }, | 699 { name => ':method', value => 'GET', mode => 0 }, |
700 { name => ':scheme', value => 'http', mode => 0 }, | 700 { name => ':scheme', value => 'http', mode => 0 }, |
701 { name => ':path', value => '/t2.html', mode => 1 }, | 701 { name => ':path', value => '/t2.html', mode => 1 }, |
702 { name => ':authority', value => 'localhost', mode => 1 }, | 702 { name => ':authority', value => 'localhost', mode => 1 }, |
703 { name => 'longname10' x 2 . 'x', value => 'value', mode => 2 }]}); | 703 { name => 'longname10' x 2 . 'x', value => 'value', mode => 2 }]}); |
704 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 704 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
705 | 705 |
706 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; | 706 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; |
707 ok($frame, 'field name size less'); | 707 ok($frame, 'field name size less'); |
708 | 708 |
709 $sid = new_stream($sess, { headers => [ | 709 $sid = $s->new_stream({ headers => [ |
710 { name => ':method', value => 'GET', mode => 0 }, | 710 { name => ':method', value => 'GET', mode => 0 }, |
711 { name => ':scheme', value => 'http', mode => 0 }, | 711 { name => ':scheme', value => 'http', mode => 0 }, |
712 { name => ':path', value => '/t2.html', mode => 1 }, | 712 { name => ':path', value => '/t2.html', mode => 1 }, |
713 { name => ':authority', value => 'localhost', mode => 1 }, | 713 { name => ':authority', value => 'localhost', mode => 1 }, |
714 { name => 'longname10' x 2 . 'x', value => 'value', mode => 2 }]}); | 714 { name => 'longname10' x 2 . 'x', value => 'value', mode => 2 }]}); |
715 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 715 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
716 | 716 |
717 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; | 717 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; |
718 ok($frame, 'field name size second'); | 718 ok($frame, 'field name size second'); |
719 | 719 |
720 $sess = new_session(8084); | 720 $s = Test::Nginx::HTTP2->new(8084); |
721 $sid = new_stream($sess, { headers => [ | 721 $sid = $s->new_stream({ headers => [ |
722 { name => ':method', value => 'GET', mode => 0 }, | 722 { name => ':method', value => 'GET', mode => 0 }, |
723 { name => ':scheme', value => 'http', mode => 0 }, | 723 { name => ':scheme', value => 'http', mode => 0 }, |
724 { name => ':path', value => '/t2.html', mode => 1 }, | 724 { name => ':path', value => '/t2.html', mode => 1 }, |
725 { name => ':authority', value => 'localhost', mode => 1 }, | 725 { name => ':authority', value => 'localhost', mode => 1 }, |
726 { name => 'longname10' x 2 . 'xx', value => 'value', mode => 2 }]}); | 726 { name => 'longname10' x 2 . 'xx', value => 'value', mode => 2 }]}); |
727 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 727 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
728 | 728 |
729 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; | 729 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; |
730 ok($frame, 'field name size equal'); | 730 ok($frame, 'field name size equal'); |
731 | 731 |
732 $sess = new_session(8084); | 732 $s = Test::Nginx::HTTP2->new(8084); |
733 $sid = new_stream($sess, { headers => [ | 733 $sid = $s->new_stream({ headers => [ |
734 { name => ':method', value => 'GET', mode => 0 }, | 734 { name => ':method', value => 'GET', mode => 0 }, |
735 { name => ':scheme', value => 'http', mode => 0 }, | 735 { name => ':scheme', value => 'http', mode => 0 }, |
736 { name => ':path', value => '/t2.html', mode => 1 }, | 736 { name => ':path', value => '/t2.html', mode => 1 }, |
737 { name => ':authority', value => 'localhost', mode => 1 }, | 737 { name => ':authority', value => 'localhost', mode => 1 }, |
738 { name => 'longname10' x 2 . 'xxx', value => 'value', mode => 2 }]}); | 738 { name => 'longname10' x 2 . 'xxx', value => 'value', mode => 2 }]}); |
739 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 739 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
740 | 740 |
741 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; | 741 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; |
742 is($frame, undef, 'field name size greater'); | 742 is($frame, undef, 'field name size greater'); |
743 | 743 |
744 # max_field_size - header field value | 744 # max_field_size - header field value |
745 | 745 |
746 $sess = new_session(8084); | 746 $s = Test::Nginx::HTTP2->new(8084); |
747 $sid = new_stream($sess, { headers => [ | 747 $sid = $s->new_stream({ headers => [ |
748 { name => ':method', value => 'GET', mode => 0 }, | 748 { name => ':method', value => 'GET', mode => 0 }, |
749 { name => ':scheme', value => 'http', mode => 0 }, | 749 { name => ':scheme', value => 'http', mode => 0 }, |
750 { name => ':path', value => '/t2.html', mode => 1 }, | 750 { name => ':path', value => '/t2.html', mode => 1 }, |
751 { name => ':authority', value => 'localhost', mode => 1 }, | 751 { name => ':authority', value => 'localhost', mode => 1 }, |
752 { name => 'name', value => 'valu5' x 4 . 'x', mode => 2 }]}); | 752 { name => 'name', value => 'valu5' x 4 . 'x', mode => 2 }]}); |
753 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 753 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
754 | 754 |
755 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; | 755 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; |
756 ok($frame, 'field value size less'); | 756 ok($frame, 'field value size less'); |
757 | 757 |
758 $sess = new_session(8084); | 758 $s = Test::Nginx::HTTP2->new(8084); |
759 $sid = new_stream($sess, { headers => [ | 759 $sid = $s->new_stream({ headers => [ |
760 { name => ':method', value => 'GET', mode => 0 }, | 760 { name => ':method', value => 'GET', mode => 0 }, |
761 { name => ':scheme', value => 'http', mode => 0 }, | 761 { name => ':scheme', value => 'http', mode => 0 }, |
762 { name => ':path', value => '/t2.html', mode => 1 }, | 762 { name => ':path', value => '/t2.html', mode => 1 }, |
763 { name => ':authority', value => 'localhost', mode => 1 }, | 763 { name => ':authority', value => 'localhost', mode => 1 }, |
764 { name => 'name', value => 'valu5' x 4 . 'xx', mode => 2 }]}); | 764 { name => 'name', value => 'valu5' x 4 . 'xx', mode => 2 }]}); |
765 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 765 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
766 | 766 |
767 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; | 767 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; |
768 ok($frame, 'field value size equal'); | 768 ok($frame, 'field value size equal'); |
769 | 769 |
770 $sess = new_session(8084); | 770 $s = Test::Nginx::HTTP2->new(8084); |
771 $sid = new_stream($sess, { headers => [ | 771 $sid = $s->new_stream({ headers => [ |
772 { name => ':method', value => 'GET', mode => 0 }, | 772 { name => ':method', value => 'GET', mode => 0 }, |
773 { name => ':scheme', value => 'http', mode => 0 }, | 773 { name => ':scheme', value => 'http', mode => 0 }, |
774 { name => ':path', value => '/t2.html', mode => 1 }, | 774 { name => ':path', value => '/t2.html', mode => 1 }, |
775 { name => ':authority', value => 'localhost', mode => 1 }, | 775 { name => ':authority', value => 'localhost', mode => 1 }, |
776 { name => 'name', value => 'valu5' x 4 . 'xxx', mode => 2 }]}); | 776 { name => 'name', value => 'valu5' x 4 . 'xxx', mode => 2 }]}); |
777 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 777 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
778 | 778 |
779 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; | 779 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; |
780 is($frame, undef, 'field value size greater'); | 780 is($frame, undef, 'field value size greater'); |
781 | 781 |
782 # max_header_size | 782 # max_header_size |
783 | 783 |
784 $sess = new_session(8085); | 784 $s = Test::Nginx::HTTP2->new(8085); |
785 $sid = new_stream($sess, { headers => [ | 785 $sid = $s->new_stream({ headers => [ |
786 { name => ':method', value => 'GET', mode => 0 }, | 786 { name => ':method', value => 'GET', mode => 0 }, |
787 { name => ':scheme', value => 'http', mode => 0 }, | 787 { name => ':scheme', value => 'http', mode => 0 }, |
788 { name => ':path', value => '/t2.html', mode => 1 }, | 788 { name => ':path', value => '/t2.html', mode => 1 }, |
789 { name => ':authority', value => 'localhost', mode => 1 }, | 789 { name => ':authority', value => 'localhost', mode => 1 }, |
790 { name => 'longname9', value => 'x', mode => 2 }]}); | 790 { name => 'longname9', value => 'x', mode => 2 }]}); |
791 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 791 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
792 | 792 |
793 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; | 793 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; |
794 ok($frame, 'header size less'); | 794 ok($frame, 'header size less'); |
795 | 795 |
796 $sid = new_stream($sess, { headers => [ | 796 $sid = $s->new_stream({ headers => [ |
797 { name => ':method', value => 'GET', mode => 0 }, | 797 { name => ':method', value => 'GET', mode => 0 }, |
798 { name => ':scheme', value => 'http', mode => 0 }, | 798 { name => ':scheme', value => 'http', mode => 0 }, |
799 { name => ':path', value => '/t2.html', mode => 1 }, | 799 { name => ':path', value => '/t2.html', mode => 1 }, |
800 { name => ':authority', value => 'localhost', mode => 1 }, | 800 { name => ':authority', value => 'localhost', mode => 1 }, |
801 { name => 'longname9', value => 'x', mode => 2 }]}); | 801 { name => 'longname9', value => 'x', mode => 2 }]}); |
802 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 802 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
803 | 803 |
804 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; | 804 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; |
805 ok($frame, 'header size second'); | 805 ok($frame, 'header size second'); |
806 | 806 |
807 $sess = new_session(8085); | 807 $s = Test::Nginx::HTTP2->new(8085); |
808 $sid = new_stream($sess, { headers => [ | 808 $sid = $s->new_stream({ headers => [ |
809 { name => ':method', value => 'GET', mode => 0 }, | 809 { name => ':method', value => 'GET', mode => 0 }, |
810 { name => ':scheme', value => 'http', mode => 0 }, | 810 { name => ':scheme', value => 'http', mode => 0 }, |
811 { name => ':path', value => '/t2.html', mode => 1 }, | 811 { name => ':path', value => '/t2.html', mode => 1 }, |
812 { name => ':authority', value => 'localhost', mode => 1 }, | 812 { name => ':authority', value => 'localhost', mode => 1 }, |
813 { name => 'longname9', value => 'xx', mode => 2 }]}); | 813 { name => 'longname9', value => 'xx', mode => 2 }]}); |
814 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 814 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
815 | 815 |
816 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; | 816 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; |
817 ok($frame, 'header size equal'); | 817 ok($frame, 'header size equal'); |
818 | 818 |
819 $sess = new_session(8085); | 819 $s = Test::Nginx::HTTP2->new(8085); |
820 $sid = new_stream($sess, { headers => [ | 820 $sid = $s->new_stream({ headers => [ |
821 { name => ':method', value => 'GET', mode => 0 }, | 821 { name => ':method', value => 'GET', mode => 0 }, |
822 { name => ':scheme', value => 'http', mode => 0 }, | 822 { name => ':scheme', value => 'http', mode => 0 }, |
823 { name => ':path', value => '/t2.html', mode => 1 }, | 823 { name => ':path', value => '/t2.html', mode => 1 }, |
824 { name => ':authority', value => 'localhost', mode => 1 }, | 824 { name => ':authority', value => 'localhost', mode => 1 }, |
825 { name => 'longname9', value => 'xxx', mode => 2 }]}); | 825 { name => 'longname9', value => 'xxx', mode => 2 }]}); |
826 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 826 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
827 | 827 |
828 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; | 828 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; |
829 is($frame, undef, 'header size greater'); | 829 is($frame, undef, 'header size greater'); |
830 | 830 |
831 # header size is based on (decompressed) header list | 831 # header size is based on (decompressed) header list |
832 # two extra 1-byte indices would otherwise fit in max_header_size | 832 # two extra 1-byte indices would otherwise fit in max_header_size |
833 | 833 |
834 $sess = new_session(8085); | 834 $s = Test::Nginx::HTTP2->new(8085); |
835 $sid = new_stream($sess, { headers => [ | 835 $sid = $s->new_stream({ headers => [ |
836 { name => ':method', value => 'GET', mode => 0 }, | 836 { name => ':method', value => 'GET', mode => 0 }, |
837 { name => ':scheme', value => 'http', mode => 0 }, | 837 { name => ':scheme', value => 'http', mode => 0 }, |
838 { name => ':path', value => '/t2.html', mode => 1 }, | 838 { name => ':path', value => '/t2.html', mode => 1 }, |
839 { name => ':authority', value => 'localhost', mode => 1 }, | 839 { name => ':authority', value => 'localhost', mode => 1 }, |
840 { name => 'longname9', value => 'x', mode => 2 }]}); | 840 { name => 'longname9', value => 'x', mode => 2 }]}); |
841 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 841 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
842 | 842 |
843 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; | 843 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; |
844 ok($frame, 'header size new index'); | 844 ok($frame, 'header size new index'); |
845 | 845 |
846 $sid = new_stream($sess, { headers => [ | 846 $sid = $s->new_stream({ headers => [ |
847 { name => ':method', value => 'GET', mode => 0 }, | 847 { name => ':method', value => 'GET', mode => 0 }, |
848 { name => ':scheme', value => 'http', mode => 0 }, | 848 { name => ':scheme', value => 'http', mode => 0 }, |
849 { name => ':path', value => '/t2.html', mode => 1 }, | 849 { name => ':path', value => '/t2.html', mode => 1 }, |
850 { name => ':authority', value => 'localhost', mode => 1 }, | 850 { name => ':authority', value => 'localhost', mode => 1 }, |
851 { name => 'longname9', value => 'x', mode => 0 }]}); | 851 { name => 'longname9', value => 'x', mode => 0 }]}); |
852 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 852 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
853 | 853 |
854 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; | 854 ($frame) = grep { $_->{type} eq 'DATA' } @$frames; |
855 ok($frame, 'header size indexed'); | 855 ok($frame, 'header size indexed'); |
856 | 856 |
857 $sid = new_stream($sess, { headers => [ | 857 $sid = $s->new_stream({ headers => [ |
858 { name => ':method', value => 'GET', mode => 0 }, | 858 { name => ':method', value => 'GET', mode => 0 }, |
859 { name => ':scheme', value => 'http', mode => 0 }, | 859 { name => ':scheme', value => 'http', mode => 0 }, |
860 { name => ':path', value => '/t2.html', mode => 1 }, | 860 { name => ':path', value => '/t2.html', mode => 1 }, |
861 { name => ':authority', value => 'localhost', mode => 1 }, | 861 { name => ':authority', value => 'localhost', mode => 1 }, |
862 { name => 'longname9', value => 'x', mode => 0 }, | 862 { name => 'longname9', value => 'x', mode => 0 }, |
863 { name => 'longname9', value => 'x', mode => 0 }]}); | 863 { name => 'longname9', value => 'x', mode => 0 }]}); |
864 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 864 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
865 | 865 |
866 ($frame) = grep { $_->{type} eq 'GOAWAY' } @$frames; | 866 ($frame) = grep { $_->{type} eq 'GOAWAY' } @$frames; |
867 is($frame->{code}, 0xb, 'header size indexed greater'); | 867 is($frame->{code}, 0xb, 'header size indexed greater'); |
868 | 868 |
869 # HPACK table boundary | 869 # HPACK table boundary |
870 | 870 |
871 $sess = new_session(); | 871 $s = Test::Nginx::HTTP2->new(); |
872 h2_read($sess, all => [{ sid => new_stream($sess, { headers => [ | 872 $s->read(all => [{ sid => $s->new_stream({ headers => [ |
873 { name => ':method', value => 'GET', mode => 0 }, | 873 { name => ':method', value => 'GET', mode => 0 }, |
874 { name => ':scheme', value => 'http', mode => 0 }, | 874 { name => ':scheme', value => 'http', mode => 0 }, |
875 { name => ':path', value => '/', mode => 0 }, | 875 { name => ':path', value => '/', mode => 0 }, |
876 { name => ':authority', value => '', mode => 0 }, | 876 { name => ':authority', value => '', mode => 0 }, |
877 { name => 'x' x 2016, value => 'x' x 2048, mode => 2 }]}), fin => 1 }]); | 877 { name => 'x' x 2016, value => 'x' x 2048, mode => 2 }]}), fin => 1 }]); |
878 $frames = h2_read($sess, all => [{ sid => new_stream($sess, { headers => [ | 878 $frames = $s->read(all => [{ sid => $s->new_stream({ headers => [ |
879 { name => ':method', value => 'GET', mode => 0 }, | 879 { name => ':method', value => 'GET', mode => 0 }, |
880 { name => ':scheme', value => 'http', mode => 0 }, | 880 { name => ':scheme', value => 'http', mode => 0 }, |
881 { name => ':path', value => '/', mode => 0 }, | 881 { name => ':path', value => '/', mode => 0 }, |
882 { name => ':authority', value => '', mode => 0 }, | 882 { name => ':authority', value => '', mode => 0 }, |
883 { name => 'x' x 2016, value => 'x' x 2048, mode => 0 }]}), fin => 1 }]); | 883 { name => 'x' x 2016, value => 'x' x 2048, mode => 0 }]}), fin => 1 }]); |
884 | 884 |
885 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 885 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
886 ok($frame, 'HPACK table boundary'); | 886 ok($frame, 'HPACK table boundary'); |
887 | 887 |
888 h2_read($sess, all => [{ sid => new_stream($sess, { headers => [ | 888 $s->read(all => [{ sid => $s->new_stream({ headers => [ |
889 { name => ':method', value => 'GET', mode => 0 }, | 889 { name => ':method', value => 'GET', mode => 0 }, |
890 { name => ':scheme', value => 'http', mode => 0 }, | 890 { name => ':scheme', value => 'http', mode => 0 }, |
891 { name => ':path', value => '/', mode => 0 }, | 891 { name => ':path', value => '/', mode => 0 }, |
892 { name => ':authority', value => '', mode => 0 }, | 892 { name => ':authority', value => '', mode => 0 }, |
893 { name => 'x' x 33, value => 'x' x 4031, mode => 2 }]}), fin => 1 }]); | 893 { name => 'x' x 33, value => 'x' x 4031, mode => 2 }]}), fin => 1 }]); |
894 $frames = h2_read($sess, all => [{ sid => new_stream($sess, { headers => [ | 894 $frames = $s->read(all => [{ sid => $s->new_stream({ headers => [ |
895 { name => ':method', value => 'GET', mode => 0 }, | 895 { name => ':method', value => 'GET', mode => 0 }, |
896 { name => ':scheme', value => 'http', mode => 0 }, | 896 { name => ':scheme', value => 'http', mode => 0 }, |
897 { name => ':path', value => '/', mode => 0 }, | 897 { name => ':path', value => '/', mode => 0 }, |
898 { name => ':authority', value => '', mode => 0 }, | 898 { name => ':authority', value => '', mode => 0 }, |
899 { name => 'x' x 33, value => 'x' x 4031, mode => 0 }]}), fin => 1 }]); | 899 { name => 'x' x 33, value => 'x' x 4031, mode => 0 }]}), fin => 1 }]); |
900 | 900 |
901 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 901 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
902 ok($frame, 'HPACK table boundary - header field name'); | 902 ok($frame, 'HPACK table boundary - header field name'); |
903 | 903 |
904 h2_read($sess, all => [{ sid => new_stream($sess, { headers => [ | 904 $s->read(all => [{ sid => $s->new_stream({ headers => [ |
905 { name => ':method', value => 'GET', mode => 0 }, | 905 { name => ':method', value => 'GET', mode => 0 }, |
906 { name => ':scheme', value => 'http', mode => 0 }, | 906 { name => ':scheme', value => 'http', mode => 0 }, |
907 { name => ':path', value => '/', mode => 0 }, | 907 { name => ':path', value => '/', mode => 0 }, |
908 { name => ':authority', value => '', mode => 0 }, | 908 { name => ':authority', value => '', mode => 0 }, |
909 { name => 'x', value => 'x' x 64, mode => 2 }]}), fin => 1 }]); | 909 { name => 'x', value => 'x' x 64, mode => 2 }]}), fin => 1 }]); |
910 $frames = h2_read($sess, all => [{ sid => new_stream($sess, { headers => [ | 910 $frames = $s->read(all => [{ sid => $s->new_stream({ headers => [ |
911 { name => ':method', value => 'GET', mode => 0 }, | 911 { name => ':method', value => 'GET', mode => 0 }, |
912 { name => ':scheme', value => 'http', mode => 0 }, | 912 { name => ':scheme', value => 'http', mode => 0 }, |
913 { name => ':path', value => '/', mode => 0 }, | 913 { name => ':path', value => '/', mode => 0 }, |
914 { name => ':authority', value => '', mode => 0 }, | 914 { name => ':authority', value => '', mode => 0 }, |
915 { name => 'x', value => 'x' x 64, mode => 0 }]}), fin => 1 }]); | 915 { name => 'x', value => 'x' x 64, mode => 0 }]}), fin => 1 }]); |
921 # | 921 # |
922 # 10.3. Intermediary Encapsulation Attacks | 922 # 10.3. Intermediary Encapsulation Attacks |
923 # Any request or response that contains a character not permitted | 923 # Any request or response that contains a character not permitted |
924 # in a header field value MUST be treated as malformed. | 924 # in a header field value MUST be treated as malformed. |
925 | 925 |
926 $sess = new_session(); | 926 $s = Test::Nginx::HTTP2->new(); |
927 $sid = new_stream($sess, { headers => [ | 927 $sid = $s->new_stream({ headers => [ |
928 { name => ':method', value => 'GET', mode => 0 }, | 928 { name => ':method', value => 'GET', mode => 0 }, |
929 { name => ':scheme', value => 'http', mode => 0 }, | 929 { name => ':scheme', value => 'http', mode => 0 }, |
930 { name => ':path', value => '/proxy2/', mode => 1 }, | 930 { name => ':path', value => '/proxy2/', mode => 1 }, |
931 { name => ':authority', value => 'localhost', mode => 1 }, | 931 { name => ':authority', value => 'localhost', mode => 1 }, |
932 { name => 'x-foo', value => "x-bar\r\nreferer:see-this", mode => 2 }]}); | 932 { name => 'x-foo', value => "x-bar\r\nreferer:see-this", mode => 2 }]}); |
933 $frames = h2_read($sess, all => [{ type => 'RST_STREAM' }]); | 933 $frames = $s->read(all => [{ type => 'RST_STREAM' }]); |
934 | 934 |
935 # 10.3. Intermediary Encapsulation Attacks | 935 # 10.3. Intermediary Encapsulation Attacks |
936 # An intermediary therefore cannot translate an HTTP/2 request or response | 936 # An intermediary therefore cannot translate an HTTP/2 request or response |
937 # containing an invalid field name into an HTTP/1.1 message. | 937 # containing an invalid field name into an HTTP/1.1 message. |
938 | 938 |
952 # invalid header name as seen with underscore should not lead to ignoring rest | 952 # invalid header name as seen with underscore should not lead to ignoring rest |
953 | 953 |
954 TODO: { | 954 TODO: { |
955 local $TODO = 'not yet' unless $t->has_version('1.9.7'); | 955 local $TODO = 'not yet' unless $t->has_version('1.9.7'); |
956 | 956 |
957 $sess = new_session(); | 957 $s = Test::Nginx::HTTP2->new(); |
958 $sid = new_stream($sess, { headers => [ | 958 $sid = $s->new_stream({ headers => [ |
959 { name => ':method', value => 'GET', mode => 0 }, | 959 { name => ':method', value => 'GET', mode => 0 }, |
960 { name => ':scheme', value => 'http', mode => 0 }, | 960 { name => ':scheme', value => 'http', mode => 0 }, |
961 { name => ':path', value => '/', mode => 0 }, | 961 { name => ':path', value => '/', mode => 0 }, |
962 { name => ':authority', value => 'localhost', mode => 1 }, | 962 { name => ':authority', value => 'localhost', mode => 1 }, |
963 { name => 'x_foo', value => "x-bar", mode => 2 }, | 963 { name => 'x_foo', value => "x-bar", mode => 2 }, |
964 { name => 'referer', value => "see-this", mode => 1 }]}); | 964 { name => 'referer', value => "see-this", mode => 1 }]}); |
965 $frames = h2_read($sess, all => [{ type => 'HEADERS' }]); | 965 $frames = $s->read(all => [{ type => 'HEADERS' }]); |
966 | 966 |
967 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 967 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
968 is($frame->{headers}->{'x-referer'}, 'see-this', 'after invalid header name'); | 968 is($frame->{headers}->{'x-referer'}, 'see-this', 'after invalid header name'); |
969 | 969 |
970 } | 970 } |
972 # missing mandatory request header ':scheme' | 972 # missing mandatory request header ':scheme' |
973 | 973 |
974 TODO: { | 974 TODO: { |
975 local $TODO = 'not yet'; | 975 local $TODO = 'not yet'; |
976 | 976 |
977 $sess = new_session(); | 977 $s = Test::Nginx::HTTP2->new(); |
978 $sid = new_stream($sess, { headers => [ | 978 $sid = $s->new_stream({ headers => [ |
979 { name => ':method', value => 'GET', mode => 0 }, | 979 { name => ':method', value => 'GET', mode => 0 }, |
980 { name => ':path', value => '/', mode => 0 }, | 980 { name => ':path', value => '/', mode => 0 }, |
981 { name => ':authority', value => 'localhost', mode => 1 }]}); | 981 { name => ':authority', value => 'localhost', mode => 1 }]}); |
982 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 982 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
983 | 983 |
984 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 984 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
985 is($frame->{headers}->{':status'}, 400, 'incomplete headers'); | 985 is($frame->{headers}->{':status'}, 400, 'incomplete headers'); |
986 | 986 |
987 } | 987 } |
988 | 988 |
989 # empty request header ':authority' | 989 # empty request header ':authority' |
990 | 990 |
991 $sess = new_session(); | 991 $s = Test::Nginx::HTTP2->new(); |
992 $sid = new_stream($sess, { headers => [ | 992 $sid = $s->new_stream({ headers => [ |
993 { name => ':method', value => 'GET', mode => 0 }, | 993 { name => ':method', value => 'GET', mode => 0 }, |
994 { name => ':scheme', value => 'http', mode => 0 }, | 994 { name => ':scheme', value => 'http', mode => 0 }, |
995 { name => ':path', value => '/', mode => 0 }, | 995 { name => ':path', value => '/', mode => 0 }, |
996 { name => ':authority', value => '', mode => 0 }]}); | 996 { name => ':authority', value => '', mode => 0 }]}); |
997 $frames = h2_read($sess, all => [{ sid => $sid, fin => 1 }]); | 997 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); |
998 | 998 |
999 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; | 999 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; |
1000 is($frame->{headers}->{':status'}, 400, 'empty authority'); | 1000 is($frame->{headers}->{':status'}, 400, 'empty authority'); |
1001 | 1001 |
1002 # client sent invalid :path header | 1002 # client sent invalid :path header |
1003 | 1003 |
1004 $sid = new_stream($sess, { path => 't1.html' }); | 1004 $sid = $s->new_stream({ path => 't1.html' }); |
1005 $frames = h2_read($sess, all => [{ type => 'RST_STREAM' }]); | 1005 $frames = $s->read(all => [{ type => 'RST_STREAM' }]); |
1006 | 1006 |
1007 ($frame) = grep { $_->{type} eq "RST_STREAM" } @$frames; | 1007 ($frame) = grep { $_->{type} eq "RST_STREAM" } @$frames; |
1008 is($frame->{code}, 1, 'invalid path'); | 1008 is($frame->{code}, 1, 'invalid path'); |
1009 | 1009 |
1010 ############################################################################### | 1010 ############################################################################### |