http-2 0.10.2 → 0.12.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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -2
  3. data/lib/http/2/buffer.rb +6 -4
  4. data/lib/http/2/client.rb +5 -1
  5. data/lib/http/2/compressor.rb +44 -36
  6. data/lib/http/2/connection.rb +76 -89
  7. data/lib/http/2/emitter.rb +4 -1
  8. data/lib/http/2/error.rb +2 -0
  9. data/lib/http/2/flow_buffer.rb +8 -3
  10. data/lib/http/2/framer.rb +83 -94
  11. data/lib/http/2/huffman.rb +19 -17
  12. data/lib/http/2/server.rb +9 -7
  13. data/lib/http/2/stream.rb +48 -48
  14. data/lib/http/2/version.rb +3 -1
  15. data/lib/http/2.rb +2 -0
  16. metadata +10 -63
  17. data/.autotest +0 -20
  18. data/.coveralls.yml +0 -1
  19. data/.gitignore +0 -20
  20. data/.gitmodules +0 -3
  21. data/.rspec +0 -5
  22. data/.rubocop.yml +0 -93
  23. data/.rubocop_todo.yml +0 -122
  24. data/.travis.yml +0 -14
  25. data/Gemfile +0 -16
  26. data/Guardfile +0 -18
  27. data/Guardfile.h2spec +0 -12
  28. data/Rakefile +0 -49
  29. data/example/Gemfile +0 -3
  30. data/example/README.md +0 -44
  31. data/example/client.rb +0 -122
  32. data/example/helper.rb +0 -19
  33. data/example/keys/server.crt +0 -20
  34. data/example/keys/server.key +0 -27
  35. data/example/server.rb +0 -139
  36. data/example/upgrade_client.rb +0 -153
  37. data/example/upgrade_server.rb +0 -203
  38. data/http-2.gemspec +0 -22
  39. data/lib/tasks/generate_huffman_table.rb +0 -166
  40. data/spec/buffer_spec.rb +0 -28
  41. data/spec/client_spec.rb +0 -188
  42. data/spec/compressor_spec.rb +0 -666
  43. data/spec/connection_spec.rb +0 -665
  44. data/spec/emitter_spec.rb +0 -54
  45. data/spec/framer_spec.rb +0 -487
  46. data/spec/h2spec/h2spec.darwin +0 -0
  47. data/spec/h2spec/output/non_secure.txt +0 -317
  48. data/spec/helper.rb +0 -147
  49. data/spec/hpack_test_spec.rb +0 -84
  50. data/spec/huffman_spec.rb +0 -68
  51. data/spec/server_spec.rb +0 -52
  52. data/spec/stream_spec.rb +0 -878
  53. data/spec/support/deep_dup.rb +0 -55
  54. data/spec/support/duplicable.rb +0 -98
data/lib/http/2/framer.rb CHANGED
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HTTP2
2
4
  # Performs encoding, decoding, and validation of binary HTTP/2 frames.
3
5
  #
4
- # rubocop:disable ClassLength
5
6
  class Framer
6
7
  include Error
7
8
 
@@ -19,82 +20,82 @@ module HTTP2
19
20
 
20
21
  # HTTP/2 frame type mapping as defined by the spec
21
22
  FRAME_TYPES = {
22
- data: 0x0,
23
- headers: 0x1,
24
- priority: 0x2,
25
- rst_stream: 0x3,
26
- settings: 0x4,
27
- push_promise: 0x5,
28
- ping: 0x6,
29
- goaway: 0x7,
23
+ data: 0x0,
24
+ headers: 0x1,
25
+ priority: 0x2,
26
+ rst_stream: 0x3,
27
+ settings: 0x4,
28
+ push_promise: 0x5,
29
+ ping: 0x6,
30
+ goaway: 0x7,
30
31
  window_update: 0x8,
31
- continuation: 0x9,
32
- altsvc: 0xa,
32
+ continuation: 0x9,
33
+ altsvc: 0xa
33
34
  }.freeze
34
35
 
35
- FRAME_TYPES_WITH_PADDING = [:data, :headers, :push_promise].freeze
36
+ FRAME_TYPES_WITH_PADDING = %i[data headers push_promise].freeze
36
37
 
37
38
  # Per frame flags as defined by the spec
