http-2 0.10.1 → 0.10.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f52820ad290d538c293b8d008baa622bc788c07c
4
- data.tar.gz: 93aa6df1ade7720059e84c8ffd69d1fb2385028d
2
+ SHA256:
3
+ metadata.gz: 8dd78ba6a3468b6a3ceda2ebabc37ceb895a90d675d9fecc035b74d2f479a457
4
+ data.tar.gz: d70542d69e57050ab9ee3c837b6123fea81424a03bf3b99ffdc889a54a2fd20c
5
5
  SHA512:
6
- metadata.gz: d8fb28dd5124a1dc9995f250ca82a0a257d5a1c2a4b802fadcf0d7fe30a054c1e1e312fa81f6bb69888103783d23916c3bdb464c5eb5819e2ef68609ddeae303
7
- data.tar.gz: 82f8859ce4752d46be361deb76e1b37b076472b0b07262ca5aa9d7b2daa2c50d6d28b44aa8811031b58a294424c1e8fc056f22ffd9c92301a48b2369503784ae
6
+ metadata.gz: f678316f6235ed93ce5a3902ef3bf4c48854605de0875054d1f3e05196fc161bdfe49d149ff930413bef5ca76c61ab2d193092867a383f1f5dbe309cfef0f012
7
+ data.tar.gz: 52fce71379a9299df1cd8c93d44964d668d09c199564482193513b109a6339f220b4ae1e724c5965892b3e53855820a810e95405b8eb198797ea130611d39a05
@@ -11,6 +11,7 @@ AllCops:
11
11
  Layout/IndentHeredoc:
12
12
  Exclude:
13
13
  - 'lib/tasks/generate_huffman_table.rb'
14
+ - 'example/*'
14
15
 
15
16
  Metrics/LineLength:
16
17
  Max: 120
@@ -19,6 +19,9 @@ Metrics/BlockNesting:
19
19
  Metrics/ClassLength:
20
20
  Max: 325
21
21
 
22
+ Metrics/ModuleLength:
23
+ Max: 120
24
+
22
25
  # Offense count: 12
23
26
  Metrics/CyclomaticComplexity:
24
27
  Max: 60
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2013 Ilya Grigorik
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -34,16 +34,16 @@ end
34
34
 
35
35
  # upgrader module
36
36
  class UpgradeHandler
37
- UPGRADE_REQUEST = <<-RESP.strip_heredoc.freeze
38
- GET %s HTTP/1.1
39
- Connection: Upgrade, HTTP2-Settings
40
- HTTP2-Settings: #{HTTP2::Client.settings_header(settings_max_concurrent_streams: 100)}
41
- Upgrade: h2c
42
- Host: %s
43
- User-Agent: http-2 upgrade
44
- Accept: */*
45
-
46
- RESP
37
+ UPGRADE_REQUEST = <<RESP.freeze
38
+ GET %s HTTP/1.1
39
+ Connection: Upgrade, HTTP2-Settings
40
+ HTTP2-Settings: #{HTTP2::Client.settings_header(settings_max_concurrent_streams: 100)}
41
+ Upgrade: h2c
42
+ Host: %s
43
+ User-Agent: http-2 upgrade
44
+ Accept: */*
45
+
46
+ RESP
47
47
 
48
48
  attr_reader :complete, :parsing
49
49
  def initialize(conn, sock)
@@ -39,12 +39,12 @@ end
39
39
 
40
40
  class UpgradeHandler
41
41
  VALID_UPGRADE_METHODS = %w(GET OPTIONS).freeze
42
- UPGRADE_RESPONSE = <<-RESP.strip_heredoc.freeze
43
- HTTP/1.1 101 Switching Protocols
44
- Connection: Upgrade
45
- Upgrade: h2c
42
+ UPGRADE_RESPONSE = <<RESP.freeze
43
+ HTTP/1.1 101 Switching Protocols
44
+ Connection: Upgrade
45
+ Upgrade: h2c
46
46
 
47
- RESP
47
+ RESP
48
48
 
49
49
  attr_reader :complete, :headers, :body, :parsing
50
50
 
@@ -18,5 +18,5 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_development_dependency 'bundler', '~> 1.3'
21
+ spec.add_development_dependency 'bundler'
22
22
  end
@@ -146,6 +146,9 @@ module HTTP2
146
146
 
147
147
  case cmd[:type]
148
148
  when :changetablesize
149
+ if cmd[:value] > @limit
150
+ fail CompressionError, 'dynamic table size update exceed limit'
151
+ end
149
152
  self.table_size = cmd[:value]
150
153
 
151
154
  when :indexed
