http-2 1.0.1 → 1.1.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.
data/lib/http/2/stream.rb CHANGED
@@ -40,6 +40,8 @@ module HTTP2
40
40
  include Emitter
41
41
  include Error
42
42
 
43
+ STREAM_OPEN_STATES = %i[open half_closed_local half_closing closing].freeze
44
+
43
45
  # Stream ID (odd for client initiated streams, even otherwise).
44
46
  attr_reader :id
45
47
 
@@ -80,6 +82,11 @@ module HTTP2
80
82
  @id = id
81
83
  @weight = weight
82
84
  @dependency = dependency
85
+
86
+ # from mixins
87
+ @listeners = Hash.new { |hash, key| hash[key] = [] }
88
+ @send_buffer = FrameBuffer.new
89
+
83
90
  process_priority(weight: weight, dependency: dependency, exclusive: exclusive)
84
91
  @local_window_max_size = connection.local_settings[:settings_initial_window_size]
85
92
  @local_window = connection.local_settings[:settings_initial_window_size]
@@ -88,7 +95,7 @@ module HTTP2
88
95
  @state = state
89
96
  @error = false
90
97
  @closed = false
91
- @_method = @_content_length = @_status_code = nil
98
+ @_method = @_content_length = @_status_code = @_trailers = nil
92
99
  @_waiting_on_trailers = false
93
100
  @received_data = false
94
101
  @activated = false
@@ -113,9 +120,7 @@ module HTTP2
113
120
  # If a DATA frame is received whose stream is not in "open" or
114
121
  # "half closed (local)" state, the recipient MUST respond with a
115
122
  # stream error (Section 5.4.2) of type STREAM_CLOSED.
116
- stream_error(:stream_closed) unless @state == :open ||
117
- @state == :half_closed_local ||
118
- @state == :half_closing || @state == :closing ||
123
+ stream_error(:stream_closed) unless STREAM_OPEN_STATES.include?(@state) ||
119
124
  (@state == :closed && @closed == :local_rst)
120
125
  @received_data = true
121
126
  calculate_content_length(frame[:length])
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTP2
4
- VERSION = "1.0.1"
4
+ VERSION = "1.1.0"
5
5
  end
data/lib/http/2.rb CHANGED
@@ -1,6 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "http/2/version"
4
+
5
+ module HTTP2
6
+ EMPTY = [].freeze
7
+ end
8
+
4
9
  require "http/2/extensions"
5
10
  require "http/2/base64"
6
11
  require "http/2/error"
@@ -7,7 +7,18 @@ module HTTP2
7
7
 
8
8
  DEFAULT_MAX_CONCURRENT_STREAMS: Integer
9
9
 
10
- type settings_hash = Hash[Symbol, Integer]
10
+ EMPTY: []
11
+
12
+ type connection_opts = Hash[Symbol, untyped]
13
+
14
+ type settings_hash = {
15
+ settings_header_table_size: Integer,
16
+ settings_enable_push: Integer,
17
+ settings_max_concurrent_streams: Integer,
18
+ settings_initial_window_size: Integer,
19
+ settings_max_frame_size: Integer,
20
+ settings_max_header_list_size: Integer
21
+ }
11
22
 
12
23
  type settings_ary = Array[settings_enum]
13
24
 
@@ -30,44 +41,44 @@ module HTTP2
30
41
  # # FRAMES
31
42
  type frame_control_flags = Array[:end_headers | :end_stream]
32
43
 
44
+ type common_frame = { stream: Integer }
45
+
33
46
  # # HEADERS
34
- # type headers_frame = {
35
- # type: :headers, flags: frame_control_flags, stream: Integer, payload: Enumerable[header_pair],
36
- # ?method: Symbol, ?trailer: Array[String], ?content_length: Integer, ?padding: Integer
37
- # }
47
+ type headers_frame = common_frame & {
48
+ type: :headers, flags: frame_control_flags, payload: Enumerable[header_pair] | String,
49
+ ?method: Symbol, ?trailer: Array[String], ?content_length: Integer, ?padding: Integer
50
+ }
38
51
 
