http-2-next 0.4.3 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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