@@ -33,6 +33,9 @@ module HTTP2
33
33
  # Default connection "fast-fail" preamble string as defined by the spec.
34
34
  CONNECTION_PREFACE_MAGIC = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".freeze
35
35
 
36
+ # Time to hold recently closed streams until purge (seconds)
37
+ RECENTLY_CLOSED_STREAMS_TTL = 15
38
+
36
39
  # Connection encapsulates all of the connection, stream, flow-control,
37
40
  # error management, and other processing logic required for a well-behaved
38
41
  # HTTP 2.0 endpoint.
@@ -683,13 +686,9 @@ module HTTP2
683
686
  # Store a reference to the closed stream, such that we can respond
684
687
  # to any in-flight frames while close is registered on both sides.
685
688
  # References to such streams will be purged whenever another stream
686
- # is closed, with a minimum of 15s RTT time window.
687
- @streams_recently_closed[id] = Time.now
688
- to_delete = @streams_recently_closed.select { |_, v| (Time.now - v) > 15 }
689
- to_delete.each do |stream_id|
690
- @streams.delete stream_id
691
- @streams_recently_closed.delete stream_id
692
- end
689
+ # is closed, with a defined RTT time window.
690
+ @streams_recently_closed[id] = Time.now.to_i
691
+ cleanup_recently_closed
693
692
  end
694
693
 
695
694
  stream.on(:promise, &method(:promise)) if self.is_a? Server
@@ -698,6 +697,22 @@ module HTTP2
698
697
  @streams[id] = stream
699
698
  end
700
699
 
700
+ # Purge recently streams closed within defined RTT time window.
701
+ def cleanup_recently_closed
702
+ now_ts = Time.now.to_i
703
+ to_delete = []
704
+ @streams_recently_closed.each do |stream_id, ts|
705
+ # Ruby Hash enumeration is ordered, so once fresh stream is met we can stop searching.
706
+ break if now_ts - ts < RECENTLY_CLOSED_STREAMS_TTL
707
+ to_delete << stream_id
708
+ end
709
+
710
+ to_delete.each do |stream_id|
711
+ @streams.delete stream_id
712
+ @streams_recently_closed.delete stream_id
713
+ end
714
+ end
715
+
701
716
  # Emit GOAWAY error indicating to peer that the connection is being
702
717
  # aborted, and once sent, raise a local exception.
703
718
  #
@@ -1,3 +1,3 @@
1
1
  module HTTP2
2
- VERSION = '0.10.1'.freeze
2
+ VERSION = '0.10.2'.freeze
3
3
  end
@@ -1,6 +1,7 @@
1
1
  require 'helper'
2
2
 
3
3
  RSpec.describe HTTP2::Client do
4
+ include FrameHelpers
4
5
  before(:each) do
5
6
  @client = Client.new
6
7
  end
@@ -36,7 +37,7 @@ RSpec.describe HTTP2::Client do
36
37
  it 'should initialize client when receiving server settings before sending ack' do
37
38
  frames = []
38
39
  @client.on(:frame) { |bytes| frames << bytes }
39
- @client << f.generate(SETTINGS.dup)
40
+ @client << f.generate(settings_frame)
40
41
 
41
42
  expect(frames[0]).to eq CONNECTION_PREFACE_MAGIC
42
43
  expect(f.parse(frames[1])[:type]).to eq :settings
@@ -72,33 +73,33 @@ RSpec.describe HTTP2::Client do
72
73
 
73
74
  it 'should raise error on PUSH_PROMISE against stream 0' do
74
75
  expect do
75
- @client << set_stream_id(f.generate(PUSH_PROMISE.dup), 0)
76
+ @client << set_stream_id(f.generate(push_promise_frame), 0)
76
77
  end.to raise_error(ProtocolError)
77
78
  end
78
79
 
79
80
  it 'should raise error on PUSH_PROMISE against bogus stream' do
80
81
  expect do
81
- @client << set_stream_id(f.generate(PUSH_PROMISE.dup), 31_415)
82
+ @client << set_stream_id(f.generate(push_promise_frame), 31_415)
82
83
  end.to raise_error(ProtocolError)
83
84
  end
84
85
 
85
86
  it 'should raise error on PUSH_PROMISE against non-idle stream' do
86
87
  expect do
87
88
  s = @client.new_stream
88
- s.send HEADERS.dup
89
+ s.send headers_frame
89
90
 
90
- @client << set_stream_id(f.generate(PUSH_PROMISE.dup), s.id)
91
- @client << set_stream_id(f.generate(PUSH_PROMISE.dup), s.id)
91
+ @client << set_stream_id(f.generate(push_promise_frame), s.id)
92
+ @client << set_stream_id(f.generate(push_promise_frame), s.id)
92
93
  end.to raise_error(ProtocolError)
