http-2-next 0.4.3 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aba29aa46e044dc37656a40df1cce81dcdc185fcb166d456592e5e05b5a45295
4
- data.tar.gz: 95ada3112561c105b5d2a9e9545aab8a29809c49bd5a70d7c64690ce80b47ccc
3
+ metadata.gz: 0c5f4b4de69d36a492e6cfff41b62c48184e85fa75505592e23b404892f69511
4
+ data.tar.gz: 9cba9804729c9617564990720cb4594ec41e32b10c2c1fb3baff545de5fb0b02
5
5
  SHA512:
6
- metadata.gz: 3e0e50d2c307de9733f7951f9abb1a67c111da2b2740f04b7d204343410258981d28917dd0c22e7b8f6e6be9dec4bfb73f20fa118183a54268d1f4d2db43ce85
7
- data.tar.gz: 4c5b8b4a840853e6d785b9d7565753e7e011a5db6d0b5b59fe042cd09491c10c429761a929824af83378b318d3eff43e58949ab6967bf57f6d571a89738ba77e
6
+ metadata.gz: 05dbde11166258b25aa492cebc9eb3f5c1ac5f9e52bcefd0150c7c9be7584de0152af624fb8e406439fca4fb3bc96c0460a6bd6168a319562532d74176ffbb95
7
+ data.tar.gz: e5d916406df282f618cd64443db492b4a0e817e35484bb31c37d1146d9d67493b5fce715cf220710ad220d9d7fe4ae6aacd2f8c973126509f1d99f71e9ee6587
@@ -74,8 +74,8 @@ module HTTP2Next
74
74
 
75
75
  private
76
76
 
77
- def verify_pseudo_headers(frame, mandatory_headers = RESPONSE_MANDATORY_HEADERS)
78
- super(frame, mandatory_headers)
77
+ def verify_pseudo_headers(frame)
78
+ _verify_pseudo_headers(frame, RESPONSE_MANDATORY_HEADERS)
79
79
  end
80
80
  end
81
81
  end
@@ -17,7 +17,7 @@ module HTTP2Next
17
17
  settings_max_concurrent_streams: Framer::MAX_STREAM_ID, # unlimited
18
18
  settings_initial_window_size: 65_535,
19
19
  settings_max_frame_size: 16_384,
20
- settings_max_header_list_size: 2**31 - 1 # unlimited
20
+ settings_max_header_list_size: (2 << 30) - 1 # unlimited
21
21
  }.freeze
22
22
 
23
23
  DEFAULT_CONNECTION_SETTINGS = {
@@ -26,7 +26,7 @@ module HTTP2Next
26
26
  settings_max_concurrent_streams: 100,
27
27
  settings_initial_window_size: 65_535,
28
28
  settings_max_frame_size: 16_384,
29
- settings_max_header_list_size: 2**31 - 1 # unlimited
29
+ settings_max_header_list_size: (2 << 30) - 1 # unlimited
30
30
  }.freeze
31
31
 
32
32
  # Default stream priority (lower values are higher priority).
@@ -120,6 +120,7 @@ module HTTP2Next
120
120
  # @param parent [Stream]
121
121
  def new_stream(**args)
122
122
  raise ConnectionClosed if @state == :closed
123
+
123
124
  raise StreamLimitExceeded if @active_stream_count >= (@max_streams || @remote_settings[:settings_max_concurrent_streams])
124
125
 
125
126
  connection_error(:protocol_error, msg: "id is smaller than previous") if @stream_id < @last_activated_stream
@@ -344,7 +345,7 @@ module HTTP2Next
344
345
  end
345
346
  end
346
347
 
347
- verify_pseudo_headers(frame, REQUEST_MANDATORY_HEADERS)
348
+ _verify_pseudo_headers(frame, REQUEST_MANDATORY_HEADERS)
348
349
  stream = activate_stream(id: pid, parent: parent)
349
350
  verify_stream_order(stream.id)
350
351
  emit(:promise, stream)
@@ -380,7 +381,7 @@ module HTTP2Next
380
381
  # (see Section 5.1).
381
382
  when :window_update