38
39
  FRAME_FLAGS = {
39
40
  data: {
40
- end_stream: 0,
41
+ end_stream: 0,
41
42
  padded: 3,
42
- compressed: 5,
43
+ compressed: 5
43
44
  },
44
45
  headers: {
45
- end_stream: 0,
46
+ end_stream: 0,
46
47
  end_headers: 2,
47
48
  padded: 3,
48
- priority: 5,
49
+ priority: 5
49
50
  },
50
- priority: {},
51
- rst_stream: {},
52
- settings: { ack: 0 },
51
+ priority: {},
52
+ rst_stream: {},
53
+ settings: { ack: 0 },
53
54
  push_promise: {
54
55
  end_headers: 2,
55
- padded: 3,
56
+ padded: 3
56
57
  },
57
- ping: { ack: 0 },
58
- goaway: {},
58
+ ping: { ack: 0 },
59
+ goaway: {},
59
60
  window_update: {},
60
61
  continuation: { end_headers: 2 },
61
- altsvc: {},
62
+ altsvc: {}
62
63
  }.each_value(&:freeze).freeze
63
64
 
64
65
  # Default settings as defined by the spec
65
66
  DEFINED_SETTINGS = {
66
- settings_header_table_size: 1,
67
- settings_enable_push: 2,
67
+ settings_header_table_size: 1,
68
+ settings_enable_push: 2,
68
69
  settings_max_concurrent_streams: 3,
69
- settings_initial_window_size: 4,
70
- settings_max_frame_size: 5,
71
- settings_max_header_list_size: 6,
70
+ settings_initial_window_size: 4,
71
+ settings_max_frame_size: 5,
72
+ settings_max_header_list_size: 6
72
73
  }.freeze
73
74
 
74
75
  # Default error types as defined by the spec
75
76
  DEFINED_ERRORS = {
76
- no_error: 0,
77
- protocol_error: 1,
78
- internal_error: 2,
77
+ no_error: 0,
78
+ protocol_error: 1,
79
+ internal_error: 2,
79
80
  flow_control_error: 3,
80
- settings_timeout: 4,
81
- stream_closed: 5,
82
- frame_size_error: 6,
83
- refused_stream: 7,
84
- cancel: 8,
85
- compression_error: 9,
86
- connect_error: 10,
87
- enhance_your_calm: 11,
81
+ settings_timeout: 4,
82
+ stream_closed: 5,
83
+ frame_size_error: 6,
84
+ refused_stream: 7,
85
+ cancel: 8,
86
+ compression_error: 9,
87
+ connect_error: 10,
88
+ enhance_your_calm: 11,
88
89
  inadequate_security: 12,
89
- http_1_1_required: 13,
90
+ http_1_1_required: 13
90
91
  }.freeze
91
92
 
92
93
  RBIT = 0x7fffffff
93
94
  RBYTE = 0x0fffffff
94
95
  EBIT = 0x80000000
95
- UINT32 = 'N'.freeze
96
- UINT16 = 'n'.freeze
97
- UINT8 = 'C'.freeze
96
+ UINT32 = 'N'
97
+ UINT16 = 'n'
98
+ UINT8 = 'C'
98
99
  HEADERPACK = (UINT8 + UINT16 + UINT8 + UINT8 + UINT32).freeze
99
100
  FRAME_LENGTH_HISHIFT = 16
100
101
  FRAME_LENGTH_LOMASK = 0xFFFF
@@ -115,24 +116,16 @@ module HTTP2
115
116
  def common_header(frame)
116
117
  header = []
117
118
 
118
- unless FRAME_TYPES[frame[:type]]
119
- fail CompressionError, "Invalid frame type (#{frame[:type]})"
120
- end
119
+ raise CompressionError, "Invalid frame type (#{frame[:type]})" unless FRAME_TYPES[frame[:type]]
121
120
 
122
- if frame[:length] > @max_frame_size
123
- fail CompressionError, "Frame size is too large: #{frame[:length]}"
124
- end
121
+ raise CompressionError, "Frame size is too large: #{frame[:length]}" if frame[:length] > @max_frame_size
125
122
 
126
- if frame[:length] < 0
127
- fail CompressionError, "Frame size is invalid: #{frame[:length]}"
128
- end
123
+ raise CompressionError, "Frame size is invalid: #{frame[:length]}" if (frame[:length]).negative?
129
124
 