93
94
  end
94
95
 
95
96
  it 'should emit stream object for received PUSH_PROMISE' do
96
97
  s = @client.new_stream
97
- s.send HEADERS.deep_dup
98
+ s.send headers_frame
98
99
 
99
100
  promise = nil
100
101
  @client.on(:promise) { |stream| promise = stream }
101
- @client << set_stream_id(f.generate(PUSH_PROMISE.deep_dup), s.id)
102
+ @client << set_stream_id(f.generate(push_promise_frame), s.id)
102
103
 
103
104
  expect(promise.id).to eq 2
104
105
  expect(promise.state).to eq :reserved_remote
@@ -107,14 +108,14 @@ RSpec.describe HTTP2::Client do
107
108
  it 'should emit promise headers for received PUSH_PROMISE' do
108
109
  header = nil
109
110
  s = @client.new_stream
110
- s.send HEADERS.deep_dup
111
+ s.send headers_frame
111
112
 
112
113
  @client.on(:promise) do |stream|
113
114
  stream.on(:promise_headers) do |h|
114
115
  header = h
115
116
  end
116
117
  end
117
- @client << set_stream_id(f.generate(PUSH_PROMISE.deep_dup), s.id)
118
+ @client << set_stream_id(f.generate(push_promise_frame), s.id)
118
119
 
119
120
  expect(header).to be_a(Array)
120
121
  # expect(header).to eq([%w(a b)])
@@ -122,7 +123,7 @@ RSpec.describe HTTP2::Client do
122
123
 
123
124
  it 'should auto RST_STREAM promises against locally-RST stream' do
124
125
  s = @client.new_stream
125
- s.send HEADERS.deep_dup
126
+ s.send headers_frame
126
127
  s.close
127
128
 
128
129
  allow(@client).to receive(:send)
@@ -131,54 +132,54 @@ RSpec.describe HTTP2::Client do
131
132
  expect(frame[:stream]).to eq 2
132
133
  end
133
134
 
134
- @client << set_stream_id(f.generate(PUSH_PROMISE.dup), s.id)
135
+ @client << set_stream_id(f.generate(push_promise_frame), s.id)
135
136
  end
136
137
  end
137
138
 
138
139
  context 'alt-svc' do
139
140
  context 'received in the connection' do
140
141
  it 'should emit :altsvc when receiving one' do
141
- @client << f.generate(SETTINGS.dup)
142
+ @client << f.generate(settings_frame)
142
143
  frame = nil
143
144
  @client.on(:altsvc) do |f|
144
145
  frame = f
145
146
  end
146
- @client << f.generate(ALTSVC.deep_dup)
147
+ @client << f.generate(altsvc_frame)
147
148
  expect(frame).to be_a(Hash)
148
149
  end
149
150
  it 'should not emit :altsvc when the frame when contains no host' do
150
- @client << f.generate(SETTINGS.dup)
151
+ @client << f.generate(settings_frame)
151
152
  frame = nil
152
153
  @client.on(:altsvc) do |f|
153
154
  frame = f
154
155
  end
155
156
 
156
- @client << f.generate(ALTSVC.deep_dup.merge(origin: nil))
157
+ @client << f.generate(altsvc_frame.merge(origin: nil))
157
158
  expect(frame).to be_nil
158
159
  end
159
160
  end
160
161
  context 'received in a stream' do
161
162
  it 'should emit :altsvc' do
162
163
  s = @client.new_stream
163
- s.send HEADERS.deep_dup
164
+ s.send headers_frame
164
165
  s.close
165
166
 
166
167
  frame = nil
167
168
  s.on(:altsvc) { |f| frame = f }
168
169
 
169
- @client << set_stream_id(f.generate(ALTSVC.deep_dup.merge(origin: nil)), s.id)
170
+ @client << set_stream_id(f.generate(altsvc_frame.merge(origin: nil)), s.id)
170
171
 
171
172
  expect(frame).to be_a(Hash)
172
173
  end
173
174
  it 'should not emit :alt_svc when the frame when contains a origin' do
174
175
  s = @client.new_stream
175
- s.send HEADERS.deep_dup
176
+ s.send headers_frame
176
177
  s.close
177
178
 
178
179
  frame = nil
179
180
  s.on(:altsvc) { |f| frame = f }
180
181
 
181
- @client << set_stream_id(f.generate(ALTSVC.deep_dup), s.id)
182
+ @client << set_stream_id(f.generate(altsvc_frame), s.id)
182
183
 
183
184
  expect(frame).to be_nil