382
383
  stream = @streams_recently_closed[frame[:stream]]
383
- connection_error(:protocol_error, "sent window update on idle stream") unless stream
384
+ connection_error(:protocol_error, msg: "sent window update on idle stream") unless stream
384
385
  process_window_update(frame: frame, encode: true)
385
386
  else
386
387
  # An endpoint that receives an unexpected stream identifier
@@ -397,8 +398,8 @@ module HTTP2Next
397
398
  connection_error(e: e)
398
399
  end
399
400
 
400
- def <<(*args)
401
- receive(*args)
401
+ def <<(data)
402
+ receive(data)
402
403
  end
403
404
 
404
405
  private
@@ -692,26 +693,28 @@ module HTTP2Next
692
693
 
693
694
  frames = []
694
695
 
695
- while payload && payload.bytesize > 0
696
- cont = frame.dup
697
- cont[:type] = :continuation
698
- cont[:flags] = []
699
- cont[:payload] = payload.byteslice(0, @remote_settings[:settings_max_frame_size])
700
- payload = payload.byteslice(@remote_settings[:settings_max_frame_size]..-1)
701
- frames << cont
702
- end
703
- if frames.empty?
704
- frames = [frame]
705
- else
706
- frames.first[:type] = frame[:type]
707
- frames.first[:flags] = frame[:flags] - [:end_headers]
708
- frames.last[:flags] << :end_headers
696
+ begin
697
+ while payload && payload.bytesize > 0
698
+ cont = frame.dup
699
+ cont[:type] = :continuation
700
+ cont[:flags] = []
701
+ cont[:payload] = payload.byteslice(0, @remote_settings[:settings_max_frame_size])
702
+ payload = payload.byteslice(@remote_settings[:settings_max_frame_size]..-1)
703
+ frames << cont
704
+ end
705
+
706
+ if frames.empty?
707
+ frames << frame
708
+ else
709
+ frames.first[:type] = frame[:type]
710
+ frames.first[:flags] = frame[:flags] - [:end_headers]
711
+ frames.last[:flags] << :end_headers
712
+ end
713
+ rescue StandardError => e
714
+ connection_error(:compression_error, e: e)
709
715
  end
710
716
 
711
717
  frames
712
- rescue StandardError => e
713
- connection_error(:compression_error, e: e)
714
- nil
715
718
  end
716
719
 
717
720
  # Activates new incoming or outgoing stream and registers appropriate
@@ -758,7 +761,7 @@ module HTTP2Next
758
761
  @last_stream_id = id
759
762
  end
760
763
 
761
- def verify_pseudo_headers(frame, mandatory_headers)
764
+ def _verify_pseudo_headers(frame, mandatory_headers)
762
765
  headers = frame[:payload]
763
766
  return if headers.is_a?(String)
764
767
 
@@ -11,7 +11,11 @@ module HTTP2Next
11
11
  class Error < StandardError
12
12
  def self.inherited(klass)
13
13
  super
14
- type = klass.name.split("::").last
14
+
15
+ type = klass.name or return
16
+
17
+ type = type.split("::").last or return
18
+
15
19
  type = type.gsub(/([^\^])([A-Z])/, '\1_\2').downcase.to_sym
16
20
  HTTP2Next::Error.types[type] = klass
17
21
  end
@@ -7,7 +7,7 @@ module HTTP2Next
7
7
  module FlowBuffer
8
8
  include Error
9
9
 
10
- MAX_WINDOW_SIZE = 2**31 - 1
10
+ MAX_WINDOW_SIZE = (2 << 30) - 1
11
11
 
12
12
  # Amount of buffered data. Only DATA payloads are subject to flow stream
13
13
  # and connection flow control.
@@ -118,9 +118,7 @@ module HTTP2Next
118
118
  end
119
119
 
120
120
  def retrieve(window_size)
121
- return if @buffer.empty?
122
-
123
- frame = @buffer.first
121
+ frame = @buffer.first or return
124
122
 
125
123
  frame_size = frame[:payload].bytesize
126
124
  end_stream = frame[:flags].include? :end_stream
@@ -133,7 +131,7 @@ module HTTP2Next
133
131
  @buffer.shift