39
52
  # # DATA
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 }
53
+ type data_frame = { type: :data, flags: frame_control_flags, ?length: Integer, payload: String, ?padding: Integer }
43
54
 
44
55
  # # PUSH_PROMISE
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 }
56
+ type push_promise_frame = { type: :push_promise, promise_stream: Integer, flags: frame_control_flags, ?method: Symbol, ?trailer: Array[String], ?content_length: Integer, payload: Enumerable[header_pair], ?padding: Integer }
46
57
 
47
58
  # # SETTINGS
48
- # type settings_frame = { type: :settings, stream: 0, payload: Array[[Symbol | Integer, Integer]] }
59
+ type settings_frame = { type: :settings, payload: Array[[Symbol | Integer, Integer]] }
49
60
 
50
61
  # # WINDOW_UPDATE
51
- # type window_update_frame = { type: :window_update, stream: Integer, increment: Integer }
62
+ type window_update_frame = { type: :window_update, increment: Integer }
52
63
 
53
64
  # # PRIORITY
54
- type priority_frame = { type: :priority, stream: Integer, dependency: Integer, exclusive: bool, weight: Integer }
65
+ type priority_frame = { dependency: Integer, exclusive: bool, weight: Integer }
55
66
 
56
67
  # # ALTSVC
57
- # type altsvc_frame = { type: :altsvc, stream: 0, max_age: Integer, port: Integer, proto: "String", host: String }
68
+ type altsvc_frame = { type: :altsvc, max_age: Integer, port: Integer, proto: "String", host: String }
58
69
 
59
70
  # # ORIGIN
60
- # type origin_frame = { type: :origin, stream: 0, origin: Array[String] }
71
+ type origin_frame = { type: :origin, origin: Array[String] }
61
72
 
62
73
  # # PING
63
- # type ping_frame = { type: :ping, payload: String, length: Integer }
74
+ type ping_frame = { type: :ping, payload: String, length: Integer }
64
75
 
65
76
  # # GOAWAY
66
- # type goaway_frame = { type: :goaway, stream: 0, last_stream: Integer, error: Symbol? }
77
+ type goaway_frame = { type: :goaway, last_stream: Integer, error: Symbol? }
67
78
 
68
- # type frame = headers_frame | data_frame | push_promise_frame |
79
+ # type frame = common_frame & (headers_frame | data_frame | push_promise_frame |
69
80
  # settings_frame | window_update_frame | priority_frame | altsvc_frame |
70
- # origin_frame | ping_frame | goaway_frame
81
+ # origin_frame | ping_frame | goaway_frame)
71
82
 
72
83
  type frame_key = :type | :flags | :stream | :padding | :ignore |
73
84
  # headers
data/sig/client.rbs CHANGED
@@ -1,5 +1,7 @@
1
1
  module HTTP2
2
2
  class Client < Connection
3
+ @h2c_upgrade: Symbol?
4
+
3
5
  def upgrade: () -> Stream
4
6
 
5
7
  def send_connection_preface: () -> void
data/sig/connection.rbs CHANGED
@@ -2,10 +2,18 @@ module HTTP2
2
2
  class Connection
3
3
  include FlowBuffer
4
4
  include Emitter
5
+ include BufferUtils
5
6
 
6
7
  REQUEST_MANDATORY_HEADERS: Array[String]
8
+
7
9
  RESPONSE_MANDATORY_HEADERS: Array[String]
8
10
 
11
+ CONNECTION_FRAME_TYPES: Array[Symbol]
12
+
13
+ HEADERS_FRAME_TYPES: Array[Symbol]
14
+
15
+ STREAM_OPEN_STATES: Array[Symbol]
16
+
9
17
  attr_reader state: Symbol
10
18
 
11
19
  attr_reader local_window: Integer
@@ -21,14 +29,18 @@ module HTTP2
21
29
 
22
30
  @stream_id: Integer