184
185
  end
@@ -236,6 +236,12 @@ RSpec.describe HTTP2::Header do
236
236
  expect(cc.table.size).to be 1
237
237
  expect(cc.table.first[0]).to eq 'test2'
238
238
  end
239
+
240
+ it 'should reject table size update if exceed limit' do
241
+ cc = EncodingContext.new(table_size: 4096)
242
+
243
+ expect { cc.process(type: :changetablesize, value: 150_000_000) }.to raise_error(CompressionError)
244
+ end
239
245
  end
240
246
 
241
247
  context 'encode' do
@@ -1,6 +1,7 @@
1
1
  require 'helper'
2
2
 
3
3
  RSpec.describe HTTP2::Connection do
4
+ include FrameHelpers
4
5
  before(:each) do
5
6
  @conn = Client.new
6
7
  end
@@ -8,21 +9,21 @@ RSpec.describe HTTP2::Connection do
8
9
  let(:f) { Framer.new }
9
10
 
10
11
  context 'initialization and settings' do
11
- (FRAME_TYPES - [SETTINGS]).each do |frame|
12
- it "should raise error if first frame is #{frame[:type]}" do
12
+ it 'should raise error if first frame is not settings' do
13
+ (frame_types - [settings_frame]).each do |frame|
13
14
  expect { @conn << frame }.to raise_error(ProtocolError)
14
15
  expect(@conn).to be_closed
15
16
  end
16
17
  end
17
18
 
18
19
  it 'should not raise error if first frame is SETTINGS' do
19
- expect { @conn << f.generate(SETTINGS.dup) }.to_not raise_error
20
+ expect { @conn << f.generate(settings_frame) }.to_not raise_error
20
21
  expect(@conn.state).to eq :connected
21
22
  expect(@conn).to_not be_closed
22
23
  end
23
24
 
24
25
  it 'should raise error if SETTINGS stream != 0' do
25
- frame = set_stream_id(f.generate(SETTINGS.dup), 0x1)
26
+ frame = set_stream_id(f.generate(settings_frame), 0x1)
26
27
  expect { @conn << frame }.to raise_error(ProtocolError)
27
28
  end
28
29
  end
@@ -41,7 +42,7 @@ RSpec.describe HTTP2::Connection do
41
42
 
42
43
  it 'should reflect incoming settings when SETTINGS is received' do
43
44
  expect(@conn.remote_settings[:settings_header_table_size]).to eq 4096
44
- settings = SETTINGS.dup
45
+ settings = settings_frame
45
46
  settings[:payload] = [[:settings_header_table_size, 256]]
46
47
 
47
48
  @conn << f.generate(settings)
@@ -50,7 +51,7 @@ RSpec.describe HTTP2::Connection do
50
51
  end
51
52
 
52
53
  it 'should send SETTINGS ACK when SETTINGS is received' do
53
- settings = SETTINGS.dup
54
+ settings = settings_frame
54
55
  settings[:payload] = [[:settings_header_table_size, 256]]
55
56
 
56
57
  # We should expect two frames here (append .twice) - one for the connection setup, and one for the settings ack.
@@ -75,34 +76,34 @@ RSpec.describe HTTP2::Connection do
75
76
  end
76
77
 
77
78
  it 'should change stream limit to received SETTINGS value' do
78
- @conn << f.generate(SETTINGS.dup)
79
+ @conn << f.generate(settings_frame)
79
80
  expect(@conn.remote_settings[:settings_max_concurrent_streams]).to eq 10
80
81
  end
81
82
 
82
83
  it 'should count open streams against stream limit' do
83
84
  s = @conn.new_stream
84
85
  expect(@conn.active_stream_count).to eq 0
85
- s.receive HEADERS
86
+ s.receive headers_frame
86
87
  expect(@conn.active_stream_count).to eq 1
87
88
  end
88
89
 
89
90
  it 'should not count reserved streams against stream limit' do
90
91
  s1 = @conn.new_stream
91
- s1.receive PUSH_PROMISE
92
+ s1.receive push_promise_frame
92
93
  expect(@conn.active_stream_count).to eq 0
93
94
 
94
95
  s2 = @conn.new_stream
95
- s2.send PUSH_PROMISE.deep_dup
96
+ s2.send push_promise_frame
96
97
  expect(@conn.active_stream_count).to eq 0
97
98
 
98
99
  # transition to half closed
99
- s1.receive HEADERS
100
- s2.send HEADERS.deep_dup
100
+ s1.receive headers_frame
101
+ s2.send headers_frame
101
102
  expect(@conn.active_stream_count).to eq 2
102
103
 
103
104
  # transition to closed