134
132
 
135
133
  if frame_size > window_size
136
- payload = frame.delete(:payload)
134
+ payload = frame[:payload]
137
135
  chunk = frame.dup
138
136
 
139
137
  # Split frame so that it fits in the window
@@ -9,7 +9,7 @@ module HTTP2Next
9
9
  include Error
10
10
 
11
11
  # Default value of max frame size (16384 bytes)
12
- DEFAULT_MAX_FRAME_SIZE = 2**14
12
+ DEFAULT_MAX_FRAME_SIZE = 2 << 13
13
13
 
14
14
  # maximum frame size
15
15
  attr_accessor :local_max_frame_size, :remote_max_frame_size
@@ -460,14 +460,14 @@ module HTTP2Next
460
460
 
461
461
  private
462
462
 
463
- def pack_error(e)
464
- unless e.is_a? Integer
465
- e = DEFINED_ERRORS[e]
463
+ def pack_error(error)
464
+ unless error.is_a? Integer
465
+ error = DEFINED_ERRORS[error]
466
466
 
467
- raise CompressionError, "Unknown error ID for #{e}" unless e
467
+ raise CompressionError, "Unknown error ID for #{error}" unless error
468
468
  end
469
469
 
470
- [e].pack(UINT32)
470
+ [error].pack(UINT32)
471
471
  end
472
472
 
473
473
  def unpack_error(error)
@@ -79,6 +79,13 @@ module HTTP2Next
79
79
  ["www-authenticate", ""]
80
80
  ].each { |pair| pair.each(&:freeze).freeze }.freeze
81
81
 
82
+ STATIC_TABLE_BY_FIELD = STATIC_TABLE
83
+ .each_with_object({})
84
+ .each_with_index { |((field, value), hs), idx| (hs[field] ||= []) << [idx, value] }
85
+ .each { |pair| pair.each(&:freeze).freeze }.freeze
86
+
87
+ STATIC_TABLE_SIZE = STATIC_TABLE.size
88
+
82
89
  # Current table of header key-value pairs.
83
90
  attr_reader :table
84
91
 
@@ -133,7 +140,7 @@ module HTTP2Next
133
140
  # @return [Array] +[key, value]+
134
141
  def dereference(index)
135
142
  # NOTE: index is zero-based in this module.
136
- value = STATIC_TABLE[index] || @table[index - STATIC_TABLE.size]
143
+ value = STATIC_TABLE[index] || @table[index - STATIC_TABLE_SIZE]
137
144
  raise CompressionError, "Index too large" unless value
138
145
 
139
146
  value
@@ -245,22 +252,24 @@ module HTTP2Next
245
252
  name_only = nil
246
253
 
247
254
  if %i[all static].include?(@options[:index])
248
- STATIC_TABLE.each_index do |i|
249
- if STATIC_TABLE[i] == header
250
- exact ||= i
251
- break
252
- elsif STATIC_TABLE[i].first == header.first
255
+ field, value = header
256
+ if (svalues = STATIC_TABLE_BY_FIELD[field])
257
+ svalues.each do |i, svalue|
253
258
  name_only ||= i
259
+ if svalue == value
260
+ exact = i
261
+ break
262
+ end
254
263
  end
255
264
  end
256
265
  end
257
266
  if [:all].include?(@options[:index]) && !exact
258
267
  @table.each_index do |i|
259
268
  if @table[i] == header
260
- exact ||= i + STATIC_TABLE.size
269
+ exact ||= i + STATIC_TABLE_SIZE
261
270
  break
262
271
  elsif @table[i].first == header.first
263
- name_only ||= i + STATIC_TABLE.size
272
+ name_only ||= i + STATIC_TABLE_SIZE
264
273
  end
265
274
  end
266
275
  end
@@ -133,8 +133,8 @@ module HTTP2Next
133
133
  send(type: :origin, stream: 0, payload: @origin_set)
134
134
  end
135
135
 
136
- def verify_pseudo_headers(frame, mandatory_headers = REQUEST_MANDATORY_HEADERS)
137
- super(frame, mandatory_headers)
136
+ def verify_pseudo_headers(frame)
137
+ _verify_pseudo_headers(frame, REQUEST_MANDATORY_HEADERS)
138
138
  end