130
- if frame[:stream] > MAX_STREAM_ID
131
- fail CompressionError, "Stream ID (#{frame[:stream]}) is too large"
132
- end
125
+ raise CompressionError, "Stream ID (#{frame[:stream]}) is too large" if frame[:stream] > MAX_STREAM_ID
133
126
 
134
127
  if frame[:type] == :window_update && frame[:increment] > MAX_WINDOWINC
135
- fail CompressionError, "Window increment (#{frame[:increment]}) is too large"
128
+ raise CompressionError, "Window increment (#{frame[:increment]}) is too large"
136
129
  end
137
130
 
138
131
  header << (frame[:length] >> FRAME_LENGTH_HISHIFT)
@@ -140,9 +133,7 @@ module HTTP2
140
133
  header << FRAME_TYPES[frame[:type]]
141
134
  header << frame[:flags].reduce(0) do |acc, f|
142
135
  position = FRAME_FLAGS[frame[:type]][f]
143
- unless position
144
- fail CompressionError, "Invalid frame flag (#{f}) for #{frame[:type]}"
145
- end
136
+ raise CompressionError, "Invalid frame flag (#{f}) for #{frame[:type]}" unless position
146
137
 
147
138
  acc | (1 << position)
148
139
  end
@@ -159,10 +150,10 @@ module HTTP2
159
150
  len_hi, len_lo, type, flags, stream = buf.slice(0, 9).unpack(HEADERPACK)
160
151
 
161
152
  frame[:length] = (len_hi << FRAME_LENGTH_HISHIFT) | len_lo
162
- frame[:type], _ = FRAME_TYPES.find { |_t, pos| type == pos }
153
+ frame[:type], = FRAME_TYPES.find { |_t, pos| type == pos }
163
154
  if frame[:type]
164
155
  frame[:flags] = FRAME_FLAGS[frame[:type]].each_with_object([]) do |(name, pos), acc|
165
- acc << name if (flags & (1 << pos)) > 0
156
+ acc << name if (flags & (1 << pos)).positive?
166
157
  end
167
158
  end
168
159
 
@@ -189,8 +180,9 @@ module HTTP2
189
180
  when :headers
190
181
  if frame[:weight] || frame[:stream_dependency] || !frame[:exclusive].nil?
191
182
  unless frame[:weight] && frame[:stream_dependency] && !frame[:exclusive].nil?
192
- fail CompressionError, "Must specify all of priority parameters for #{frame[:type]}"
183
+ raise CompressionError, "Must specify all of priority parameters for #{frame[:type]}"
193
184
  end
185
+
194
186
  frame[:flags] += [:priority] unless frame[:flags].include? :priority
195
187
  end
196
188
 
@@ -205,8 +197,9 @@ module HTTP2
205
197
 
206
198
  when :priority
207
199
  unless frame[:weight] && frame[:stream_dependency] && !frame[:exclusive].nil?
208
- fail CompressionError, "Must specify all of priority parameters for #{frame[:type]}"
200
+ raise CompressionError, "Must specify all of priority parameters for #{frame[:type]}"
209
201
  end
202
+
210
203
  bytes << [(frame[:exclusive] ? EBIT : 0) | (frame[:stream_dependency] & RBIT)].pack(UINT32)
211
204
  bytes << [frame[:weight] - 1].pack(UINT8)
212
205
  length += 5
@@ -216,9 +209,7 @@ module HTTP2
216
209
  length += 4
217
210
 
218
211
  when :settings
219
- if (frame[:stream]).nonzero?
220
- fail CompressionError, "Invalid stream ID (#{frame[:stream]})"
221
- end
212
+ raise CompressionError, "Invalid stream ID (#{frame[:stream]})" if (frame[:stream]).nonzero?
222
213
 
223
214
  frame[:payload].each do |(k, v)|
224
215
  if k.is_a? Integer
@@ -226,7 +217,7 @@ module HTTP2
226
217
  else
227
218
  k = DEFINED_SETTINGS[k]
228
219
 
229
- fail CompressionError, "Unknown settings ID for #{k}" if k.nil?
220
+ raise CompressionError, "Unknown settings ID for #{k}" if k.nil?
230
221
  end
231
222
 
232
223
  bytes << [k].pack(UINT16)
@@ -241,8 +232,9 @@ module HTTP2
241
232
 
242
233
  when :ping
243
234
  if frame[:payload].bytesize != 8