104
- s1.receive DATA
105
- s2.send DATA.dup
105
+ s1.receive data_frame
106
+ s2.send data_frame
106
107
  expect(@conn.active_stream_count).to eq 0
107
108
 
108
109
  expect(s1).to be_closed
@@ -110,12 +111,12 @@ RSpec.describe HTTP2::Connection do
110
111
  end
111
112
 
112
113
  it 'should not exceed stream limit set by peer' do
113
- @conn << f.generate(SETTINGS.dup)
114
+ @conn << f.generate(settings_frame)
114
115
 
115
116
  expect do
116
117
  10.times do
117
118
  s = @conn.new_stream
118
- s.send HEADERS.deep_dup
119
+ s.send headers_frame
119
120
  end
120
121
  end.to_not raise_error
121
122
 
@@ -123,9 +124,9 @@ RSpec.describe HTTP2::Connection do
123
124
  end
124
125
 
125
126
  it 'should initialize stream with HEADERS priority value' do
126
- @conn << f.generate(SETTINGS.dup)
127
+ @conn << f.generate(settings_frame)
127
128
 
128
- stream, headers = nil, HEADERS.dup
129
+ stream, headers = nil, headers_frame
129
130
  headers[:weight] = 20
130
131
  headers[:stream_dependency] = 0
131
132
  headers[:exclusive] = false
@@ -137,16 +138,33 @@ RSpec.describe HTTP2::Connection do
137
138
  end
138
139
 
139
140
  it 'should initialize idle stream on PRIORITY frame' do
140
- @conn << f.generate(SETTINGS.dup)
141
+ @conn << f.generate(settings_frame)
141
142
 
142
143
  stream = nil
143
144
  @conn.on(:stream) { |s| stream = s }
144
- @conn << f.generate(PRIORITY.dup)
145
+ @conn << f.generate(priority_frame)
145
146
 
146
147
  expect(stream.state).to eq :idle
147
148
  end
148
149
  end
149
150
 
151
+ context 'cleanup_recently_closed' do
152
+ it 'should cleanup old connections' do
153
+ now_ts = Time.now.to_i
154
+ stream_ids = Array.new(4) { @conn.new_stream.id }
155
+ expect(@conn.instance_variable_get('@streams').size).to eq(4)
156
+
157
+ # Assume that the first 3 streams were closed in different time
158
+ recently_closed = stream_ids[0, 3].zip([now_ts - 100, now_ts - 50, now_ts - 5]).to_h
159
+ @conn.instance_variable_set('@streams_recently_closed', recently_closed)
160
+
161
+ # Cleanup should delete streams that were closed earlier than 15s ago
162
+ @conn.__send__(:cleanup_recently_closed)
163
+ expect(@conn.instance_variable_get('@streams').size).to eq(2)
164
+ expect(@conn.instance_variable_get('@streams_recently_closed')).to eq(stream_ids[2] => now_ts - 5)
165
+ end
166
+ end
167
+
150
168
  context 'Headers pre/post processing' do
151
169
  it 'should not concatenate multiple occurences of a header field with the same name' do