139
139
 
140
140
  # Handle locally initiated server-push event emitted by the stream.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTP2Next
4
- VERSION = "0.4.3"
4
+ VERSION = "0.5.0"
5
5
  end
data/sig/connection.rbs CHANGED
@@ -3,6 +3,9 @@ module HTTP2Next
3
3
  include FlowBuffer
4
4
  include Emitter
5
5
 
6
+ REQUEST_MANDATORY_HEADERS: Array[String]
7
+ RESPONSE_MANDATORY_HEADERS: Array[String]
8
+
6
9
  attr_reader state: Symbol
7
10
 
8
11
  attr_reader local_window: Integer
@@ -12,28 +15,20 @@ module HTTP2Next
12
15
 
13
16
  attr_reader remote_settings: settings_hash
14
17
  attr_reader local_settings: settings_hash
15
- attr_reader pending_settings: settings_hash
18
+ attr_reader pending_settings: settings_ary
16
19
 
17
20
  attr_reader active_stream_count: Integer
18
21
 
19
- attr_writer max_streams: Integer
22
+ attr_writer max_streams: Integer?
20
23
 
21
24
  def closed?: () -> bool
22
25
 
23
- def new_stream: (
24
- ?weight: Integer,
25
- ?dependency: Integer,
26
- ?exclusive: bool,
27
- ?parent: Stream?,
28
- ?state: Symbol
29
- ) -> Stream
26
+ def new_stream: (**untyped) -> Stream
30
27
 
31
28
  def ping: (String) -> void
32
29
  | (String) { () -> void } -> void
33
30
 
34
- def goaway: (Symbol, String?) -> void
35
- | (Symbol) -> void
36
- | () -> void
31
+ def goaway: (?Symbol, ?String) -> void
37
32
 
38
33
  def window_update: (Integer increment) -> void
39
34
 
@@ -44,7 +39,7 @@ module HTTP2Next
44
39
 
45
40
  private
46
41
 
47
- def initialize: (settings_hash) -> untyped
42
+ def initialize: (?settings_hash) -> untyped
48
43
 
49
44
  def send: (frame) -> void
50
45
 
@@ -64,10 +59,14 @@ module HTTP2Next
64
59
 
65
60
  def encode_headers: (frame) -> Array[frame]
66
61
 
67
- def activate_stream: (id: Integer, **untyped) -> void
62
+ def activate_stream: (id: Integer, **untyped) -> Stream
68
63
 
69
64
  def verify_stream_order: (Integer id) -> void
70
65
 
71
- def verify_pseudo_headers: (frame, Array[String]) -> void
66
+ def verify_pseudo_headers: (frame) -> void
67
+
68
+ def _verify_pseudo_headers: (frame, Array[String]) -> void
69
+
70
+ def connection_error: (?Symbol error, ?msg: String, ?e: StandardError) -> void
72
71
  end
73
72
  end
data/sig/error.rbs ADDED
@@ -0,0 +1,2 @@
1
+ module HTTP2Next
2
+ end
data/sig/flow_buffer.rbs CHANGED
@@ -14,9 +14,7 @@ module HTTP2Next
14
14
 
15
15
  def calculate_window_update: (Integer) -> void
16
16
 
17
- def send_data: () -> void
18
- | (frame?) -> void
19
- | (frame?, bool) -> void
17
+ def send_data: (?frame? frame, ?bool encode) -> void
20
18
 
21
19
  def process_window_update: (frame: frame, ?encode: bool) -> void
22
20
  end
data/sig/frame_buffer.rbs CHANGED
@@ -2,12 +2,12 @@ module HTTP2Next
2
2
  class FrameBuffer
3
3
  attr_reader bytesize: Integer
4
4
 
5
- @buffer: Array[String]
5
+ @buffer: Array[data_frame]
6
6
 
7
- def <<: (frame) -> void
7
+ def <<: (data_frame) -> void
8
8
 
9
9
  def empty?: () -> bool
10
10
 