244
- fail CompressionError, "Invalid payload size (#{frame[:payload].size} != 8 bytes)"
235
+ raise CompressionError, "Invalid payload size (#{frame[:payload].size} != 8 bytes)"
245
236
  end
237
+
246
238
  bytes << frame[:payload]
247
239
  length += 8
248
240
 
@@ -268,7 +260,8 @@ module HTTP2
268
260
  bytes << [frame[:max_age], frame[:port]].pack(UINT32 + UINT16)
269
261
  length += 6
270
262
  if frame[:proto]
271
- fail CompressionError, 'Proto too long' if frame[:proto].bytesize > 255
263
+ raise CompressionError, 'Proto too long' if frame[:proto].bytesize > 255
264
+
272
265
  bytes << [frame[:proto].bytesize].pack(UINT8)
273
266
  bytes << frame[:proto].force_encoding(Encoding::BINARY)
274
267
  length += 1 + frame[:proto].bytesize
@@ -277,7 +270,8 @@ module HTTP2
277
270
  length += 1
278
271
  end
279
272
  if frame[:host]
280
- fail CompressionError, 'Host too long' if frame[:host].bytesize > 255
273
+ raise CompressionError, 'Host too long' if frame[:host].bytesize > 255
274
+
281
275
  bytes << [frame[:host].bytesize].pack(UINT8)
282
276
  bytes << frame[:host].force_encoding(Encoding::BINARY)
283
277
  length += 1 + frame[:host].bytesize
@@ -296,13 +290,13 @@ module HTTP2
296
290
  # - http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-6.1
297
291
  if frame[:padding]
298
292
  unless FRAME_TYPES_WITH_PADDING.include?(frame[:type])
299
- fail CompressionError, "Invalid padding flag for #{frame[:type]}"
293
+ raise CompressionError, "Invalid padding flag for #{frame[:type]}"
300
294
  end
301
295
 
302
296
  padlen = frame[:padding]
303
297
 
304
298
  if padlen <= 0 || padlen > 256 || padlen + length > @max_frame_size
305
- fail CompressionError, "Invalid padding #{padlen}"
299
+ raise CompressionError, "Invalid padding #{padlen}"
306
300
  end
307
301
 
308
302
  length += padlen
@@ -312,7 +306,7 @@ module HTTP2
312
306
  # Padding: Padding octets that contain no application semantic value.
313
307
  # Padding octets MUST be set to zero when sending and ignored when
314
308
  # receiving.
315
- bytes << "\0" * padlen
309
+ bytes << ("\0" * padlen)
316
310
  end
317
311
 
318
312
  frame[:length] = length
@@ -325,10 +319,11 @@ module HTTP2
325
319
  # @param buf [Buffer]
326
320
  def parse(buf)
327
321
  return nil if buf.size < 9
322
+
328
323
  frame = read_common_header(buf)
329
324
  return nil if buf.size < 9 + frame[:length]
330
325
 
331
- fail ProtocolError, 'payload too large' if frame[:length] > DEFAULT_MAX_FRAME_SIZE
326
+ raise ProtocolError, 'payload too large' if frame[:length] > DEFAULT_MAX_FRAME_SIZE
332
327
 
333
328
  buf.read(9)
334
329
  payload = buf.read(frame[:length])
@@ -343,10 +338,11 @@ module HTTP2
343
338
  if FRAME_TYPES_WITH_PADDING.include?(frame[:type])
344
339
  padded = frame[:flags].include?(:padded)
345
340
  if padded
346
- padlen = payload.read(1).unpack(UINT8).first
341
+ padlen = payload.read(1).unpack1(UINT8)
347
342
  frame[:padding] = padlen + 1
348
- fail ProtocolError, 'padding too long' if padlen > payload.bytesize
349
- payload.slice!(-padlen, padlen) if padlen > 0
343
+ raise ProtocolError, 'padding too long' if padlen > payload.bytesize
344
+
345
+ payload.slice!(-padlen, padlen) if padlen.positive?
350
346
  frame[:length] -= frame[:padding]
351
347
  frame[:flags].delete(:padded)
352
348
  end
@@ -375,21 +371,17 @@ module HTTP2
375
371
  # NOTE: frame[:length] might not match the number of frame[:payload]
376
372
  # because unknown extensions are ignored.
377
373
  frame[:payload] = []