23
31
  @active_stream_count: Integer
24
- @last_activated_stream: Integer
25
32
  @last_stream_id: Integer
26
33
 
27
34
  @streams: Hash[Integer, Stream]
28
- @streams_recently_closed: Hash[Integer, Stream]
35
+ @streams_recently_closed: Hash[Integer, Numeric]
29
36
 
30
37
  @framer: Framer
31
38
 
39
+ type role_type = :client | :server
40
+
41
+ @local_role: role_type
42
+ @remote_role: role_type
43
+
32
44
  @local_window_limit: Integer
33
45
  @remote_window_limit: Integer
34
46
 
@@ -39,6 +51,7 @@ module HTTP2
39
51
  @recv_buffer: String
40
52
  @continuation: Array[frame]
41
53
 
54
+ @h2c_upgrade: Symbol?
42
55
  @closed_since: Float?
43
56
  @received_frame: bool
44
57
 
@@ -53,18 +66,18 @@ module HTTP2
53
66
 
54
67
  def window_update: (Integer increment) -> void
55
68
 
56
- def settings: (settings_enum) -> void
69
+ def settings: (settings_enum payload) -> void
57
70
 
58
71
  def receive: (string data) -> void
59
72
  alias << receive
60
73
 
61
- def initialize: (?settings_hash) -> void
74
+ def initialize: (?connection_opts) -> void
62
75
 
63
76
  private
64
77
 
65
- def send: (frame) -> void
78
+ def send: (frame frame) -> void
66
79
 
67
- def encode: (frame) -> Array[String]
80
+ def encode: (frame frame) -> void
68
81
 
69
82
  def connection_frame?: (frame) -> bool
70
83
 
@@ -72,13 +85,13 @@ module HTTP2
72
85
 
73
86
  def ping_management: (frame) -> void
74
87
 
75
- def validate_settings: (:client | :server, settings_enum) -> void
88
+ def validate_settings: (role_type, settings_enum) -> void
76
89
 
77
90
  def connection_settings: (frame) -> void
78
91
 
79
92
  def decode_headers: (frame) -> void
80
93
 
81
- def encode_headers: (frame) -> Array[frame]
94
+ def encode_headers: (frame headers_frame) -> void
82
95
 
83
96
  def activate_stream: (id: Integer, **untyped) -> Stream
84
97
 
data/sig/emitter.rbs CHANGED
@@ -1,13 +1,11 @@
1
1
  module HTTP2
2
2
  module Emitter
3
+ @listeners: Hash[Symbol, Array[^(*untyped) -> void]]
4
+
3
5
  def on: (Symbol event) { (*untyped) -> void } -> void
4
6
 
5
7
  def once: (Symbol event) { (*untyped) -> void } -> void
6
8
 
7
9
  def emit: (Symbol event, *untyped args) ?{ (*untyped) -> void } -> void
8
-
9
- private
10
-
11
- def listeners: (Symbol event) -> Array[Proc]
12
10
  end
13
11
  end
data/sig/extensions.rbs CHANGED
@@ -1,5 +1,15 @@
1
1
  module HTTP2
2
+ module BufferUtils
3
+ def append_str: (String str, String data) -> void
4
+
5
+ def read_str: (String str, Integer n) -> String
6
+
7
+ def read_uint32: (String str) -> Integer
8
+
9
+ def shift_byte: (String str) -> Integer
10
+ end
11
+
2
12
  module PackingExtensions
3
- def pack: (Array[Integer] array_to_pack, String template, buffer: String, ?offset: Integer) -> String
13
+ def pack: (Array[Integer | String] array_to_pack, String template, buffer: String, ?offset: Integer) -> String
4
14
  end
5
15
  end
data/sig/flow_buffer.rbs CHANGED
@@ -2,20 +2,22 @@ module HTTP2
2
2
  module FlowBuffer
3
3
  MAX_WINDOW_SIZE: Integer
4
4
 
5
+ attr_reader send_buffer: FrameBuffer
6
+
5
7
  def buffered_amount: () -> Integer
