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