378
- unless (frame[:length] % 6).zero?
379
- fail ProtocolError, 'Invalid settings payload length'
380
- end
374
+ raise ProtocolError, 'Invalid settings payload length' unless (frame[:length] % 6).zero?
381
375
 
382
- if (frame[:stream]).nonzero?
383
- fail ProtocolError, "Invalid stream ID (#{frame[:stream]})"
384
- end
376
+ raise ProtocolError, "Invalid stream ID (#{frame[:stream]})" if (frame[:stream]).nonzero?
385
377
 
386
378
  (frame[:length] / 6).times do
387
- id = payload.read(2).unpack(UINT16).first
379
+ id = payload.read(2).unpack1(UINT16)
388
380
  val = payload.read_uint32
389
381
 
390
382
  # Unsupported or unrecognized settings MUST be ignored.
391
383
  # Here we send it along.
392
- name, _ = DEFINED_SETTINGS.find { |_name, v| v == id }
384
+ name, = DEFINED_SETTINGS.find { |_name, v| v == id }
393
385
  frame[:payload] << [name, val] if name
394
386
  end
395
387
  when :push_promise
@@ -402,7 +394,7 @@ module HTTP2
402
394
  frame[:error] = unpack_error payload.read_uint32
403
395
 
404
396
  size = frame[:length] - 8 # for last_stream and error
405
- frame[:payload] = payload.read(size) if size > 0
397
+ frame[:payload] = payload.read(size) if size.positive?
406
398
  when :window_update
407
399
  frame[:increment] = payload.read_uint32 & RBIT
408
400
  when :continuation
@@ -411,12 +403,12 @@ module HTTP2
411
403
  frame[:max_age], frame[:port] = payload.read(6).unpack(UINT32 + UINT16)
412
404
 
413
405
  len = payload.getbyte
414
- frame[:proto] = payload.read(len) if len > 0
406
+ frame[:proto] = payload.read(len) if len.positive?
415
407
 
416
408
  len = payload.getbyte
417
- frame[:host] = payload.read(len) if len > 0
409
+ frame[:host] = payload.read(len) if len.positive?
418
410
 
419
- frame[:origin] = payload.read(payload.size) if payload.size > 0
411
+ frame[:origin] = payload.read(payload.size) unless payload.empty?
420
412
  # else # Unknown frame type is explicitly allowed
421
413
  end
422
414
 
@@ -427,9 +419,7 @@ module HTTP2
427
419
 
428
420
  def pack_error(e)
429
421
  unless e.is_a? Integer
430
- if DEFINED_ERRORS[e].nil?
431
- fail CompressionError, "Unknown error ID for #{e}"
432
- end
422
+ raise CompressionError, "Unknown error ID for #{e}" if DEFINED_ERRORS[e].nil?
433
423
 
434
424
  e = DEFINED_ERRORS[e]
435
425
  end
@@ -438,9 +428,8 @@ module HTTP2
438
428
  end
439
429
 
440
430
  def unpack_error(e)
441
- name, _ = DEFINED_ERRORS.find { |_name, v| v == e }
431
+ name, = DEFINED_ERRORS.find { |_name, v| v == e }
442
432
  name || error
443
433
  end
444
434
  end
445
- # rubocop:enable ClassLength
446
435
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'error'
2
4
 
3
5
  module HTTP2
@@ -20,7 +22,7 @@ module HTTP2
20
22
  # @return [String] binary string
21
23
  def encode(str)
22
24
  bitstring = str.each_byte.map { |chr| ENCODE_TABLE[chr] }.join
23
- bitstring << '1' * ((8 - bitstring.size) % 8)
25
+ bitstring << ('1' * ((8 - bitstring.size) % 8))
24
26
  [bitstring].pack('B*')
25
27
  end
26
28
 
@@ -30,12 +32,12 @@ module HTTP2
30
32
  # @return [String] binary string
31
33
  # @raise [CompressionError] when Huffman coded string is malformed
32
34
  def decode(buf)
33
- emit = ''
35
+ emit = String.new
34
36
  state = 0 # start state
35
37
 
36
38
  mask = (1 << BITS_AT_ONCE) - 1
37
39
  buf.each_byte do |chr|
38
- (8 / BITS_AT_ONCE - 1).downto(0) do |shift|
40
+ ((8 / BITS_AT_ONCE) - 1).downto(0) do |shift|
39
41
  branch = (chr >> (shift * BITS_AT_ONCE)) & mask