6
8
 
7
9
  def flush: () -> void
8
10
 
9
11
  private
10
12
 
11
- def send_buffer: () -> FrameBuffer
12
-
13
- def update_local_window: (frame) -> void
13
+ def update_local_window: (data_frame frame) -> void
14
14
 
15
15
  def calculate_window_update: (Integer) -> void
16
16
 
17
- def send_data: (?frame? frame, ?bool encode) -> void
17
+ def send_data: (?data_frame? frame, ?bool encode) -> void
18
+
19
+ def send_frame: (data_frame frame, bool encode) -> void
18
20
 
19
- def process_window_update: (frame: frame, ?encode: bool) -> void
21
+ def process_window_update: (frame: window_update_frame, ?encode: bool) -> void
20
22
  end
21
23
  end
data/sig/frame_buffer.rbs CHANGED
@@ -4,7 +4,7 @@ module HTTP2
4
4
 
5
5
  @buffer: Array[data_frame]
6
6
 
7
- def <<: (data_frame) -> void
7
+ def <<: (data_frame frame) -> void
8
8
 
9
9
  def empty?: () -> bool
10
10
 
data/sig/framer.rbs CHANGED
@@ -1,6 +1,8 @@
1
1
  module HTTP2
2
2
  class Framer
3
+ include Error
3
4
  include PackingExtensions
5
+ include BufferUtils
4
6
 
5
7
  DEFAULT_MAX_FRAME_SIZE: Integer
6
8
 
@@ -10,6 +12,8 @@ module HTTP2
10
12
 
11
13
  FRAME_TYPES: Hash[Symbol, Integer]
12
14
 
15
+ FRAME_TYPES_BY_NAME: Array[Symbol]
16
+
13
17
  FRAME_TYPES_WITH_PADDING: Array[Symbol]
14
18
 
15
19
  FRAME_FLAGS: Hash[Symbol, Hash[Symbol, Integer]]
@@ -37,6 +41,8 @@ module HTTP2
37
41
 
38
42
  def common_header: (frame, buffer: String) -> String
39
43
 
44
+ def read_common_header: (String buf) -> frame
45
+
40
46
  def read_common_frame: (String) -> frame
41
47
 
42
48
  def generate: (frame) -> String
@@ -9,7 +9,7 @@ module HTTP2
9
9
 
10
10
  def integer: (Integer, Integer, buffer: String, ?offset: Integer) -> String
11
11
 
12
- def string: (String) -> String
12
+ def string: (String, ?String buffer) -> String
13
13
 
14
14
  def header: (header_command, ?String) -> String
15
15
 
@@ -17,11 +17,13 @@ module HTTP2
17
17
 
18
18
  private
19
19
 
20
- def initialize: (?context_hash options) -> void
20
+ def initialize: (?connection_opts options) -> void
21
21
 
22
- def huffman_string: (String str) -> String
22
+ def huffman_string: (String str, ?String buffer) -> String
23
23
 
24
- def plain_string: (String str) -> String
24
+ def plain_string: (String str, ?String buffer) -> String
25
+
26
+ def set_huffman_size: (String str, Integer huffman_offset) -> String
25
27
  end
26
28
  end
27
29
  end
@@ -1,6 +1,10 @@
1
1
  module HTTP2
2
2
  module Header
3
3
  class Decompressor
4
+ include BufferUtils
5
+
6
+ FORBIDDEN_HEADERS: Array[String]
7
+
4
8
  @cc: EncodingContext
5
9
 
6
10
  def table_size=: (Integer) -> void
@@ -15,8 +19,7 @@ module HTTP2
15
19
  | (String) -> Array[header_pair]
16
20
  private
17
21
 
18
- def initialize: (context_hash options) -> untyped
19
- | () -> untyped
22
+ def initialize: (?connection_opts options) -> void
20
23
  end
21
24
  end
22
25
  end
@@ -3,32 +3,50 @@ module HTTP2
3
3
  class EncodingContext