11
- def retrieve: (Integer) -> frame?
11
+ def retrieve: (Integer) -> data_frame?
12
12
  end
13
13
  end
data/sig/framer.rbs CHANGED
@@ -1,7 +1,36 @@
1
1
  module HTTP2Next
2
2
  class Framer
3
+ DEFAULT_MAX_FRAME_SIZE: Integer
4
+
5
+ MAX_STREAM_ID: Integer
6
+
7
+ MAX_WINDOWINC: Integer
8
+
9
+ FRAME_TYPES: Hash[Symbol, Integer]
10
+
11
+ FRAME_TYPES_WITH_PADDING: Array[Symbol]
12
+
13
+ FRAME_FLAGS: Hash[Symbol, Hash[Symbol, Integer]]
14
+
15
+ DEFINED_SETTINGS: Hash[Symbol, Integer]
16
+
17
+ DEFINED_ERRORS: Hash[Symbol, Integer]
18
+
19
+ RBIT: Integer
20
+ RBYTE: Integer
21
+ EBIT: Integer
22
+ UINT32: String
23
+ UINT16: String
24
+ UINT8: String
25
+ HEADERPACK: String
26
+ FRAME_LENGTH_HISHIFT: Integer
27
+ FRAME_LENGTH_LOMASK: Integer
28
+
29
+ @local_max_frame_size: Integer
30
+ @remote_max_frame_size: Integer
31
+
3
32
  attr_accessor local_max_frame_size: Integer
4
-
33
+
5
34
  attr_accessor remote_max_frame_size: Integer
6
35
 
7
36
  def common_header: (frame) -> String
@@ -14,11 +43,9 @@ module HTTP2Next
14
43
 
15
44
  private
16
45
 
17
- def initialize: (Integer, Integer) -> untyped
18
- | (Integer) -> untyped
19
- | () -> untyped
46
+ def initialize: (?Integer local_max_frame_size, ?Integer remote_max_frame_size) -> untyped
20
47
 
21
- def pack_error: (Integer | Symbol e) -> String
48
+ def pack_error: (Integer | Symbol error) -> String
22
49
 
23
50
  def unpack_error: (Integer) -> (Symbol | Integer)
24
51
  end
data/sig/header.rbs CHANGED
@@ -11,5 +11,17 @@ module HTTP2Next
11
11
  type context_hash = Hash[Symbol, Symbol | Integer]
12
12
 
13
13
  type header_command = Hash[header_key, header_value]
14
+
15
+ HEADREP: Hash[Symbol, Hash[Symbol, Integer]]
16
+
17
+ NAIVE: Hash[Symbol, Symbol]
18
+ LINEAR: Hash[Symbol, Symbol]
19
+ STATIC: Hash[Symbol, Symbol]
20
+ SHORTER: Hash[Symbol, Symbol]
21
+ NAIVEH: Hash[Symbol, Symbol]
22
+ LINEARH: Hash[Symbol, Symbol]
23
+ STATICH: Hash[Symbol, Symbol]
24
+ SHORTERH: Hash[Symbol, Symbol]
25
+
14
26
  end
15
27
  end
data/sig/next.rbs CHANGED
@@ -1,4 +1,6 @@
1
1
  module HTTP2Next
2
+ VERSION: String
3
+
2
4
  DEFAULT_FLOW_WINDOW: Integer
3
5
 
4
6
  DEFAULT_HEADER_SIZE: Integer
@@ -7,7 +9,9 @@ module HTTP2Next
7
9
 
8
10
  type settings_hash = Hash[Symbol, Integer]
9
11
 
10
- type settings_enum = Enumerable[Symbol, Integer]
12
+ type settings_ary = Array[settings_enum]
13
+
14
+ type settings_enum = Enumerable[[Symbol, Integer]]
11
15
 
12
16
  SPEC_DEFAULT_CONNECTION_SETTINGS: settings_hash
13
17
 
@@ -17,14 +21,14 @@ module HTTP2Next
17
21
 
18
22
  CONNECTION_PREFACE_MAGIC: String
19
23
 
20
- REQUEST_MANDATORY_HEADERS: Array[Symbol]
24
+ REQUEST_MANDATORY_HEADERS: Array[String]
21
25
 