40
42
  # MACHINE[state] = [final, [transitions]]
41
43
  # [final] unfinished bits so far are prefix of the EOS code.
@@ -43,15 +45,15 @@ module HTTP2
43
45
  # [emit] character to be emitted on this transition, empty string, or EOS.
44
46
  # [next] next state number.
45
47
  trans = MACHINE[state][branch]
46
- fail CompressionError, 'Huffman decode error (EOS found)' if trans.first == EOS
48
+ raise CompressionError, 'Huffman decode error (EOS found)' if trans.first == EOS
49
+
47
50
  emit << trans.first.chr if trans.first
48
51
  state = trans.last
49
52
  end
50
53
  end
51
54
  # Check whether partial input is correctly filled
52
- unless state <= MAX_FINAL_STATE
53
- fail CompressionError, 'Huffman decode error (EOS invalid)'
54
- end
55
+ raise CompressionError, 'Huffman decode error (EOS invalid)' unless state <= MAX_FINAL_STATE
56
+
55
57
  emit.force_encoding(Encoding::BINARY)
56
58
  end
57
59
 
@@ -153,23 +155,23 @@ module HTTP2
153
155
  [0x7fff0, 19],
154
156
  [0x1ffc, 13],
155
157
  [0x3ffc, 14],
156
- [0x22, 6],
158
+ [0x22, 6],
157
159
  [0x7ffd, 15],
158
- [0x3, 5],
159
- [0x23, 6],
160
- [0x4, 5],
161
- [0x24, 6],
162
- [0x5, 5],
160
+ [0x3, 5],
161
+ [0x23, 6],
162
+ [0x4, 5],
163
+ [0x24, 6],
164
+ [0x5, 5],
163
165
  [0x25, 6],
164
166
  [0x26, 6],
165
167
  [0x27, 6],
166
- [0x6, 5],
168
+ [0x6, 5],
167
169
  [0x74, 7],
168
170
  [0x75, 7],
169
171
  [0x28, 6],
170
172
  [0x29, 6],
171
173
  [0x2a, 6],
172
- [0x7, 5],
174
+ [0x7, 5],
173
175
  [0x2b, 6],
174
176
  [0x76, 7],
175
177
  [0x2c, 6],
@@ -314,10 +316,10 @@ module HTTP2
314
316
  [0x7ffffef, 27],
315
317
  [0x7fffff0, 27],
316
318
  [0x3ffffee, 26],
317
- [0x3fffffff, 30],
319
+ [0x3fffffff, 30]
318
320
  ].each(&:freeze).freeze
319
321
 
320
- ENCODE_TABLE = CODES.map { |c, l| [c].pack('N').unpack('B*').first[-l..-1] }.each(&:freeze).freeze
322
+ ENCODE_TABLE = CODES.map { |c, l| [c].pack('N').unpack1('B*')[-l..-1] }.each(&:freeze).freeze
321
323
  end
322
324
  end
323
325
  end
data/lib/http/2/server.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base64'
2
4
  module HTTP2
3
5
  # HTTP 2.0 server connection class that implements appropriate header
@@ -77,7 +79,7 @@ module HTTP2
77
79
  length: buf.bytesize,
78
80
  type: :settings,
79
81
  stream: 0,
80
- flags: [],
82
+ flags: []
81
83
  )
82
84
  buf.prepend(header)
83
85
  receive(buf)
@@ -87,12 +89,12 @@ module HTTP2
87
89
  emit(:stream, stream)
88
90
 
89
91
  headers_frame = {
90
- type: :headers,
91
- stream: 1,
92
- weight: DEFAULT_WEIGHT,
92
+ type: :headers,
93
+ stream: 1,
94
+ weight: DEFAULT_WEIGHT,
93
95
  dependency: 0,
94
- exclusive: false,
95
- payload: headers,
96
+ exclusive: false,
97
+ payload: headers
96
98
  }
97
99
 
98
100
  if body.empty?
@@ -124,7 +126,7 @@ module HTTP2
124
126
  flags: flags,
125
127
  stream: parent.id,
126
128
  promise_stream: promise.id,
127
- payload: headers.to_a,
129
+ payload: headers.to_a
128
130
  )
129
131
 
130
132
  callback.call(promise)