4
4
  STATIC_TABLE: Array[header_pair]
5
5
 
6
+ STATIC_TABLE_BY_FIELD: Hash[String, Array[[Integer, String]]]
7
+
8
+ STATIC_TABLE_SIZE: Integer
9
+
10
+ STATIC_ALL: Array[Symbol]
11
+
12
+ STATIC_NEVER: Array[Symbol]
13
+
14
+ DEFAULT_OPTIONS: context_hash
15
+
16
+ UPPER: Regexp
17
+
18
+
6
19
  attr_reader table: Array[header_pair]
7
20
 
8
21
  attr_reader options: context_hash
9
22
 
23
+ attr_reader current_table_size: Integer
24
+
25
+ @limit: Integer
26
+
27
+ @_table_updated: bool
28
+
10
29
  def dup: () -> EncodingContext
11
30
 
12
31
  def dereference: (Integer) -> header_pair
13
32
 
14
33
  def process: (header_command cmd) -> header_pair?
15
34
 
16
- def encode: (_Each[header_pair]) -> Array[header_command]
35
+ def encode: (_Each[header_pair]) { (header_command) -> void } -> void
17
36
 
18
37
  def addcmd: (String name, String value) -> header_command
19
38
 
20
39
  def table_size=: (Integer) -> void
21
40
 
22
- def current_table_size: () -> Integer
41
+ def listen_on_table: { () -> void } -> void
23
42
 
24
43
  private
25
44
 
26
- def initialize: (context_hash options) -> untyped
27
- | () -> untyped
45
+ def initialize: (?connection_opts options) -> void
28
46
 
29
- def add_to_table: (header_pair) -> void
47
+ def add_to_table: (string name, string value) -> void
30
48
 
31
- def size_check: (header_pair?) -> bool
49
+ def size_check: (Integer cmdsize) -> bool
32
50
  end
33
51
  end
34
52
  end
@@ -1,9 +1,25 @@
1
1
  module HTTP2
2
2
  module Header
3
- class Huffman
4
- def encode: (String str) -> String
3
+ module Huffman
4
+ include Error
5
+ extend PackingExtensions
6
+ extend BufferUtils
5
7
 
6
- def decode: (String str) -> String
8
+ BITS_AT_ONCE: Integer
9
+
10
+ EOS: Integer
11
+
12
+ CODES: Array[[Integer, Integer]]
13
+
14
+ ENCODE_TABLE: Array[String]
15
+
16
+ MAX_FINAL_STATE: Integer
17
+
18
+ MACHINE: Array[Array[[Integer?, Integer]]]
19
+
20
+ def self?.encode: (String str, ?String buffer) -> String
21
+
22
+ def self?.decode: (String str) -> String
7
23
  end
8
24
  end
9
25
  end
data/sig/header.rbs CHANGED
@@ -3,16 +3,19 @@ module HTTP2
3
3
  type header_key = :type | :name | :value | :index
4
4
  type header_value = Integer | String | :indexed | :changetablesize | :incremental | :noindex | :neverindexed
5
5
 
6
- #type context_hash = {
7
- # huffman?: (:always | :never | :shorter),
8
- # index?: (:all | :static | :never),
9
- # table_size?: Integer
10
- #}
11
- type context_hash = Hash[Symbol, Symbol | Integer]
6
+ type context_hash = {
7
+ huffman: (:always | :never | :shorter),
8
+ index: (:all | :static | :never),
9
+ table_size: Integer
10
+ }
12
11
 
13
- type header_command = Hash[header_key, header_value]
12
+ type header_type = :indexed | :incremental | :noindex | :neverindexed | :changetablesize
14
13
 
15
- HEADREP: Hash[Symbol, Hash[Symbol, Integer]]
14
+ type header_command = { type: :indexed , name: Integer } |
15
+ { type: (:incremental | :noindex | :neverindexed), name: Integer | String, value: String } |
16
+ { type: :changetablesize, ?name: Integer, value: Integer }
17
+
18
+ HEADREP: Hash[header_type, { prefix: Integer, pattern: Integer }]
16
19
 