152
170
  input = [
@@ -173,16 +191,14 @@ RSpec.describe HTTP2::Connection do
173
191
  end
174
192
 
175
193
  it 'should not split zero-concatenated header field values' do
176
- input = [
177
- ['cache-control', "max-age=60, private\0must-revalidate"],
178
- ['content-type', 'text/html'],
179
- ['cookie', "a=b\0c=d; e=f"],
180
- ]
181
- expected = [
182
- ['cache-control', "max-age=60, private\0must-revalidate"],
183
- ['content-type', 'text/html'],
184
- ['cookie', "a=b\0c=d; e=f"],
185
- ]
194
+ input = [*RESPONSE_HEADERS,
195
+ ['cache-control', "max-age=60, private\0must-revalidate"],
196
+ ['content-type', 'text/html'],
197
+ ['cookie', "a=b\0c=d; e=f"]]
198
+ expected = [*RESPONSE_HEADERS,
199
+ ['cache-control', "max-age=60, private\0must-revalidate"],
200
+ ['content-type', 'text/html'],
201
+ ['cookie', "a=b\0c=d; e=f"]]
186
202
 
187
203
  result = nil
188
204
  @conn.on(:stream) do |stream|
@@ -204,13 +220,13 @@ RSpec.describe HTTP2::Connection do
204
220
  end
205
221
 
206
222
  it 'should update connection and stream windows on SETTINGS' do
207
- settings, data = SETTINGS.dup, DATA.dup
223
+ settings, data = settings_frame, data_frame
208
224
  settings[:payload] = [[:settings_initial_window_size, 1024]]
209
225
  data[:payload] = 'x' * 2048
210
226
 
211
227
  stream = @conn.new_stream
212
228
 
213
- stream.send HEADERS.deep_dup
229
+ stream.send headers_frame
214
230
  stream.send data
215
231
  expect(stream.remote_window).to eq(DEFAULT_FLOW_WINDOW - 2048)
216
232
  expect(@conn.remote_window).to eq(DEFAULT_FLOW_WINDOW - 2048)
@@ -221,7 +237,7 @@ RSpec.describe HTTP2::Connection do
221
237
  end
222
238
 
223
239
  it 'should initialize streams with window specified by peer' do
224
- settings = SETTINGS.dup
240
+ settings = settings_frame
225
241
  settings[:payload] = [[:settings_initial_window_size, 1024]]
226
242
 
227
243
  @conn << f.generate(settings)
@@ -229,37 +245,37 @@ RSpec.describe HTTP2::Connection do
229
245
  end
230
246
 
231
247
  it 'should observe connection flow control' do
232
- settings, data = SETTINGS.dup, DATA.dup
248
+ settings, data = settings_frame, data_frame
233
249
  settings[:payload] = [[:settings_initial_window_size, 1000]]
234
250
 
235
251
  @conn << f.generate(settings)
236
252
  s1 = @conn.new_stream
237
253
  s2 = @conn.new_stream
238
254
 
239
- s1.send HEADERS.deep_dup
255
+ s1.send headers_frame
240
256
  s1.send data.merge(payload: 'x' * 900)
241
257
  expect(@conn.remote_window).to eq 100
242
258
 
243
- s2.send HEADERS.deep_dup
259
+ s2.send headers_frame
244
260
  s2.send data.merge(payload: 'x' * 200)
245
261
  expect(@conn.remote_window).to eq 0
246
262
  expect(@conn.buffered_amount).to eq 100
247
263
 
248
- @conn << f.generate(WINDOW_UPDATE.merge(stream: 0, increment: 1000))
264
+ @conn << f.generate(window_update_frame.merge(stream: 0, increment: 1000))
249
265
  expect(@conn.buffered_amount).to eq 0
250
266
  expect(@conn.remote_window).to eq 900
251
267
  end
252
268
 
253
269
  it 'should update window when data received is over half of the maximum local window size' do
254
- settings, data = SETTINGS.dup, DATA.dup
270
+ settings, data = settings_frame, data_frame
255
271
  conn = Client.new(settings_initial_window_size: 500)
256
272
 
257
273
  conn.receive f.generate(settings)
258
274
  s1 = conn.new_stream
259
275
  s2 = conn.new_stream
260
276
 
261
- s1.send HEADERS.deep_dup
262
- s2.send HEADERS.deep_dup
277
+ s1.send headers_frame
278
+ s2.send headers_frame
263
279
  expect(conn).to receive(:send) do |frame|
264
280
  expect(frame[:type]).to eq :window_update
265
281
  expect(frame[:stream]).to eq 0
@@ -275,11 +291,11 @@ RSpec.describe HTTP2::Connection do
275
291
 
276
292
  context 'framing' do
277
293
  it 'should buffer incomplete frames' do
278
- settings = SETTINGS.dup
294
+ settings = settings_frame
279
295
  settings[:payload] = [[:settings_initial_window_size, 1000]]
280
296
  @conn << f.generate(settings)
281
297
 
282
- frame = f.generate(WINDOW_UPDATE.merge(stream: 0, increment: 1000))
298
+ frame = f.generate(window_update_frame.merge(stream: 0, increment: 1000))
283
299
  @conn << frame
284
300
  expect(@conn.remote_window).to eq 2000
285
301
 
@@ -295,10 +311,10 @@ RSpec.describe HTTP2::Connection do
295
311
  ]
296
312
 
297
313
  cc = Compressor.new
298
- headers = HEADERS.dup
314
+ headers = headers_frame
299
315
  headers[:payload] = cc.encode(req_headers)
300
316
 
301
- @conn << f.generate(SETTINGS.dup)
317
+ @conn << f.generate(settings_frame)
302
318
  @conn.on(:stream) do |stream|
303
319
  expect(stream).to receive(:<<) do |frame|
304
320
  expect(frame[:payload]).to eq req_headers
@@ -315,7 +331,7 @@ RSpec.describe HTTP2::Connection do
315
331
  ]
316
332
 
317
333
  cc = Compressor.new
318
- h1, h2 = HEADERS.dup, CONTINUATION.dup
334
+ h1, h2 = headers_frame, continuation_frame
319
335
 
320
336
  # Header block fragment might not complete for decompression
