h2 0.6.0 → 0.6.1
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/CHANGELOG.md +5 -0
- data/Gemfile +2 -0
- data/exe/h2 +1 -6
- data/lib/h2.rb +41 -0
- data/lib/h2/client.rb +27 -10
- data/lib/h2/client/celluloid.rb +1 -0
- data/lib/h2/client/concurrent.rb +1 -0
- data/lib/h2/server.rb +0 -14
- data/lib/h2/server/connection.rb +3 -25
- data/lib/h2/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9a9868c3d9496207683352704cd152a9d5426ff42cd3aa30035a56981596e957
|
4
|
+
data.tar.gz: 43e60980d431d769835d4bb15de0cacbb5676c250b1e461c31e4f88c89734c48
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19e4e75141869144f1ed7b6abf8b6faeb61d00db6466d02ec5264ec7d95ddada0de2914b071dc13a5293885189fea5cb9b235515fc8e282218244d19b5eea08a
|
7
|
+
data.tar.gz: 50a36bbc351d0dca3cc81750800e2a5085e403bc6019a8620cef8ec5d8977c4e227dcd994656365eb9d75ae03d4fdb0dd9d2e740f2eeccbdf636210f8952dd50
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/exe/h2
CHANGED
@@ -9,7 +9,6 @@ require 'colored'
|
|
9
9
|
require 'optparse'
|
10
10
|
|
11
11
|
begin # {{{
|
12
|
-
raise LoadError if ARGV.include?('--dev')
|
13
12
|
require 'h2'
|
14
13
|
rescue LoadError
|
15
14
|
$: << File.expand_path('../../lib', __FILE__)
|
@@ -59,10 +58,6 @@ OptionParser.new do |o|
|
|
59
58
|
options[:debug] = true
|
60
59
|
end
|
61
60
|
|
62
|
-
o.on '--dev', 'load lib from source tree' do
|
63
|
-
# handled above for reasons
|
64
|
-
end
|
65
|
-
|
66
61
|
o.on '-g', '--goaway', 'send GOAWAY frame when stream is complete' do
|
67
62
|
options[:goaway] = true
|
68
63
|
end
|
@@ -142,8 +137,8 @@ end
|
|
142
137
|
|
143
138
|
puts s.body
|
144
139
|
|
145
|
-
c.goaway if options[:goaway]
|
146
140
|
c.block! if options[:block]
|
141
|
+
c.goaway if options[:goaway]
|
147
142
|
c.close
|
148
143
|
|
149
144
|
# }}}
|
data/lib/h2.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'http/2'
|
4
|
+
require 'logger'
|
4
5
|
require 'uri'
|
5
6
|
require 'h2/version'
|
6
7
|
|
@@ -28,8 +29,21 @@ module H2
|
|
28
29
|
:put
|
29
30
|
]
|
30
31
|
|
32
|
+
Logger = ::Logger.new STDOUT
|
33
|
+
|
31
34
|
class << self
|
32
35
|
|
36
|
+
# turn on extra verbose debug logging
|
37
|
+
#
|
38
|
+
def verbose!
|
39
|
+
@verbose = true
|
40
|
+
end
|
41
|
+
|
42
|
+
def verbose?
|
43
|
+
@verbose = false unless defined?(@verbose)
|
44
|
+
@verbose
|
45
|
+
end
|
46
|
+
|
33
47
|
# convenience wrappers to make requests with HTTP methods
|
34
48
|
#
|
35
49
|
# @see H2.request
|
@@ -120,6 +134,33 @@ module H2
|
|
120
134
|
|
121
135
|
end
|
122
136
|
|
137
|
+
module FrameDebugger
|
138
|
+
|
139
|
+
def self.included base
|
140
|
+
H2.verbose!
|
141
|
+
base::PARSER_EVENTS.push :frame_sent, :frame_received
|
142
|
+
end
|
143
|
+
|
144
|
+
def on_frame_sent f
|
145
|
+
Logger.debug "Sent frame: #{truncate_frame(f).inspect}"
|
146
|
+
end
|
147
|
+
|
148
|
+
def on_frame_received f
|
149
|
+
Logger.debug "Received frame: #{truncate_frame(f).inspect}"
|
150
|
+
end
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
def truncate_string s
|
155
|
+
(String === s && s.length > 64) ? "#{s[0,64]}..." : s
|
156
|
+
end
|
157
|
+
|
158
|
+
def truncate_frame f
|
159
|
+
f.reduce({}) { |h, (k, v)| h[k] = truncate_string(v); h }
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
|
123
164
|
end
|
124
165
|
|
125
166
|
require 'h2/client'
|
data/lib/h2/client.rb
CHANGED
@@ -7,16 +7,18 @@ module H2
|
|
7
7
|
include Blockable
|
8
8
|
include On
|
9
9
|
|
10
|
-
|
10
|
+
PARSER_EVENTS = [
|
11
11
|
:close,
|
12
12
|
:frame,
|
13
13
|
:goaway,
|
14
14
|
:promise
|
15
15
|
]
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
# include FrameDebugger
|
18
|
+
|
19
|
+
ALPN_PROTOCOLS = ['h2']
|
20
|
+
DEFAULT_MAXLEN = 4096
|
21
|
+
RE_IP_ADDR = Regexp.union Resolv::IPv4::Regex, Resolv::IPv6::Regex
|
20
22
|
|
21
23
|
attr_accessor :last_stream
|
22
24
|
attr_reader :client, :reader, :scheme, :socket, :streams
|
@@ -24,14 +26,14 @@ module H2
|
|
24
26
|
# create a new h2 client
|
25
27
|
#
|
26
28
|
# @param [String] host IP address or hostname
|
27
|
-
# @param [Integer] port TCP port
|
29
|
+
# @param [Integer] port TCP port (default: 443)
|
28
30
|
# @param [String,URI] url full URL to parse (optional: existing +URI+ instance)
|
29
31
|
# @param [Hash,FalseClass] tls TLS options (optional: +false+ do not use TLS)
|
30
32
|
# @option tls [String] :cafile path to CA file
|
31
33
|
#
|
32
34
|
# @return [H2::Client]
|
33
35
|
#
|
34
|
-
def initialize host: nil, port:
|
36
|
+
def initialize host: nil, port: 443, url: nil, tls: {}
|
35
37
|
raise ArgumentError if url.nil? && (host.nil? || port.nil?)
|
36
38
|
|
37
39
|
if url
|
@@ -52,11 +54,12 @@ module H2
|
|
52
54
|
@socket = tls_socket @socket if @tls
|
53
55
|
@client = HTTP2::Client.new
|
54
56
|
|
57
|
+
@first = true
|
58
|
+
@reading = false
|
59
|
+
|
55
60
|
init_blocking
|
56
61
|
yield self if block_given?
|
57
62
|
bind_events
|
58
|
-
|
59
|
-
read
|
60
63
|
end
|
61
64
|
|
62
65
|
# @return true if the connection is closed
|
@@ -76,6 +79,14 @@ module H2
|
|
76
79
|
@socket.eof?
|
77
80
|
end
|
78
81
|
|
82
|
+
def reading?
|
83
|
+
@mutex.synchronize { @reading }
|
84
|
+
end
|
85
|
+
|
86
|
+
def reading!
|
87
|
+
@mutex.synchronize { @reading = true }
|
88
|
+
end
|
89
|
+
|
79
90
|
# send a goaway frame and wait until the connection is closed
|
80
91
|
#
|
81
92
|
def goaway!
|
@@ -98,7 +109,7 @@ module H2
|
|
98
109
|
# binds all connection events to their respective on_ handlers
|
99
110
|
#
|
100
111
|
def bind_events
|
101
|
-
|
112
|
+
PARSER_EVENTS.each do |e|
|
102
113
|
@client.on(e){|*a| __send__ "on_#{e}", *a}
|
103
114
|
end
|
104
115
|
end
|
@@ -194,6 +205,8 @@ module H2
|
|
194
205
|
# creates a new +Thread+ to read the given number of bytes each loop from
|
195
206
|
# the current +@socket+
|
196
207
|
#
|
208
|
+
# NOTE: initial client frames (settings, etc) should be sent first!
|
209
|
+
#
|
197
210
|
# NOTE: this is the override point for celluloid actor pool or concurrent
|
198
211
|
# ruby threadpool support
|
199
212
|
#
|
@@ -202,6 +215,7 @@ module H2
|
|
202
215
|
def read maxlen = DEFAULT_MAXLEN
|
203
216
|
main = Thread.current
|
204
217
|
@reader = Thread.new do
|
218
|
+
reading!
|
205
219
|
begin
|
206
220
|
_read maxlen
|
207
221
|
rescue => e
|
@@ -230,7 +244,7 @@ module H2
|
|
230
244
|
begin
|
231
245
|
@client << data
|
232
246
|
rescue HTTP2::Error::ProtocolError => pe
|
233
|
-
STDERR.puts
|
247
|
+
STDERR.puts "protocol error: #{pe.message}"
|
234
248
|
STDERR.puts pe.backtrace.map {|l| "\t" + l}
|
235
249
|
end
|
236
250
|
end
|
@@ -286,6 +300,9 @@ module H2
|
|
286
300
|
@socket.write bytes
|
287
301
|
end
|
288
302
|
@socket.flush
|
303
|
+
|
304
|
+
@first = false if @first
|
305
|
+
read unless @first or @reading
|
289
306
|
end
|
290
307
|
|
291
308
|
# fake exceptionless IO for writing on older ruby versions
|
data/lib/h2/client/celluloid.rb
CHANGED
data/lib/h2/client/concurrent.rb
CHANGED
data/lib/h2/server.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'celluloid/current'
|
2
|
-
require 'logger'
|
3
2
|
require 'reel'
|
4
3
|
require 'h2/reel/ext'
|
5
4
|
require 'h2'
|
@@ -8,8 +7,6 @@ module H2
|
|
8
7
|
|
9
8
|
CONTENT_LENGTH_KEY = 'content-length'
|
10
9
|
|
11
|
-
Logger = ::Logger.new STDOUT
|
12
|
-
|
13
10
|
class << self
|
14
11
|
|
15
12
|
def alpn?
|
@@ -21,17 +18,6 @@ module H2
|
|
21
18
|
@jruby = RUBY_ENGINE == 'jruby'
|
22
19
|
end
|
23
20
|
|
24
|
-
# turn on extra verbose debug logging
|
25
|
-
#
|
26
|
-
def verbose!
|
27
|
-
@verbose = true
|
28
|
-
end
|
29
|
-
|
30
|
-
def verbose?
|
31
|
-
@verbose = false unless defined?(@verbose)
|
32
|
-
@verbose
|
33
|
-
end
|
34
|
-
|
35
21
|
end
|
36
22
|
|
37
23
|
# base H2 server, a direct subclass of +Reel::Server+
|
data/lib/h2/server/connection.rb
CHANGED
@@ -13,12 +13,12 @@ module H2
|
|
13
13
|
#
|
14
14
|
PARSER_EVENTS = [
|
15
15
|
:frame,
|
16
|
-
:frame_sent,
|
17
|
-
:frame_received,
|
18
16
|
:stream,
|
19
17
|
:goaway
|
20
18
|
]
|
21
19
|
|
20
|
+
# include FrameDebugger
|
21
|
+
|
22
22
|
attr_reader :parser, :server, :socket
|
23
23
|
|
24
24
|
def initialize socket:, server:
|
@@ -94,7 +94,7 @@ module H2
|
|
94
94
|
|
95
95
|
rescue => e
|
96
96
|
Logger.error "Exception: #{e.message} - closing socket"
|
97
|
-
STDERR.puts e.backtrace
|
97
|
+
STDERR.puts e.backtrace if H2.verbose?
|
98
98
|
close
|
99
99
|
|
100
100
|
end
|
@@ -107,24 +107,12 @@ module H2
|
|
107
107
|
# called by +@parser+ with a binary frame to write to the +@socket+
|
108
108
|
#
|
109
109
|
def on_frame bytes
|
110
|
-
Logger.debug "Writing bytes: #{truncate_string(bytes.unpack("H*").first)}" if H2.verbose?
|
111
|
-
|
112
|
-
# N.B. this is the important bit
|
113
|
-
#
|
114
110
|
@socket.write bytes
|
115
111
|
rescue IOError, Errno::EPIPE => e
|
116
112
|
Logger.error e.message
|
117
113
|
close
|
118
114
|
end
|
119
115
|
|
120
|
-
def on_frame_sent f
|
121
|
-
Logger.debug "Sent frame: #{truncate_frame(f).inspect}" if H2.verbose?
|
122
|
-
end
|
123
|
-
|
124
|
-
def on_frame_received f
|
125
|
-
Logger.debug "Received frame: #{truncate_frame(f).inspect}" if H2.verbose?
|
126
|
-
end
|
127
|
-
|
128
116
|
# the +@parser+ calls this when a new stream has been initiated by the
|
129
117
|
# client
|
130
118
|
#
|
@@ -138,16 +126,6 @@ module H2
|
|
138
126
|
close
|
139
127
|
end
|
140
128
|
|
141
|
-
private
|
142
|
-
|
143
|
-
def truncate_string s
|
144
|
-
(String === s && s.length > 64) ? "#{s[0,64]}..." : s
|
145
|
-
end
|
146
|
-
|
147
|
-
def truncate_frame f
|
148
|
-
f.reduce({}) { |h, (k, v)| h[k] = truncate_string(v); h }
|
149
|
-
end
|
150
|
-
|
151
129
|
end
|
152
130
|
end
|
153
131
|
end
|
data/lib/h2/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: h2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kenichi Nakamura
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-07-
|
11
|
+
date: 2018-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: http-2
|