17
20
  NAIVE: Hash[Symbol, Symbol]
18
21
  LINEAR: Hash[Symbol, Symbol]
data/sig/stream.rbs CHANGED
@@ -3,6 +3,8 @@ module HTTP2
3
3
  include FlowBuffer
4
4
  include Emitter
5
5
 
6
+ STREAM_OPEN_STATES: Array[Symbol]
7
+
6
8
  attr_reader id: Integer
7
9
  attr_reader state: Symbol
8
10
  attr_reader parent: Stream?
@@ -19,6 +21,7 @@ module HTTP2
19
21
  @_content_length: Integer?
20
22
  @_status_code: Integer?
21
23
  @_waiting_on_trailers: bool
24
+ @_trailers: Array[String]?
22
25
  @received_data: bool
23
26
  @activated: bool
24
27
 
@@ -26,15 +29,15 @@ module HTTP2
26
29
 
27
30
  def closed?: () -> bool
28
31
 
29
- def receive: (frame) -> void
32
+ def receive: (frame frame) -> void
30
33
 
31
34
  alias << receive
32
35
 
33
- def verify_trailers: (frame) -> void
36
+ def verify_trailers: (headers_frame frame) -> void
34
37
 
35
38
  def calculate_content_length: (Integer?) -> void
36
39
 
37
- def send: (frame) -> void
40
+ def send: (frame frame) -> void
38
41
 
39
42
  def headers: (Enumerable[header_pair] headers, ?end_headers: bool, ?end_stream: bool) -> void
40
43
 
@@ -77,9 +80,9 @@ module HTTP2
77
80
 
78
81
  def complete_transition: (frame) -> void
79
82
 
80
- def process_priority: ({weight: Integer, dependency: Integer, exclusive: bool}) -> void
83
+ def process_priority: (priority_frame frame) -> void
81
84
 
82
- def end_frame?: () -> bool
85
+ def end_stream?: (frame frame) -> boolish
83
86
 
84
87
  def stream_error: (Symbol error, ?msg: String?) -> void
85
88
  | () -> void
metadata CHANGED
@@ -1,16 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http-2
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Cardoso
8
8
  - Ilya Grigorik
9
9
  - Kaoru Maeda
10
- autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2024-07-26 00:00:00.000000000 Z
12
+ date: 2025-04-10 00:00:00.000000000 Z
14
13
  dependencies: []
15
14
  description: Pure-ruby HTTP 2.0 protocol implementation
16
15
  email:
@@ -39,6 +38,7 @@ files:
39
38
  - lib/http/2/server.rb
40
39
  - lib/http/2/stream.rb
41
40
  - lib/http/2/version.rb
41
+ - sig/2.rbs
42
42
  - sig/client.rbs
43
43
  - sig/connection.rbs
44
44
  - sig/emitter.rbs
@@ -52,7 +52,6 @@ files:
52
52
  - sig/header/decompressor.rbs
53
53
  - sig/header/encoding_context.rbs
54
54
  - sig/header/huffman.rbs
55
- - sig/next.rbs
56
55
  - sig/server.rbs
57
56
  - sig/stream.rbs
58
57
  homepage: https://github.com/igrigorik/http-2
@@ -64,7 +63,6 @@ metadata:
64
63
  source_code_uri: https://github.com/igrigorik/http-2
65
64
  homepage_uri: https://github.com/igrigorik/http-2
66
65
  rubygems_mfa_required: 'true'
67
- post_install_message:
68
66
  rdoc_options: []
69
67
  require_paths:
70
68
  - lib
@@ -79,8 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
79
77
  - !ruby/object:Gem::Version
80
78
  version: '0'
81
79
  requirements: []
82
- rubygems_version: 3.5.3
83
- signing_key:
80
+ rubygems_version: 3.6.2
84
81
  specification_version: 4
85
82
  summary: Pure-ruby HTTP 2.0 protocol implementation
86
83
  test_files: []