http-2 0.12.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +10 -7
- data/lib/http/2/base64.rb +45 -0
- data/lib/http/2/client.rb +14 -5
- data/lib/http/2/connection.rb +176 -90
- data/lib/http/2/emitter.rb +4 -5
- data/lib/http/2/error.rb +22 -1
- data/lib/http/2/extensions.rb +53 -0
- data/lib/http/2/flow_buffer.rb +88 -35
- data/lib/http/2/framer.rb +127 -89
- 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} +11 -7
- 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 +39 -14
- data/lib/http/2/stream.rb +86 -17
- data/lib/http/2/version.rb +1 -1
- data/lib/http/2.rb +12 -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 +37 -25
- data/LICENSE +0 -21
- data/lib/http/2/buffer.rb +0 -78
- data/lib/http/2/compressor.rb +0 -580
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,16 +1,17 @@
|
|
1
1
|
# HTTP-2
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/http-2.svg)](http://rubygems.org/gems/http-2)
|
4
|
-
[![
|
4
|
+
[![Build status](https://github.com/igrigorik/http-2/actions/workflows/ci.yml/badge.svg)](https://github.com/igrigorik/http-2)
|
5
5
|
|
6
6
|
Pure Ruby, framework and transport agnostic, implementation of HTTP/2 protocol and HPACK header compression with support for:
|
7
7
|
|
8
|
+
|
8
9
|
* [Binary framing](https://hpbn.co/http2/#binary-framing-layer) parsing and encoding
|
9
10
|
* [Stream multiplexing](https://hpbn.co/http2/#streams-messages-and-frames) and [prioritization](https://hpbn.co/http2/#stream-prioritization)
|
10
11
|
* Connection and stream [flow control](https://hpbn.co/http2/#flow-control)
|
11
12
|
* [Header compression](https://hpbn.co/http2/#header-compression) and [server push](https://hpbn.co/http2/#server-push)
|
12
13
|
* Connection and stream management
|
13
|
-
* And more... see [API docs](
|
14
|
+
* And more... see [API docs](https://www.rubydoc.info/gems/http-2)
|
14
15
|
|
15
16
|
Protocol specifications:
|
16
17
|
|
@@ -30,6 +31,7 @@ Your code is responsible for feeding data into the parser, which performs all of
|
|
30
31
|
|
31
32
|
```ruby
|
32
33
|
require 'http/2'
|
34
|
+
|
33
35
|
socket = YourTransport.new
|
34
36
|
|
35
37
|
conn = HTTP2::Client.new
|
@@ -40,12 +42,12 @@ while bytes = socket.read
|
|
40
42
|
end
|
41
43
|
```
|
42
44
|
|
43
|
-
Checkout provided [client](
|
45
|
+
Checkout provided [client](example/client.rb) and [server](example/server.rb) implementations for basic examples.
|
44
46
|
|
45
47
|
|
46
48
|
### Connection lifecycle management
|
47
49
|
|
48
|
-
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:
|
49
51
|
|
50
52
|
```ruby
|
51
53
|
# - Server ---------------
|
@@ -148,7 +150,7 @@ conn.on(:stream) do |stream|
|
|
148
150
|
end
|
149
151
|
```
|
150
152
|
|
151
|
-
Events emitted by the [Stream object](http
|
153
|
+
Events emitted by the [Stream object](lib/http/2/stream.rb):
|
152
154
|
|
153
155
|
<table>
|
154
156
|
<tr>
|
@@ -252,7 +254,7 @@ conn.on(:stream) do |stream|
|
|
252
254
|
# split response between multiple DATA frames
|
253
255
|
stream.data(response_chunk, end_stream: false)
|
254
256
|
stream.data(last_chunk)
|
255
|
-
|
257
|
+
|
256
258
|
# now send the previously promised data
|
257
259
|
push_stream.data(push_data)
|
258
260
|
end
|
@@ -283,4 +285,5 @@ rake
|
|
283
285
|
|
284
286
|
### License
|
285
287
|
|
286
|
-
(MIT License) - Copyright (c) 2013 Ilya Grigorik ![GA](https://www.google-analytics.com/__utm.gif?utmac=UA-71196-9&utmhn=github.com&utmdt=HTTP2&utmp=/http-2/readme)
|
288
|
+
(MIT License) - Copyright (c) 2013-2019 Ilya Grigorik ![GA](https://www.google-analytics.com/__utm.gif?utmac=UA-71196-9&utmhn=github.com&utmdt=HTTP2&utmp=/http-2/readme)
|
289
|
+
(MIT License) - Copyright (c) 2019 Tiago Cardoso ![GA](https://www.google-analytics.com/__utm.gif?utmac=UA-71196-9&utmhn=github.com&utmdt=HTTP2&utmp=/http-2/readme)
|
@@ -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
@@ -20,7 +20,7 @@ module HTTP2
|
|
20
20
|
#
|
21
21
|
class Client < Connection
|
22
22
|
# Initialize new HTTP 2.0 client object.
|
23
|
-
def initialize(
|
23
|
+
def initialize(settings = {})
|
24
24
|
@stream_id = 1
|
25
25
|
@state = :waiting_connection_preface
|
26
26
|
|
@@ -37,20 +37,23 @@ module HTTP2
|
|
37
37
|
# @param frame [Hash]
|
38
38
|
def send(frame)
|
39
39
|
send_connection_preface
|
40
|
-
super
|
40
|
+
super
|
41
41
|
end
|
42
42
|
|
43
43
|
def receive(frame)
|
44
44
|
send_connection_preface
|
45
|
-
super
|
45
|
+
super
|
46
46
|
end
|
47
47
|
|
48
48
|
# sends the preface and initializes the first stream in half-closed state
|
49
49
|
def upgrade
|
50
|
+
@h2c_upgrade = :start
|
50
51
|
raise ProtocolError unless @stream_id == 1
|
51
52
|
|
52
53
|
send_connection_preface
|
53
|
-
new_stream(state: :half_closed_local)
|
54
|
+
stream = new_stream(state: :half_closed_local)
|
55
|
+
@h2c_upgrade = :finished
|
56
|
+
stream
|
54
57
|
end
|
55
58
|
|
56
59
|
# Emit the connection preface if not yet
|
@@ -64,9 +67,15 @@ module HTTP2
|
|
64
67
|
settings(payload)
|
65
68
|
end
|
66
69
|
|
67
|
-
def self.settings_header(
|
70
|
+
def self.settings_header(settings)
|
68
71
|
frame = Framer.new.generate(type: :settings, stream: 0, payload: settings)
|
69
72
|
Base64.urlsafe_encode64(frame[9..-1])
|
70
73
|
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def verify_pseudo_headers(frame)
|
78
|
+
_verify_pseudo_headers(frame, RESPONSE_MANDATORY_HEADERS)
|
79
|
+
end
|
71
80
|
end
|
72
81
|
end
|