22
- RESPONSE_MANDATORY_HEADERS: Array[Symbol]
26
+ RESPONSE_MANDATORY_HEADERS: Array[String]
23
27
 
24
- type header_pair = [String, String]
28
+ type header_pair = [string, string]
25
29
 
26
30
  # # FRAMES
27
- # type frame_control_flags = Array[:end_headers | :end_stream]
31
+ type frame_control_flags = Array[:end_headers | :end_stream]
28
32
 
29
33
  # # HEADERS
30
34
  # type headers_frame = {
@@ -33,7 +37,9 @@ module HTTP2Next
33
37
  # }
34
38
 
35
39
  # # DATA
36
- # type data_frame = { type: :data, flags: frame_control_flags, stream: Integer, length: Integer, payload: String, ?padding: Integer }
40
+ type data_frame = { type: :data, flags: frame_control_flags, stream: Integer, length: Integer, payload: String, padding: Integer }
41
+ | { type: :data, flags: frame_control_flags, stream: Integer, length: Integer, payload: String }
42
+ | { type: :data, flags: frame_control_flags, payload: String }
37
43
 
38
44
  # # PUSH_PROMISE
39
45
  # type push_promise_frame = { type: :push_promise, promise_stream: Integer, flags: frame_control_flags, stream: Integer, ?method: Symbol, ?trailer: Array[String], ?content_length: Integer, payload: Enumerable[header_pair], ?padding: Integer }
@@ -45,7 +51,7 @@ module HTTP2Next
45
51
  # type window_update_frame = { type: :window_update, stream: Integer, increment: Integer }
46
52
 
47
53
  # # PRIORITY
48
- # type priority_frame = { type: :priority, stream: Integer, dependency: Integer, exclusive: bool, weight: Integer }
54
+ type priority_frame = { type: :priority, stream: Integer, dependency: Integer, exclusive: bool, weight: Integer }
49
55
 
50
56
  # # ALTSVC
51
57
  # type altsvc_frame = { type: :altsvc, stream: 0, max_age: Integer, port: Integer, proto: "String", host: String }
data/sig/stream.rbs CHANGED
@@ -4,7 +4,7 @@ module HTTP2Next
4
4
  include Emitter
5
5
 
6
6
  attr_reader id: Integer
7
- attr_reader state: Symbol
7
+ attr_reader state: Symbol
8
8
  attr_reader parent: Stream?
9
9
  attr_reader weight: Integer
10
10
  attr_reader dependency: Integer
@@ -42,7 +42,7 @@ module HTTP2Next
42
42
  def cancel: () -> void
43
43
 
44
44
  def refuse: () -> void
45
-
45
+
46
46
  def window_update: (Integer increment) -> void
47
47
 
48
48
  private
@@ -54,7 +54,7 @@ module HTTP2Next
54
54
  ?dependency: Integer,
55
55
  ?exclusive: bool,
56
56
  ?parent: Stream?,
57
- ?state: Symbol
57
+ ?state: Symbol
58
58
  ) -> untyped
59
59
 
60
60
  def transition: (frame, bool sending) -> void
@@ -63,7 +63,7 @@ module HTTP2Next
63
63
 
64
64
  def complete_transition: (frame) -> void
65
65
 
66
- def process_priority: (frame) -> void
66
+ def process_priority: ({weight: Integer, dependency: Integer, exclusive: bool}) -> void
67
67
 
68
68
  def end_frame?: () -> bool
69
69
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http-2-next
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Cardoso
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-05-26 00:00:00.000000000 Z
13
+ date: 2021-08-05 00:00:00.000000000 Z
14
14
  dependencies: []
15
15
  description: Pure-ruby HTTP 2.0 protocol implementation
16
16
  email:
@@ -41,6 +41,7 @@ files:
41
41
  - sig/client.rbs
42
42
  - sig/connection.rbs
43
43
  - sig/emitter.rbs
44
+ - sig/error.rbs
44
45
  - sig/flow_buffer.rbs
45
46
  - sig/frame_buffer.rbs
46
47
  - sig/framer.rbs