321
337
  payload = cc.encode(req_headers)
@@ -326,7 +342,7 @@ RSpec.describe HTTP2::Connection do
326
342
  h2[:payload] = payload # the remaining
327
343
  h2[:stream] = 5
328
344
 
329
- @conn << f.generate(SETTINGS.dup)
345
+ @conn << f.generate(settings_frame)
330
346
  @conn.on(:stream) do |stream|
331
347
  expect(stream).to receive(:<<) do |frame|
332
348
  expect(frame[:payload]).to eq req_headers
@@ -338,18 +354,18 @@ RSpec.describe HTTP2::Connection do
338
354
  end
339
355
 
340
356
  it 'should require that split header blocks are a contiguous sequence' do
341
- headers = HEADERS.dup
357
+ headers = headers_frame
342
358
  headers[:flags] = []
343
359
 
344
- @conn << f.generate(SETTINGS.dup)
360
+ @conn << f.generate(settings_frame)
345
361
  @conn << f.generate(headers)
346
- (FRAME_TYPES - [CONTINUATION]).each do |frame|
362
+ (frame_types - [continuation_frame]).each do |frame|
347
363
  expect { @conn << f.generate(frame.deep_dup) }.to raise_error(ProtocolError)
348
364
  end
349
365
  end
350
366
 
351
367
  it 'should raise compression error on encode of invalid frame' do
352
- @conn << f.generate(SETTINGS.dup)
368
+ @conn << f.generate(settings_frame)
353
369
  stream = @conn.new_stream
354
370
 
355
371
  expect do
@@ -358,8 +374,8 @@ RSpec.describe HTTP2::Connection do
358
374
  end
359
375
 
360
376
  it 'should raise connection error on decode of invalid frame' do
361
- @conn << f.generate(SETTINGS.dup)
362
- frame = f.generate(DATA.dup) # Receiving DATA on unopened stream 1 is an error.
377
+ @conn << f.generate(settings_frame)
378
+ frame = f.generate(data_frame) # Receiving DATA on unopened stream 1 is an error.
363
379
  # Connection errors emit protocol error frames
364
380
  expect { @conn << frame }.to raise_error(ProtocolError)
365
381
  end
@@ -370,7 +386,7 @@ RSpec.describe HTTP2::Connection do
370
386
  @conn.settings(settings_max_concurrent_streams: 10,
371
387
  settings_initial_window_size: 0x7fffffff)
372
388
 
373
- expect(bytes).to eq f.generate(SETTINGS.dup)
389
+ expect(bytes).to eq f.generate(settings_frame)
374
390
  end
375
391
 
376
392
  it 'should compress stream headers' do
@@ -482,44 +498,44 @@ RSpec.describe HTTP2::Connection do
482
498
  context 'connection management' do
483
499
  it 'should raise error on invalid connection header' do
484
500
  srv = Server.new
485
- expect { srv << f.generate(SETTINGS.dup) }.to raise_error(HandshakeError)
501
+ expect { srv << f.generate(settings_frame) }.to raise_error(HandshakeError)
486
502
 
487
503
  srv = Server.new
488
504
  expect do
489
505
  srv << CONNECTION_PREFACE_MAGIC
490
- srv << f.generate(SETTINGS.dup)
506
+ srv << f.generate(settings_frame)
491
507
  end.to_not raise_error
492
508
  end
493
509
 
494
510
  it 'should respond to PING frames' do
495
- @conn << f.generate(SETTINGS.dup)
511
+ @conn << f.generate(settings_frame)
496
512
  expect(@conn).to receive(:send) do |frame|
497
513
  expect(frame[:type]).to eq :ping
498
514
  expect(frame[:flags]).to eq [:ack]
499
515
  expect(frame[:payload]).to eq '12345678'
500
516
  end
501
517
 
502
- @conn << f.generate(PING.dup)
518
+ @conn << f.generate(ping_frame)
503
519
  end
504
520
 
505
521
  it 'should fire callback on PONG' do
506
- @conn << f.generate(SETTINGS.dup)
522
+ @conn << f.generate(settings_frame)
507
523
 
508
524
  pong = nil
509
525
  @conn.ping('12345678') { |d| pong = d }
510
- @conn << f.generate(PONG.dup)
526
+ @conn << f.generate(pong_frame)
511
527
  expect(pong).to eq '12345678'
512
528
  end
513
529
 
514
530
  it 'should fire callback on receipt of GOAWAY' do
515
531
  last_stream, payload, error = nil
516
- @conn << f.generate(SETTINGS.dup)
532
+ @conn << f.generate(settings_frame)
517
533
  @conn.on(:goaway) do |s, e, p|
