http-2 0.6.3 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.coveralls.yml +1 -0
- data/.gitmodules +3 -0
- data/Gemfile +5 -0
- data/README.md +5 -4
- data/Rakefile +1 -0
- data/example/client.rb +20 -5
- data/example/helper.rb +1 -1
- data/example/keys/mycert.pem +21 -22
- data/example/keys/mykey.pem +25 -25
- data/example/server.rb +10 -3
- data/http-2.gemspec +1 -1
- data/lib/http/2.rb +2 -0
- data/lib/http/2/client.rb +16 -10
- data/lib/http/2/compressor.rb +346 -286
- data/lib/http/2/connection.rb +254 -95
- data/lib/http/2/error.rb +0 -6
- data/lib/http/2/flow_buffer.rb +12 -10
- data/lib/http/2/framer.rb +203 -57
- data/lib/http/2/huffman.rb +332 -0
- data/lib/http/2/huffman_statemachine.rb +272 -0
- data/lib/http/2/server.rb +5 -4
- data/lib/http/2/stream.rb +72 -35
- data/lib/http/2/version.rb +1 -1
- data/lib/tasks/generate_huffman_table.rb +160 -0
- data/spec/client_spec.rb +3 -3
- data/spec/compressor_spec.rb +422 -281
- data/spec/connection_spec.rb +236 -56
- data/spec/framer_spec.rb +213 -45
- data/spec/helper.rb +42 -15
- data/spec/hpack_test_spec.rb +83 -0
- data/spec/huffman_spec.rb +68 -0
- data/spec/server_spec.rb +7 -6
- data/spec/stream_spec.rb +81 -54
- metadata +21 -11
@@ -0,0 +1,83 @@
|
|
1
|
+
require "helper"
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
describe HTTP2::Header do
|
5
|
+
folders = %w[
|
6
|
+
go-hpack
|
7
|
+
haskell-http2-diff
|
8
|
+
haskell-http2-diff-huffman
|
9
|
+
haskell-http2-linear
|
10
|
+
haskell-http2-linear-huffman
|
11
|
+
haskell-http2-naive
|
12
|
+
haskell-http2-naive-huffman
|
13
|
+
haskell-http2-static
|
14
|
+
haskell-http2-static-huffman
|
15
|
+
#hyper-hpack
|
16
|
+
nghttp2
|
17
|
+
nghttp2-16384-4096
|
18
|
+
nghttp2-change-table-size
|
19
|
+
node-http2-hpack
|
20
|
+
]
|
21
|
+
|
22
|
+
context "Decompressor" do
|
23
|
+
folders.each do |folder|
|
24
|
+
next if folder =~ /#/
|
25
|
+
path = File.expand_path("hpack-test-case/#{folder}", File.dirname(__FILE__))
|
26
|
+
Dir.exists?(path) or next
|
27
|
+
context "#{folder}" do
|
28
|
+
Dir.foreach(path) do |file|
|
29
|
+
next if file !~ /\.json/
|
30
|
+
it "should decode #{file}" do
|
31
|
+
story = JSON.parse(File.read("#{path}/#{file}"))
|
32
|
+
cases = story['cases']
|
33
|
+
table_size = cases[0]['header_table_size'] || 4096
|
34
|
+
context = story['context'] ? story['context'].to_sym : :request
|
35
|
+
@dc = Decompressor.new(table_size: table_size)
|
36
|
+
cases.each do |c|
|
37
|
+
wire = [c['wire']].pack("H*").force_encoding('binary')
|
38
|
+
@emitted = @dc.decode(HTTP2::Buffer.new(wire))
|
39
|
+
headers = c['headers'].flat_map(&:to_a)
|
40
|
+
@emitted.should eq headers
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "Compressor" do
|
49
|
+
%w[
|
50
|
+
LINEAR
|
51
|
+
NAIVE
|
52
|
+
SHORTER
|
53
|
+
STATIC
|
54
|
+
].each do |mode|
|
55
|
+
next if mode =~ /#/
|
56
|
+
['', 'H'].each do |huffman|
|
57
|
+
[4096, 512].each do |table_size|
|
58
|
+
context "with #{mode}#{huffman} mode and table_size #{table_size}" do
|
59
|
+
options = eval("HTTP2::Header::#{mode}#{huffman}")
|
60
|
+
path = File.expand_path("hpack-test-case/raw-data", File.dirname(__FILE__))
|
61
|
+
Dir.foreach(path) do |file|
|
62
|
+
next if file !~ /\.json/
|
63
|
+
it "should encode #{file}" do
|
64
|
+
story = JSON.parse(File.read("#{path}/#{file}"))
|
65
|
+
cases = story['cases']
|
66
|
+
context = story['context'] ? story['context'].to_sym : :request
|
67
|
+
@cc = Compressor .new(table_size: table_size)
|
68
|
+
@dc = Decompressor.new(table_size: table_size)
|
69
|
+
cases.each do |c|
|
70
|
+
headers = c['headers'].flat_map(&:to_a)
|
71
|
+
wire = @cc.encode(headers)
|
72
|
+
decoded = @dc.decode(HTTP2::Buffer.new(wire))
|
73
|
+
decoded.should eq headers
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
describe HTTP2::Header::Huffman do
|
4
|
+
huffman_examples = [# plain, encoded
|
5
|
+
["www.example.com", "f1e3c2e5f23a6ba0ab90f4ff"],
|
6
|
+
["no-cache", "a8eb10649cbf"],
|
7
|
+
["Mon, 21 Oct 2013 20:13:21 GMT", "d07abe941054d444a8200595040b8166e082a62d1bff"],
|
8
|
+
]
|
9
|
+
context "encode" do
|
10
|
+
before(:all) { @encoder = HTTP2::Header::Huffman.new }
|
11
|
+
huffman_examples.each do |plain, encoded|
|
12
|
+
it "should encode #{plain} into #{encoded}" do
|
13
|
+
@encoder.encode(plain).unpack("H*").first.should eq encoded
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
context "decode" do
|
18
|
+
before(:all) { @encoder = HTTP2::Header::Huffman.new }
|
19
|
+
huffman_examples.each do |plain, encoded|
|
20
|
+
it "should decode #{encoded} into #{plain}" do
|
21
|
+
@encoder.decode(HTTP2::Buffer.new([encoded].pack("H*"))).should eq plain
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
[
|
26
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0",
|
27
|
+
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
28
|
+
"http://www.craigslist.org/about/sites/",
|
29
|
+
"cl_b=AB2BKbsl4hGM7M4nH5PYWghTM5A; cl_def_lang=en; cl_def_hp=shoals",
|
30
|
+
"image/png,image/*;q=0.8,*/*;q=0.5",
|
31
|
+
"BX=c99r6jp89a7no&b=3&s=q4; localization=en-us%3Bus%3Bus",
|
32
|
+
"UTF-8でエンコードした日本語文字列",
|
33
|
+
].each do |string|
|
34
|
+
it "should encode then decode '#{string}' into the same" do
|
35
|
+
s = string.dup.force_encoding('binary')
|
36
|
+
encoded = @encoder.encode(s)
|
37
|
+
@encoder.decode(HTTP2::Buffer.new(encoded)).should eq s
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should encode/decode all_possible 2-byte sequences" do
|
42
|
+
(2**16).times do |n|
|
43
|
+
str = [n].pack("V")[0,2].force_encoding('binary')
|
44
|
+
@encoder.decode(HTTP2::Buffer.new(@encoder.encode(str))).should eq str
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should raise when input is shorter than expected" do
|
49
|
+
plain, encoded = huffman_examples[0]
|
50
|
+
encoded = [encoded].pack("H*")
|
51
|
+
expect { @encoder.decode(HTTP2::Buffer.new(encoded[0...-1])) }.to raise_error(/EOS invalid/)
|
52
|
+
end
|
53
|
+
it "should raise when input is not padded by 1s" do
|
54
|
+
plain, encoded = ["www.example.com", "f1e3c2e5f23a6ba0ab90f4fe"] # note the fe at end
|
55
|
+
encoded = [encoded].pack("H*")
|
56
|
+
expect { @encoder.decode(HTTP2::Buffer.new(encoded)) }.to raise_error(/EOS invalid/)
|
57
|
+
end
|
58
|
+
it "should raise when exceedingly padded" do
|
59
|
+
plain, encoded = ["www.example.com", "e7cf9bebe89b6fb16fa9b6ffff"] # note the extra ff
|
60
|
+
encoded = [encoded].pack("H*")
|
61
|
+
expect { @encoder.decode(HTTP2::Buffer.new(encoded)) }.to raise_error(/EOS invalid/)
|
62
|
+
end
|
63
|
+
it "should raise when EOS is explicitly encoded" do
|
64
|
+
encoded = ["1c7fffffffff"].pack("H*") # a b EOS
|
65
|
+
expect { @encoder.decode(HTTP2::Buffer.new(encoded)) }.to raise_error(/EOS found/)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/spec/server_spec.rb
CHANGED
@@ -15,7 +15,7 @@ describe HTTP2::Server do
|
|
15
15
|
it "should emit SETTINGS on new connection" do
|
16
16
|
frames = []
|
17
17
|
@srv.on(:frame) { |recv| frames << recv }
|
18
|
-
@srv <<
|
18
|
+
@srv << CONNECTION_PREFACE_MAGIC
|
19
19
|
|
20
20
|
f.parse(frames[0])[:type].should eq :settings
|
21
21
|
end
|
@@ -23,14 +23,15 @@ describe HTTP2::Server do
|
|
23
23
|
it "should initialize client with custom connection settings" do
|
24
24
|
frames = []
|
25
25
|
|
26
|
-
@srv = Server.new(
|
26
|
+
@srv = Server.new(settings_max_concurrent_streams: 200,
|
27
|
+
settings_initial_window_size: 2**10)
|
27
28
|
@srv.on(:frame) { |recv| frames << recv }
|
28
|
-
@srv <<
|
29
|
+
@srv << CONNECTION_PREFACE_MAGIC
|
29
30
|
|
30
31
|
frame = f.parse(frames[0])
|
31
32
|
frame[:type].should eq :settings
|
32
|
-
frame[:payload][:settings_max_concurrent_streams
|
33
|
-
frame[:payload][:settings_initial_window_size
|
33
|
+
frame[:payload].should include([:settings_max_concurrent_streams, 200])
|
34
|
+
frame[:payload].should include([:settings_initial_window_size, 2**10])
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
@@ -40,7 +41,7 @@ describe HTTP2::Server do
|
|
40
41
|
|
41
42
|
@srv.on(:stream) do |stream|
|
42
43
|
expect {
|
43
|
-
stream.promise(
|
44
|
+
stream.promise(':method' => 'GET') {}
|
44
45
|
}.to_not raise_error
|
45
46
|
end
|
46
47
|
|
data/spec/stream_spec.rb
CHANGED
@@ -12,8 +12,8 @@ describe HTTP2::Stream do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should set custom stream priority" do
|
15
|
-
stream = @client.new_stream(
|
16
|
-
stream.
|
15
|
+
stream = @client.new_stream(weight: 3, dependency: 2, exclusive: true)
|
16
|
+
stream.weight.should eq 3
|
17
17
|
end
|
18
18
|
|
19
19
|
context "reserved (local)" do
|
@@ -55,8 +55,8 @@ describe HTTP2::Stream do
|
|
55
55
|
end
|
56
56
|
|
57
57
|
it "should reprioritize stream on PRIORITY" do
|
58
|
-
@stream.receive PRIORITY.
|
59
|
-
@stream.
|
58
|
+
expect { @stream.receive PRIORITY }.to_not raise_error
|
59
|
+
@stream.weight.should eq 20
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
@@ -95,8 +95,8 @@ describe HTTP2::Stream do
|
|
95
95
|
end
|
96
96
|
|
97
97
|
it "should reprioritize stream on PRIORITY" do
|
98
|
-
@stream.send PRIORITY
|
99
|
-
@stream.
|
98
|
+
expect { @stream.send PRIORITY }.to_not raise_error
|
99
|
+
@stream.weight.should eq 20
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
@@ -116,7 +116,7 @@ describe HTTP2::Stream do
|
|
116
116
|
end
|
117
117
|
|
118
118
|
it "should transition to half closed (local) if sending END_STREAM" do
|
119
|
-
[DATA, HEADERS
|
119
|
+
[DATA, HEADERS].each do |frame|
|
120
120
|
s, f = @stream.dup, frame.dup
|
121
121
|
f[:flags] = [:end_stream]
|
122
122
|
|
@@ -126,7 +126,7 @@ describe HTTP2::Stream do
|
|
126
126
|
end
|
127
127
|
|
128
128
|
it "should transition to half closed (remote) if receiving END_STREAM" do
|
129
|
-
[DATA, HEADERS
|
129
|
+
[DATA, HEADERS].each do |frame|
|
130
130
|
s, f = @stream.dup, frame.dup
|
131
131
|
f[:flags] = [:end_stream]
|
132
132
|
|
@@ -173,8 +173,8 @@ describe HTTP2::Stream do
|
|
173
173
|
sp.receive HEADERS
|
174
174
|
sr.send HEADERS
|
175
175
|
|
176
|
-
openp.should
|
177
|
-
openr.should
|
176
|
+
openp.should be_truthy
|
177
|
+
openr.should be_truthy
|
178
178
|
end
|
179
179
|
|
180
180
|
it "should not emit :active on transition from open" do
|
@@ -202,8 +202,8 @@ describe HTTP2::Stream do
|
|
202
202
|
sp.receive RST_STREAM
|
203
203
|
sr.close
|
204
204
|
|
205
|
-
closep.should
|
206
|
-
closer.should
|
205
|
+
closep.should be_truthy
|
206
|
+
closer.should be_truthy
|
207
207
|
end
|
208
208
|
|
209
209
|
it "should emit :close after frame is processed" do
|
@@ -236,7 +236,7 @@ describe HTTP2::Stream do
|
|
236
236
|
before(:each) { @stream.send HEADERS_END_STREAM }
|
237
237
|
|
238
238
|
it "should raise error on attempt to send frames" do
|
239
|
-
(FRAME_TYPES - [RST_STREAM]).each do |frame|
|
239
|
+
(FRAME_TYPES - [PRIORITY, RST_STREAM]).each do |frame|
|
240
240
|
expect { @stream.dup.send frame }.to raise_error StreamError
|
241
241
|
end
|
242
242
|
end
|
@@ -267,6 +267,11 @@ describe HTTP2::Stream do
|
|
267
267
|
@stream.state.should eq :half_closed_local
|
268
268
|
end
|
269
269
|
|
270
|
+
it "should reprioritize stream on PRIORITY" do
|
271
|
+
expect { @stream.send PRIORITY }.to_not raise_error
|
272
|
+
@stream.weight.should eq 20
|
273
|
+
end
|
274
|
+
|
270
275
|
it "should emit :half_close event on transition" do
|
271
276
|
order = []
|
272
277
|
stream = @client.new_stream
|
@@ -286,7 +291,7 @@ describe HTTP2::Stream do
|
|
286
291
|
@stream.receive RST_STREAM
|
287
292
|
|
288
293
|
@stream.state.should eq :closed
|
289
|
-
closed.should
|
294
|
+
closed.should be_truthy
|
290
295
|
end
|
291
296
|
end
|
292
297
|
|
@@ -294,7 +299,7 @@ describe HTTP2::Stream do
|
|
294
299
|
before(:each) { @stream.receive HEADERS_END_STREAM }
|
295
300
|
|
296
301
|
it "should raise STREAM_CLOSED error on reciept of frames" do
|
297
|
-
(FRAME_TYPES - [RST_STREAM, WINDOW_UPDATE]).each do |frame|
|
302
|
+
(FRAME_TYPES - [PRIORITY, RST_STREAM, WINDOW_UPDATE]).each do |frame|
|
298
303
|
expect {
|
299
304
|
@stream.dup.receive frame
|
300
305
|
}.to raise_error(StreamClosed)
|
@@ -302,7 +307,7 @@ describe HTTP2::Stream do
|
|
302
307
|
end
|
303
308
|
|
304
309
|
it "should transition to closed if END_STREAM flag is sent" do
|
305
|
-
[DATA, HEADERS
|
310
|
+
[DATA, HEADERS].each do |frame|
|
306
311
|
s, f = @stream.dup, frame.dup
|
307
312
|
f[:flags] = [:end_stream]
|
308
313
|
|
@@ -327,6 +332,11 @@ describe HTTP2::Stream do
|
|
327
332
|
@stream.state.should eq :half_closed_remote
|
328
333
|
end
|
329
334
|
|
335
|
+
it "should reprioritize stream on PRIORITY" do
|
336
|
+
expect { @stream.receive PRIORITY }.to_not raise_error
|
337
|
+
@stream.weight.should eq 20
|
338
|
+
end
|
339
|
+
|
330
340
|
it "should emit :half_close event on transition" do
|
331
341
|
order = []
|
332
342
|
stream = @client.new_stream
|
@@ -346,7 +356,7 @@ describe HTTP2::Stream do
|
|
346
356
|
@stream.close
|
347
357
|
|
348
358
|
@stream.state.should eq :closed
|
349
|
-
closed.should
|
359
|
+
closed.should be_truthy
|
350
360
|
end
|
351
361
|
end
|
352
362
|
|
@@ -358,7 +368,7 @@ describe HTTP2::Stream do
|
|
358
368
|
end
|
359
369
|
|
360
370
|
it "should raise STREAM_CLOSED on attempt to send frames" do
|
361
|
-
(FRAME_TYPES - [RST_STREAM]).each do |frame|
|
371
|
+
(FRAME_TYPES - [PRIORITY, RST_STREAM]).each do |frame|
|
362
372
|
expect {
|
363
373
|
@stream.dup.send frame
|
364
374
|
}.to raise_error(StreamClosed)
|
@@ -366,20 +376,28 @@ describe HTTP2::Stream do
|
|
366
376
|
end
|
367
377
|
|
368
378
|
it "should raise STREAM_CLOSED on receipt of frame" do
|
369
|
-
(FRAME_TYPES - [RST_STREAM]).each do |frame|
|
379
|
+
(FRAME_TYPES - [PRIORITY, RST_STREAM, WINDOW_UPDATE]).each do |frame|
|
370
380
|
expect {
|
371
381
|
@stream.dup.receive frame
|
372
382
|
}.to raise_error(StreamClosed)
|
373
383
|
end
|
374
384
|
end
|
375
385
|
|
376
|
-
it "should allow RST_STREAM to be sent" do
|
386
|
+
it "should allow PRIORITY, RST_STREAM to be sent" do
|
387
|
+
expect { @stream.send PRIORITY }.to_not raise_error
|
377
388
|
expect { @stream.send RST_STREAM }.to_not raise_error
|
378
389
|
end
|
379
390
|
|
380
|
-
it "should
|
391
|
+
it "should allow PRIORITY, RST_STREAM to be received" do
|
392
|
+
expect { @stream.receive PRIORITY }.to_not raise_error
|
381
393
|
expect { @stream.receive RST_STREAM }.to_not raise_error
|
382
394
|
end
|
395
|
+
|
396
|
+
it "should reprioritize stream on PRIORITY" do
|
397
|
+
expect { @stream.receive PRIORITY }.to_not raise_error
|
398
|
+
@stream.weight.should eq 20
|
399
|
+
end
|
400
|
+
|
383
401
|
end
|
384
402
|
|
385
403
|
context "local closed via RST_STREAM frame" do
|
@@ -407,40 +425,45 @@ describe HTTP2::Stream do
|
|
407
425
|
# We're auto RST'ing PUSH streams in connection class, hence
|
408
426
|
# skipping this transition for now.
|
409
427
|
#end
|
428
|
+
|
410
429
|
end
|
411
430
|
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
431
|
+
# FIXME: Isn't this test same as "half closed (local)"?
|
432
|
+
# context "local closed via END_STREAM flag" do
|
433
|
+
# before(:each) do
|
434
|
+
# @stream.send HEADERS # open
|
435
|
+
# @stream.send DATA # contains end_stream flag
|
436
|
+
# end
|
437
|
+
|
438
|
+
# it "should ignore received frames" do
|
439
|
+
# FRAME_TYPES.each do |frame|
|
440
|
+
# expect { @stream.dup.receive frame }.to_not raise_error
|
441
|
+
# end
|
442
|
+
# end
|
443
|
+
# end
|
417
444
|
|
418
|
-
it "should ignore received frames" do
|
419
|
-
FRAME_TYPES.each do |frame|
|
420
|
-
expect { @stream.dup.receive frame }.to_not raise_error
|
421
|
-
end
|
422
|
-
end
|
423
|
-
end
|
424
445
|
end
|
425
446
|
end # end stream states
|
426
447
|
|
448
|
+
# TODO: add test cases to ensure on(:priority) emitted after close
|
449
|
+
|
427
450
|
context "flow control" do
|
428
451
|
it "should initialize to default flow control window" do
|
429
|
-
@stream.
|
452
|
+
@stream.remote_window.should eq DEFAULT_FLOW_WINDOW
|
430
453
|
end
|
431
454
|
|
432
455
|
it "should update window size on DATA frames only" do
|
433
456
|
@stream.send HEADERS # go to open
|
434
|
-
@stream.
|
457
|
+
@stream.remote_window.should eq DEFAULT_FLOW_WINDOW
|
435
458
|
|
436
459
|
(FRAME_TYPES - [DATA,PING,GOAWAY,SETTINGS]).each do |frame|
|
437
460
|
s = @stream.dup
|
438
461
|
s.send frame
|
439
|
-
s.
|
462
|
+
s.remote_window.should eq DEFAULT_FLOW_WINDOW
|
440
463
|
end
|
441
464
|
|
442
465
|
@stream.send DATA
|
443
|
-
@stream.
|
466
|
+
@stream.remote_window.should eq DEFAULT_FLOW_WINDOW - DATA[:payload].bytesize
|
444
467
|
end
|
445
468
|
|
446
469
|
it "should update window size on receipt of WINDOW_UPDATE" do
|
@@ -448,14 +471,14 @@ describe HTTP2::Stream do
|
|
448
471
|
@stream.send DATA
|
449
472
|
@stream.receive WINDOW_UPDATE
|
450
473
|
|
451
|
-
@stream.
|
474
|
+
@stream.remote_window.should eq (
|
452
475
|
DEFAULT_FLOW_WINDOW - DATA[:payload].bytesize + WINDOW_UPDATE[:increment]
|
453
476
|
)
|
454
477
|
end
|
455
478
|
|
456
479
|
it "should observe session flow control" do
|
457
480
|
settings, data = SETTINGS.dup, DATA.dup
|
458
|
-
settings[:payload] =
|
481
|
+
settings[:payload] = [[:settings_initial_window_size, 1000]]
|
459
482
|
settings[:stream] = 0
|
460
483
|
|
461
484
|
framer = Framer.new
|
@@ -464,17 +487,17 @@ describe HTTP2::Stream do
|
|
464
487
|
s1 = @client.new_stream
|
465
488
|
s1.send HEADERS
|
466
489
|
s1.send data.merge({payload: "x" * 900, flags: []})
|
467
|
-
s1.
|
490
|
+
s1.remote_window.should eq 100
|
468
491
|
|
469
492
|
s1.send data.merge({payload: "x" * 200})
|
470
|
-
s1.
|
493
|
+
s1.remote_window.should eq 0
|
471
494
|
s1.buffered_amount.should eq 100
|
472
495
|
|
473
496
|
@client << framer.generate(WINDOW_UPDATE.merge({
|
474
497
|
stream: s1.id, increment: 1000
|
475
498
|
}))
|
476
499
|
s1.buffered_amount.should eq 0
|
477
|
-
s1.
|
500
|
+
s1.remote_window.should eq 900
|
478
501
|
end
|
479
502
|
end
|
480
503
|
|
@@ -482,17 +505,17 @@ describe HTTP2::Stream do
|
|
482
505
|
it ".reprioritize should emit PRIORITY frame" do
|
483
506
|
@stream.should_receive(:send) do |frame|
|
484
507
|
frame[:type].should eq :priority
|
485
|
-
frame[:
|
508
|
+
frame[:weight].should eq 30
|
486
509
|
end
|
487
510
|
|
488
|
-
@stream.reprioritize 30
|
511
|
+
@stream.reprioritize weight: 30
|
489
512
|
end
|
490
513
|
|
491
514
|
it ".reprioritize should raise error if invoked by server" do
|
492
515
|
srv = Server.new
|
493
516
|
stream = srv.new_stream
|
494
517
|
|
495
|
-
expect { stream.reprioritize(10) }.to raise_error(StreamError)
|
518
|
+
expect { stream.reprioritize(weight: 10) }.to raise_error(StreamError)
|
496
519
|
end
|
497
520
|
|
498
521
|
it ".headers should emit HEADERS frames" do
|
@@ -528,7 +551,7 @@ describe HTTP2::Stream do
|
|
528
551
|
end
|
529
552
|
|
530
553
|
it ".data should split large DATA frames" do
|
531
|
-
data = "x" *
|
554
|
+
data = "x" * 16384 * 2
|
532
555
|
|
533
556
|
@stream.stub(:send)
|
534
557
|
@stream.should_receive(:send).exactly(3).times
|
@@ -564,7 +587,7 @@ describe HTTP2::Stream do
|
|
564
587
|
end
|
565
588
|
|
566
589
|
it "should emit received headers via on(:headers)" do
|
567
|
-
headers, recv =
|
590
|
+
headers, recv = [["header", "value"]], nil
|
568
591
|
@srv.on(:stream) do |stream|
|
569
592
|
stream.on(:headers) {|h| recv = h}
|
570
593
|
end
|
@@ -585,16 +608,21 @@ describe HTTP2::Stream do
|
|
585
608
|
@client_stream.data(payload)
|
586
609
|
end
|
587
610
|
|
588
|
-
it "should emit received priority via on(:priority)" do
|
589
|
-
|
611
|
+
it "should emit received priority parameters via on(:priority)" do
|
612
|
+
new_weight, new_dependency = 15, @client_stream.id + 2
|
613
|
+
callback_called = false
|
590
614
|
@srv.on(:stream) do |stream|
|
591
615
|
stream.on(:priority) do |pri|
|
592
|
-
|
616
|
+
callback_called = true
|
617
|
+
pri.is_a?(Hash).should be
|
618
|
+
pri[:weight].should eq new_weight
|
619
|
+
pri[:dependency].should eq new_dependency
|
593
620
|
end
|
594
621
|
end
|
595
622
|
|
596
623
|
@client_stream.headers({"key" => "value"})
|
597
|
-
@client_stream.reprioritize(
|
624
|
+
@client_stream.reprioritize(weight: new_weight, dependency: new_dependency)
|
625
|
+
callback_called.should be
|
598
626
|
end
|
599
627
|
|
600
628
|
context "push" do
|
@@ -604,7 +632,6 @@ describe HTTP2::Stream do
|
|
604
632
|
@server_stream = stream
|
605
633
|
end
|
606
634
|
|
607
|
-
# @srv << @frm.generate(SETTINGS)
|
608
635
|
@client_stream.headers({"key" => "value"})
|
609
636
|
end
|
610
637
|
|
@@ -643,7 +670,7 @@ describe HTTP2::Stream do
|
|
643
670
|
end
|
644
671
|
|
645
672
|
it "client: headers > active > headers > .. > data > close" do
|
646
|
-
order, headers = [],
|
673
|
+
order, headers = [], []
|
647
674
|
@client.on(:promise) do |push|
|
648
675
|
order << :reserved
|
649
676
|
|
@@ -654,7 +681,7 @@ describe HTTP2::Stream do
|
|
654
681
|
|
655
682
|
push.on(:headers) do |h|
|
656
683
|
order << :headers
|
657
|
-
headers
|
684
|
+
headers += h
|
658
685
|
end
|
659
686
|
|
660
687
|
push.id.should be_even
|
@@ -665,7 +692,7 @@ describe HTTP2::Stream do
|
|
665
692
|
push.data("somedata")
|
666
693
|
end
|
667
694
|
|
668
|
-
headers.should eq(
|
695
|
+
headers.should eq([["key", "val"], ["key2", "val2"]])
|
669
696
|
order.should eq [:reserved, :headers, :active, :headers,
|
670
697
|
:half_close, :data, :close]
|
671
698
|
end
|