http-2 0.11.0 → 1.0.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 +4 -4
- data/README.md +10 -9
- data/lib/http/2/base64.rb +45 -0
- data/lib/http/2/client.rb +19 -6
- data/lib/http/2/connection.rb +235 -163
- data/lib/http/2/emitter.rb +7 -5
- data/lib/http/2/error.rb +24 -1
- data/lib/http/2/extensions.rb +53 -0
- data/lib/http/2/flow_buffer.rb +91 -33
- data/lib/http/2/framer.rb +184 -157
- data/lib/http/2/header/compressor.rb +157 -0
- data/lib/http/2/header/decompressor.rb +144 -0
- data/lib/http/2/header/encoding_context.rb +337 -0
- data/lib/http/2/{huffman.rb → header/huffman.rb} +25 -19
- data/lib/http/2/{huffman_statemachine.rb → header/huffman_statemachine.rb} +2 -0
- data/lib/http/2/header.rb +35 -0
- data/lib/http/2/server.rb +47 -20
- data/lib/http/2/stream.rb +130 -61
- data/lib/http/2/version.rb +3 -1
- data/lib/http/2.rb +14 -13
- data/sig/client.rbs +9 -0
- data/sig/connection.rbs +93 -0
- data/sig/emitter.rbs +13 -0
- data/sig/error.rbs +35 -0
- data/sig/extensions.rbs +5 -0
- data/sig/flow_buffer.rbs +21 -0
- data/sig/frame_buffer.rbs +13 -0
- data/sig/framer.rbs +54 -0
- data/sig/header/compressor.rbs +27 -0
- data/sig/header/decompressor.rbs +22 -0
- data/sig/header/encoding_context.rbs +34 -0
- data/sig/header/huffman.rbs +9 -0
- data/sig/header.rbs +27 -0
- data/sig/next.rbs +101 -0
- data/sig/server.rbs +12 -0
- data/sig/stream.rbs +91 -0
- metadata +38 -79
- data/.autotest +0 -20
- data/.coveralls.yml +0 -1
- data/.gitignore +0 -20
- data/.gitmodules +0 -3
- data/.rspec +0 -5
- data/.rubocop.yml +0 -93
- data/.rubocop_todo.yml +0 -131
- data/.travis.yml +0 -17
- data/Gemfile +0 -16
- data/Guardfile +0 -18
- data/Guardfile.h2spec +0 -12
- data/LICENSE +0 -21
- data/Rakefile +0 -49
- data/example/Gemfile +0 -3
- data/example/README.md +0 -44
- data/example/client.rb +0 -122
- data/example/helper.rb +0 -19
- data/example/keys/server.crt +0 -20
- data/example/keys/server.key +0 -27
- data/example/server.rb +0 -139
- data/example/upgrade_client.rb +0 -153
- data/example/upgrade_server.rb +0 -203
- data/http-2.gemspec +0 -22
- data/lib/http/2/buffer.rb +0 -76
- data/lib/http/2/compressor.rb +0 -572
- data/lib/tasks/generate_huffman_table.rb +0 -166
- data/spec/buffer_spec.rb +0 -28
- data/spec/client_spec.rb +0 -188
- data/spec/compressor_spec.rb +0 -666
- data/spec/connection_spec.rb +0 -681
- data/spec/emitter_spec.rb +0 -54
- data/spec/framer_spec.rb +0 -487
- data/spec/h2spec/h2spec.darwin +0 -0
- data/spec/h2spec/output/non_secure.txt +0 -317
- data/spec/helper.rb +0 -147
- data/spec/hpack_test_spec.rb +0 -84
- data/spec/huffman_spec.rb +0 -68
- data/spec/server_spec.rb +0 -52
- data/spec/stream_spec.rb +0 -878
- data/spec/support/deep_dup.rb +0 -55
- data/spec/support/duplicable.rb +0 -98
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c5b015395ca278b22ea3af7f2c0c149071ddb1ad4cd5db5c52329554de87fe27
|
4
|
+
data.tar.gz: 3f7a6d671bd23efe5b60f16dc39294b6cd7a45d6087ff1be70f0624f682895a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce8dff286d18b7607a338572b9b85ab2ff88eb8a28b8de8a6139344d0cc2f3ebc700ca9affc8398526b88fb95b7fe5da90209c5c6fbdff155c319f9e8691062b
|
7
|
+
data.tar.gz: b7f920fc81747d811855eec66a8f63e5a18d5a8ca49d81efe8f6567c6c72a1275c4846219a1532855834717453a7e0d914d3138296fb24876f5af3d9c3151772
|
data/README.md
CHANGED
@@ -1,18 +1,17 @@
|
|
1
1
|
# HTTP-2
|
2
2
|
|
3
3
|
[](http://rubygems.org/gems/http-2)
|
4
|
-
[](https://coveralls.io/r/igrigorik/http-2)
|
6
|
-
[](https://github.com/igrigorik/ga-beacon)
|
4
|
+
[](https://github.com/igrigorik/http-2)
|
7
5
|
|
8
6
|
Pure Ruby, framework and transport agnostic, implementation of HTTP/2 protocol and HPACK header compression with support for:
|
9
7
|
|
8
|
+
|
10
9
|
* [Binary framing](https://hpbn.co/http2/#binary-framing-layer) parsing and encoding
|
11
10
|
* [Stream multiplexing](https://hpbn.co/http2/#streams-messages-and-frames) and [prioritization](https://hpbn.co/http2/#stream-prioritization)
|
12
11
|
* Connection and stream [flow control](https://hpbn.co/http2/#flow-control)
|
13
12
|
* [Header compression](https://hpbn.co/http2/#header-compression) and [server push](https://hpbn.co/http2/#server-push)
|
14
13
|
* Connection and stream management
|
15
|
-
* And more... see [API docs](
|
14
|
+
* And more... see [API docs](https://www.rubydoc.info/gems/http-2)
|
16
15
|
|
17
16
|
Protocol specifications:
|
18
17
|
|
@@ -32,6 +31,7 @@ Your code is responsible for feeding data into the parser, which performs all of
|
|
32
31
|
|
33
32
|
```ruby
|
34
33
|
require 'http/2'
|
34
|
+
|
35
35
|
socket = YourTransport.new
|
36
36
|
|
37
37
|
conn = HTTP2::Client.new
|
@@ -42,12 +42,12 @@ while bytes = socket.read
|
|
42
42
|
end
|
43
43
|
```
|
44
44
|
|
45
|
-
Checkout provided [client](
|
45
|
+
Checkout provided [client](example/client.rb) and [server](example/server.rb) implementations for basic examples.
|
46
46
|
|
47
47
|
|
48
48
|
### Connection lifecycle management
|
49
49
|
|
50
|
-
Depending on the role of the endpoint you must initialize either a [Client](http
|
50
|
+
Depending on the role of the endpoint you must initialize either a [Client](lib/http/2/client.rb) or a [Server](lib/http/2/server.rb) object. Doing so picks the appropriate header compression / decompression algorithms and stream management logic. From there, you can subscribe to connection level events, or invoke appropriate APIs to allocate new streams and manage the lifecycle. For example:
|
51
51
|
|
52
52
|
```ruby
|
53
53
|
# - Server ---------------
|
@@ -150,7 +150,7 @@ conn.on(:stream) do |stream|
|
|
150
150
|
end
|
151
151
|
```
|
152
152
|
|
153
|
-
Events emitted by the [Stream object](http
|
153
|
+
Events emitted by the [Stream object](lib/http/2/stream.rb):
|
154
154
|
|
155
155
|
<table>
|
156
156
|
<tr>
|
@@ -254,7 +254,7 @@ conn.on(:stream) do |stream|
|
|
254
254
|
# split response between multiple DATA frames
|
255
255
|
stream.data(response_chunk, end_stream: false)
|
256
256
|
stream.data(last_chunk)
|
257
|
-
|
257
|
+
|
258
258
|
# now send the previously promised data
|
259
259
|
push_stream.data(push_data)
|
260
260
|
end
|
@@ -285,4 +285,5 @@ rake
|
|
285
285
|
|
286
286
|
### License
|
287
287
|
|
288
|
-
(MIT License) - Copyright (c) 2013 Ilya Grigorik 
|
288
|
+
(MIT License) - Copyright (c) 2013-2019 Ilya Grigorik 
|
289
|
+
(MIT License) - Copyright (c) 2019 Tiago Cardoso 
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
if RUBY_VERSION < "3.3.0"
|
4
|
+
require "base64"
|
5
|
+
elsif !defined?(Base64)
|
6
|
+
module HTTP2
|
7
|
+
# require "base64" will not be a default gem after ruby 3.4.0
|
8
|
+
module Base64
|
9
|
+
module_function
|
10
|
+
|
11
|
+
def encode64(bin)
|
12
|
+
[bin].pack("m")
|
13
|
+
end
|
14
|
+
|
15
|
+
def decode64(str)
|
16
|
+
str.unpack1("m")
|
17
|
+
end
|
18
|
+
|
19
|
+
def strict_encode64(bin)
|
20
|
+
[bin].pack("m0")
|
21
|
+
end
|
22
|
+
|
23
|
+
def strict_decode64(str)
|
24
|
+
str.unpack1("m0")
|
25
|
+
end
|
26
|
+
|
27
|
+
def urlsafe_encode64(bin, padding: true)
|
28
|
+
str = strict_encode64(bin)
|
29
|
+
str.chomp!("==") or str.chomp!("=") unless padding
|
30
|
+
str.tr!("+/", "-_")
|
31
|
+
str
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def urlsafe_decode64(str)
|
36
|
+
if !str.end_with?("=") && str.length % 4 != 0
|
37
|
+
str = str.ljust((str.length + 3) & ~3, "=")
|
38
|
+
str.tr!("-_", "+/")
|
39
|
+
else
|
40
|
+
str = str.tr("-_", "+/")
|
41
|
+
end
|
42
|
+
strict_decode64(str)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/http/2/client.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module HTTP2
|
2
4
|
# HTTP 2.0 client connection class that implements appropriate header
|
3
5
|
# compression / decompression algorithms and stream management logic.
|
@@ -18,7 +20,7 @@ module HTTP2
|
|
18
20
|
#
|
19
21
|
class Client < Connection
|
20
22
|
# Initialize new HTTP 2.0 client object.
|
21
|
-
def initialize(
|
23
|
+
def initialize(settings = {})
|
22
24
|
@stream_id = 1
|
23
25
|
@state = :waiting_connection_preface
|
24
26
|
|
@@ -35,24 +37,29 @@ module HTTP2
|
|
35
37
|
# @param frame [Hash]
|
36
38
|
def send(frame)
|
37
39
|
send_connection_preface
|
38
|
-
super
|
40
|
+
super
|
39
41
|
end
|
40
42
|
|
41
43
|
def receive(frame)
|
42
44
|
send_connection_preface
|
43
|
-
super
|
45
|
+
super
|
44
46
|
end
|
45
47
|
|
46
48
|
# sends the preface and initializes the first stream in half-closed state
|
47
49
|
def upgrade
|
48
|
-
|
50
|
+
@h2c_upgrade = :start
|
51
|
+
raise ProtocolError unless @stream_id == 1
|
52
|
+
|
49
53
|
send_connection_preface
|
50
|
-
new_stream(state: :half_closed_local)
|
54
|
+
stream = new_stream(state: :half_closed_local)
|
55
|
+
@h2c_upgrade = :finished
|
56
|
+
stream
|
51
57
|
end
|
52
58
|
|
53
59
|
# Emit the connection preface if not yet
|
54
60
|
def send_connection_preface
|
55
61
|
return unless @state == :waiting_connection_preface
|
62
|
+
|
56
63
|
@state = :connected
|
57
64
|
emit(:frame, CONNECTION_PREFACE_MAGIC)
|
58
65
|
|
@@ -60,9 +67,15 @@ module HTTP2
|
|
60
67
|
settings(payload)
|
61
68
|
end
|
62
69
|
|
63
|
-
def self.settings_header(
|
70
|
+
def self.settings_header(settings)
|
64
71
|
frame = Framer.new.generate(type: :settings, stream: 0, payload: settings)
|
65
72
|
Base64.urlsafe_encode64(frame[9..-1])
|
66
73
|
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def verify_pseudo_headers(frame)
|
78
|
+
_verify_pseudo_headers(frame, RESPONSE_MANDATORY_HEADERS)
|
79
|
+
end
|
67
80
|
end
|
68
81
|
end
|