518
534
  last_stream = s
519
535
  error = e
520
536
  payload = p
521
537
  end
522
- @conn << f.generate(GOAWAY.merge(last_stream: 17, payload: 'test'))
538
+ @conn << f.generate(goaway_frame.merge(last_stream: 17, payload: 'test'))
523
539
 
524
540
  expect(last_stream).to eq 17
525
541
  expect(error).to eq :no_error
@@ -536,8 +552,8 @@ RSpec.describe HTTP2::Connection do
536
552
  end
537
553
 
538
554
  it 'should raise error when opening new stream after receiving GOAWAY' do
539
- @conn << f.generate(SETTINGS.dup)
540
- @conn << f.generate(GOAWAY.dup)
555
+ @conn << f.generate(settings_frame)
556
+ @conn << f.generate(goaway_frame)
541
557
  expect { @conn.new_stream }.to raise_error(ConnectionClosed)
542
558
  end
543
559
 
@@ -545,26 +561,26 @@ RSpec.describe HTTP2::Connection do
545
561
  @conn.goaway
546
562
  expect(@conn).to be_closed
547
563
 
548
- expect { @conn << f.generate(SETTINGS.dup) }.not_to raise_error(ProtocolError)
549
- expect { @conn << f.generate(PING.dup) }.not_to raise_error(ProtocolError)
550
- expect { @conn << f.generate(GOAWAY.dup) }.not_to raise_error(ProtocolError)
564
+ expect { @conn << f.generate(settings_frame) }.not_to raise_error(ProtocolError)
565
+ expect { @conn << f.generate(ping_frame) }.not_to raise_error(ProtocolError)
566
+ expect { @conn << f.generate(goaway_frame) }.not_to raise_error(ProtocolError)
551
567
  end
552
568
 
553
569
  it 'should process connection management frames after GOAWAY' do
554
- @conn << f.generate(SETTINGS.dup)
555
- @conn << f.generate(HEADERS.dup)
556
- @conn << f.generate(GOAWAY.dup)
557
- @conn << f.generate(HEADERS.merge(stream: 7))
558
- @conn << f.generate(PUSH_PROMISE.dup)
570
+ @conn << f.generate(settings_frame)
571
+ @conn << f.generate(headers_frame)
572
+ @conn << f.generate(goaway_frame)
573
+ @conn << f.generate(headers_frame.merge(stream: 7))
574
+ @conn << f.generate(push_promise_frame)
559
575
 
560
576
  expect(@conn.active_stream_count).to eq 1
561
577
  end
562
578
 
563
579
  it 'should raise error on frame for invalid stream ID' do
564
- @conn << f.generate(SETTINGS.dup)
580
+ @conn << f.generate(settings_frame)
565
581
 
566
582
  expect do
567
- @conn << f.generate(DATA.dup.merge(stream: 31))
583
+ @conn << f.generate(data_frame.merge(stream: 31))
568
584
  end.to raise_error(ProtocolError)
569
585
  end
570
586
 
@@ -573,12 +589,12 @@ RSpec.describe HTTP2::Connection do
573
589
  srv << CONNECTION_PREFACE_MAGIC
574
590
 
575
591
  stream = srv.new_stream
576
- stream.send HEADERS.dup
577
- stream.send DATA.dup
592
+ stream.send headers_frame
593
+ stream.send data_frame
578
594
  stream.close
579
595
 
580
596
  expect do
581
- srv << f.generate(RST_STREAM.dup.merge(stream: stream.id))
597
+ srv << f.generate(rst_stream_frame.merge(stream: stream.id))
582
598
  end.to_not raise_error
583
599
  end
584
600
 
@@ -596,7 +612,7 @@ RSpec.describe HTTP2::Connection do
596
612
  [frame]
597
613
  end
598
614
 
599
- expect { @conn << f.generate(DATA.dup) }.to raise_error(ProtocolError)
615
+ expect { @conn << f.generate(data_frame) }.to raise_error(ProtocolError)
600
616
  end
601
617
  end
602
618
 
@@ -625,8 +641,8 @@ RSpec.describe HTTP2::Connection do
625
641
  end
626
642
 
627
643
  it '.goaway should generate GOAWAY frame with last processed stream ID' do
628
- @conn << f.generate(SETTINGS.dup)
629
- @conn << f.generate(HEADERS.merge(stream: 17))
644
+ @conn << f.generate(settings_frame)
645
+ @conn << f.generate(headers_frame.merge(stream: 17))
630
646
 
631
647
  expect(@conn).to receive(:send) do |frame|
632
648
  expect(frame[:type]).to eq :goaway