h2 0.5.0 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b2ce1f4f619d3bd9eb680ad49ad0181ef4a5e81b0a9fa07f0b8e544b85b77028
4
- data.tar.gz: 34de290127df74e156b02e595f2b1ea91ab3da6edf38cfff263a4734e16297cc
3
+ metadata.gz: e62e384940a1e408102e4e518942c1245ce374f82007c858d9de5a0b286c2301
4
+ data.tar.gz: d3fc7f3d111b3786cb50c58f862b32dad713557ae69cf18233cd1eda7ca0d5be
5
5
  SHA512:
6
- metadata.gz: 2a89223df4da4f8effb784628e711bd9341b63b096ecfa5d1bb970f2d9a447c59e51871167c7da1f48eb3fc70436970fe64a84400ab93ab7e835e7d165cc203b
7
- data.tar.gz: 81cd03234bc8eff7a0acc6d69105ba5cf9599b8ad9b8193c28679d6c1fb504a612cb9c5062bba7f4c3ebe5448636908c8c87e75666de0575b78bb28d9a4b0e8f
6
+ metadata.gz: 907a28fb440862cbc3a6a9dbb80db39408f3635f4aa4983358bba508617ddbb8fcb9da0a30b3601a614f4ea7a79ff4cceece1b7d1c687b6afc3e663ad5d4459d
7
+ data.tar.gz: 317f75c090f2f54526a2bff4b2e8b7d298ab7f6bf8f4653e9bd5ac2916f333133e26a7b47d357c447a7a0a6741468b99733e1212c71ee018f4698c51b0ea5eaf
data/CHANGELOG.md CHANGED
@@ -1,7 +1,17 @@
1
1
  h2 changelog
2
2
  ============
3
3
 
4
- ### 0.4.1 16 jun 2017
4
+ ### 0.6.0 25 jul 2018
5
+
6
+ * update server API - kwargs
7
+ * update client API - addr: -> host:
8
+ * add rubydoc, update readme
9
+
10
+ ### 0.5.0 21 jul 2018
11
+
12
+ * add server
13
+
14
+ ### 0.4.1 17 jul 2018
5
15
 
6
16
  * update .travis.yml for latest supported versions
7
17
  * add CLI flags for threading model
data/README.md CHANGED
@@ -20,7 +20,7 @@ require 'h2/server'
20
20
 
21
21
  server = H2::Server::HTTP.new host: addr, port: port do |connection|
22
22
  connection.each_stream do |stream|
23
- stream.respond :ok, "hello, world!\n"
23
+ stream.respond status: 200, body: "hello, world!\n"
24
24
  stream.connection.goaway
25
25
  end
26
26
  end
@@ -29,7 +29,7 @@ stream = H2.get url: "http://#{addr}:#{port}", tls: false
29
29
  stream.body #=> "hello, world!\n"
30
30
  ```
31
31
 
32
- See [examples](https://github.com/kenichi/h2/tree/master/examples/server/)
32
+ See [examples](https://github.com/kenichi/h2/tree/master/examples/server/).
33
33
 
34
34
  ## Client Usage
35
35
 
@@ -55,7 +55,7 @@ client.closed? #=> true
55
55
  # --- normal connection
56
56
  #
57
57
 
58
- client = H2::Client.new addr: 'example.com', port: 443
58
+ client = H2::Client.new host: 'example.com', port: 443
59
59
 
60
60
  stream = client.get path: '/'
61
61
 
@@ -103,7 +103,7 @@ If you're running on macOS and using Homebrew's openssl package, you may need to
103
103
  specify the CA file in the TLS options:
104
104
 
105
105
  ```ruby
106
- client = H2::Client.new addr: 'example.com', port: 443, tls: { ca_file: '/usr/local/etc/openssl/cert.pem' }
106
+ client = H2::Client.new host: 'example.com', port: 443, tls: { ca_file: '/usr/local/etc/openssl/cert.pem' }
107
107
  ```
108
108
 
109
109
  or when using the CLI:
@@ -12,7 +12,7 @@ addr, port = '127.0.0.1', 1234
12
12
  puts "*** Starting server on http://#{addr}:#{port}"
13
13
  s = H2::Server::HTTP.new host: addr, port: port do |connection|
14
14
  connection.each_stream do |stream|
15
- stream.respond :ok, "hello, world!\n"
15
+ stream.respond status: 200, body: "hello, world!\n"
16
16
  stream.connection.goaway
17
17
  end
18
18
  end
@@ -21,9 +21,9 @@ s = H2::Server::HTTPS.new host: addr, port: port, **tls do |connection|
21
21
  stream.goaway_on_complete
22
22
 
23
23
  if stream.request.path == '/favicon.ico'
24
- stream.respond :not_found
24
+ stream.respond status: 404
25
25
  else
26
- stream.respond :ok, "hello, world!\n"
26
+ stream.respond status: 200, body: "hello, world!\n"
27
27
  end
28
28
  end
29
29
  end
@@ -11,7 +11,7 @@ port = 1234
11
11
  addr = Socket.getaddrinfo('localhost', port).first[3]
12
12
  certs_dir = File.expand_path '../../../tmp/certs', __FILE__
13
13
  dog_png = File.read File.expand_path '../dog.png', __FILE__
14
- push_promise = '<html>wait for it...<img src="/dog.png"/><script src="/pushed.js"></script></html>'
14
+ push_promise = '<html><body>wait for it...<img src="/dog.png"/><script src="/pushed.js"></script></body></html>'
15
15
  pushed_js = '(()=>{ alert("hello h2 push promise!"); })();'
16
16
 
17
17
  sni = {
@@ -27,17 +27,21 @@ s = H2::Server::HTTPS.new host: addr, port: port, sni: sni do |connection|
27
27
  connection.each_stream do |stream|
28
28
 
29
29
  if stream.request.path == '/favicon.ico'
30
- stream.respond :not_found
30
+ stream.respond status: 404
31
31
 
32
32
  else
33
33
  stream.goaway_on_complete
34
34
 
35
- stream.push_promise '/dog.png', { 'content-type' => 'image/png' }, dog_png
35
+ # one-line convenience with async "keep" handler
36
+ stream.push_promise path: '/dog.png', headers: { 'content-type' => 'image/png' }, body: dog_png
36
37
 
37
- js_promise = stream.push_promise_for '/pushed.js', { 'content-type' => 'application/javascript' }, pushed_js
38
+ # more control over when promises are "kept"...
39
+ js_promise = stream.push_promise_for path: '/pushed.js',
40
+ headers: { 'content-type' => 'application/javascript' },
41
+ body: pushed_js
38
42
  js_promise.make_on stream
39
43
 
40
- stream.respond :ok, push_promise
44
+ stream.respond status: 200, body: push_promise
41
45
 
42
46
  js_promise.keep
43
47
  end
data/exe/h2 CHANGED
@@ -8,9 +8,8 @@
8
8
  require 'colored'
9
9
  require 'optparse'
10
10
 
11
- $: << File.expand_path('../../../http-2/lib', __FILE__)
12
-
13
11
  begin # {{{
12
+ raise LoadError if ARGV.include?('--dev')
14
13
  require 'h2'
15
14
  rescue LoadError
16
15
  $: << File.expand_path('../../lib', __FILE__)
@@ -60,6 +59,10 @@ OptionParser.new do |o|
60
59
  options[:debug] = true
61
60
  end
62
61
 
62
+ o.on '--dev', 'load lib from source tree' do
63
+ # handled above for reasons
64
+ end
65
+
63
66
  o.on '-g', '--goaway', 'send GOAWAY frame when stream is complete' do
64
67
  options[:goaway] = true
65
68
  end
data/h2.gemspec CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
17
17
 
18
18
  spec.required_ruby_version = '>= 2.2'
19
19
 
20
- spec.add_dependency 'http-2', '~> 0.9', '>= 0.9.1'
20
+ spec.add_dependency 'http-2', '~> 0.10', '>= 0.10.0'
21
21
  spec.add_dependency 'colored', '1.2'
22
22
 
23
23
  spec.add_development_dependency "bundler", "~> 1.15"
data/lib/h2.rb CHANGED
@@ -30,6 +30,10 @@ module H2
30
30
 
31
31
  class << self
32
32
 
33
+ # convenience wrappers to make requests with HTTP methods
34
+ #
35
+ # @see H2.request
36
+ #
33
37
  REQUEST_METHODS.each do |m|
34
38
  define_method m do |**args, &block|
35
39
  request method: m, **args, &block
@@ -38,25 +42,43 @@ module H2
38
42
 
39
43
  private
40
44
 
41
- def request addr: nil,
45
+ # creates a +H2::Client+ and initiates a +H2::Stream+ by making a request
46
+ # with the given HTTP method
47
+ #
48
+ # @param [String] host IP address or hostname
49
+ # @param [Integer] port TCP port
50
+ # @param [String,URI] url full URL to parse (optional: existing +URI+ instance)
51
+ # @param [Symbol] method HTTP request method
52
+ # @param [String] path request path
53
+ # @param [Hash] headers request headers
54
+ # @param [Hash] params request query string parameters
55
+ # @param [String] body request body
56
+ # @param [Hash,FalseClass] tls TLS options (optional: +false+ do not use TLS)
57
+ # @option tls [String] :cafile path to CA file
58
+ #
59
+ # @yield [H2::Stream]
60
+ #
61
+ # @return [H2::Stream]
62
+ #
63
+ def request host: nil,
42
64
  port: nil,
65
+ url: nil,
43
66
  method:,
44
67
  path: '/',
45
68
  headers: {},
46
69
  params: {},
47
70
  body: nil,
48
- url: nil,
49
71
  tls: {},
50
72
  &block
51
73
 
52
- raise ArgumentError if url.nil? && (addr.nil? || port.nil?)
74
+ raise ArgumentError if url.nil? && (host.nil? || port.nil?)
53
75
  if url
54
76
  url = URI.parse url unless URI === url
55
- addr = url.host
77
+ host = url.host
56
78
  port = url.port
57
79
  path = url.request_uri
58
80
  end
59
- c = Client.new addr: addr, port: port, tls: tls
81
+ c = Client.new host: host, port: port, tls: tls
60
82
  c.__send__ method, path: path, headers: headers, params: params, body: body, &block
61
83
  end
62
84
  end
data/lib/h2/client.rb CHANGED
@@ -21,24 +21,34 @@ module H2
21
21
  attr_accessor :last_stream
22
22
  attr_reader :client, :reader, :scheme, :socket, :streams
23
23
 
24
- def initialize addr: nil, port: nil, url: nil, tls: {}
25
- raise ArgumentError if url.nil? && (addr.nil? || port.nil?)
24
+ # create a new h2 client
25
+ #
26
+ # @param [String] host IP address or hostname
27
+ # @param [Integer] port TCP port
28
+ # @param [String,URI] url full URL to parse (optional: existing +URI+ instance)
29
+ # @param [Hash,FalseClass] tls TLS options (optional: +false+ do not use TLS)
30
+ # @option tls [String] :cafile path to CA file
31
+ #
32
+ # @return [H2::Client]
33
+ #
34
+ def initialize host: nil, port: nil, url: nil, tls: {}
35
+ raise ArgumentError if url.nil? && (host.nil? || port.nil?)
26
36
 
27
37
  if url
28
38
  url = URI.parse url unless URI === url
29
- @addr = url.host
39
+ @host = url.host
30
40
  @port = url.port
31
41
  @scheme = url.scheme
32
42
  tls = false if 'http' == @scheme
33
43
  else
34
- @addr = addr
44
+ @host = host
35
45
  @port = port
36
46
  @scheme = tls ? 'https' : 'http'
37
47
  end
38
48
 
39
49
  @tls = tls
40
50
  @streams = {}
41
- @socket = TCPSocket.new(@addr, @port)
51
+ @socket = TCPSocket.new(@host, @port)
42
52
  @socket = tls_socket @socket if @tls
43
53
  @client = HTTP2::Client.new
44
54
 
@@ -49,10 +59,14 @@ module H2
49
59
  read
50
60
  end
51
61
 
62
+ # @return true if the connection is closed
63
+ #
52
64
  def closed?
53
65
  @socket.closed?
54
66
  end
55
67
 
68
+ # close the connection
69
+ #
56
70
  def close
57
71
  unblock!
58
72
  @socket.close unless closed?
@@ -62,28 +76,55 @@ module H2
62
76
  @socket.eof?
63
77
  end
64
78
 
79
+ # send a goaway frame and wait until the connection is closed
80
+ #
65
81
  def goaway!
66
82
  goaway block: true
67
83
  end
68
84
 
85
+ # send a goaway frame and optionally wait for the connection to be closed
86
+ #
87
+ # @param [Boolean] block waits for close if +true+, returns immediately otherwise
88
+ #
89
+ # @return +false+ if already closed
90
+ # @return +nil+
91
+ #
69
92
  def goaway block: false
70
93
  return false if closed?
71
94
  @client.goaway
72
95
  block! if block
73
96
  end
74
97
 
98
+ # binds all connection events to their respective on_ handlers
99
+ #
75
100
  def bind_events
76
101
  CONNECTION_EVENTS.each do |e|
77
102
  @client.on(e){|*a| __send__ "on_#{e}", *a}
78
103
  end
79
104
  end
80
105
 
106
+ # convenience wrappers to make requests with HTTP methods
107
+ #
108
+ # @see Client#request
109
+ #
81
110
  REQUEST_METHODS.each do |m|
82
111
  define_method m do |**args, &block|
83
112
  request method: m, **args, &block
84
113
  end
85
114
  end
86
115
 
116
+ # initiate a +Stream+ by making a request with the given HTTP method
117
+ #
118
+ # @param [Symbol] method HTTP request method
119
+ # @param [String] path request path
120
+ # @param [Hash] headers request headers
121
+ # @param [Hash] params request query string parameters
122
+ # @param [String] body request body
123
+ #
124
+ # @yield [H2::Stream]
125
+ #
126
+ # @return [H2::Stream]
127
+ #
87
128
  def request method:, path:, headers: {}, params: {}, body: nil, &block
88
129
  s = @client.new_stream
89
130
  stream = add_stream method: method, path: path, stream: s, &block
@@ -95,6 +136,10 @@ module H2
95
136
  stream
96
137
  end
97
138
 
139
+ # mutates the given hash into +String+ keys and values
140
+ #
141
+ # @param [Hash] hash the headers +Hash+ to stringify
142
+ #
98
143
  def stringify_headers hash
99
144
  hash.keys.each do |key|
100
145
  hash[key] = hash[key].to_s unless String === hash[key]
@@ -103,9 +148,14 @@ module H2
103
148
  hash
104
149
  end
105
150
 
151
+ # builds headers +Hash+ with appropriate ordering
152
+ #
153
+ # @see https://http2.github.io/http2-spec/#rfc.section.8.1.2.1
154
+ # @see https://github.com/igrigorik/http-2/pull/136
155
+ #
106
156
  def build_headers method:, path:, headers:
107
157
  h = {
108
- AUTHORITY_KEY => [@addr, @port.to_s].join(':'),
158
+ AUTHORITY_KEY => [@host, @port.to_s].join(':'),
109
159
  METHOD_KEY => method.to_s.upcase,
110
160
  PATH_KEY => path,
111
161
  SCHEME_KEY => @scheme
@@ -113,6 +163,9 @@ module H2
113
163
  h.merge! stringify_headers(headers)
114
164
  end
115
165
 
166
+ # creates a new stream and adds it to the +@streams+ +Hash+ keyed at both
167
+ # the method +Symbol+ and request path as well as the ID of the stream.
168
+ #
116
169
  def add_stream method:, path:, stream:, &block
117
170
  @streams[method] ||= {}
118
171
  @streams[method][path] ||= []
@@ -122,6 +175,8 @@ module H2
122
175
  stream
123
176
  end
124
177
 
178
+ # add query string parameters the given request path +String+
179
+ #
125
180
  def add_params params, path
126
181
  appendage = path.index('?') ? '&' : '?'
127
182
  path << appendage
@@ -130,10 +185,20 @@ module H2
130
185
 
131
186
  # ---
132
187
 
188
+ # maintain a ivar for the +Array+ to send to +IO.select+
189
+ #
133
190
  def selector
134
191
  @selector ||= [@socket]
135
192
  end
136
193
 
194
+ # creates a new +Thread+ to read the given number of bytes each loop from
195
+ # the current +@socket+
196
+ #
197
+ # NOTE: this is the override point for celluloid actor pool or concurrent
198
+ # ruby threadpool support
199
+ #
200
+ # @param [Integer] maxlen maximum number of bytes to read
201
+ #
137
202
  def read maxlen = DEFAULT_MAXLEN
138
203
  main = Thread.current
139
204
  @reader = Thread.new do
@@ -145,6 +210,11 @@ module H2
145
210
  end
146
211
  end
147
212
 
213
+ # underyling read loop implementation, handling returned +Symbol+ values
214
+ # and shovelling data into the client parser
215
+ #
216
+ # @param [Integer] maxlen maximum number of bytes to read
217
+ #
148
218
  def _read maxlen = DEFAULT_MAXLEN
149
219
  begin
150
220
  data = nil
@@ -173,6 +243,10 @@ module H2
173
243
  end
174
244
  end
175
245
 
246
+ # fake exceptionless IO for reading on older ruby versions
247
+ #
248
+ # @param [Integer] maxlen maximum number of bytes to read
249
+ #
176
250
  def read_from_socket maxlen
177
251
  @socket.read_nonblock maxlen
178
252
  rescue IO::WaitReadable
@@ -181,11 +255,18 @@ module H2
181
255
 
182
256
  # ---
183
257
 
258
+ # close callback for parser: calls custom handler, then closes connection
259
+ #
184
260
  def on_close
185
261
  on :close
186
262
  close
187
263
  end
188
264
 
265
+ # frame callback for parser: writes bytes to the +@socket+, and slicing
266
+ # appropriately for given return values
267
+ #
268
+ # @param [String] bytes
269
+ #
189
270
  def on_frame bytes
190
271
  on :frame, bytes
191
272
 
@@ -207,17 +288,26 @@ module H2
207
288
  @socket.flush
208
289
  end
209
290
 
291
+ # fake exceptionless IO for writing on older ruby versions
292
+ #
293
+ # @param [String] bytes
294
+ #
210
295
  def write_to_socket bytes
211
296
  @socket.write_nonblock bytes
212
297
  rescue IO::WaitWritable
213
298
  :wait_writable
214
299
  end
215
300
 
301
+ # goaway callback for parser: calls custom handler, then closes connection
302
+ #
216
303
  def on_goaway *args
217
304
  on :goaway, *args
218
305
  close
219
306
  end
220
307
 
308
+ # push promise callback for parser: creates new +Stream+ with appropriate
309
+ # parent, binds close event, calls custom handler
310
+ #
221
311
  def on_promise promise
222
312
  push_promise = Stream.new client: self,
223
313
  parent: @streams[promise.parent.id],
@@ -235,10 +325,14 @@ module H2
235
325
 
236
326
  # ---
237
327
 
328
+ # build, configure, and return TLS socket
329
+ #
330
+ # @param [TCPSocket] socket unencrypted socket
331
+ #
238
332
  def tls_socket socket
239
333
  socket = OpenSSL::SSL::SSLSocket.new socket, create_ssl_context
240
334
  socket.sync_close = true
241
- socket.hostname = @addr unless RE_IP_ADDR.match(@addr)
335
+ socket.hostname = @host unless RE_IP_ADDR.match(@host)
242
336
  socket.connect
243
337
  socket
244
338
  end
@@ -261,6 +355,8 @@ module H2
261
355
  ctx
262
356
  end
263
357
 
358
+ # handle protocol negotiation for older ruby/openssl versions
359
+ #
264
360
  if H2.alpn?
265
361
  def set_ssl_context_protocols ctx
266
362
  ctx.alpn_protocols = ALPN_PROTOCOLS
@@ -273,6 +369,8 @@ module H2
273
369
 
274
370
  # ---
275
371
 
372
+ # use exceptionless IO if this ruby version supports it
373
+ #
276
374
  module ExceptionlessIO
277
375
 
278
376
  def read_from_socket maxlen
@@ -40,32 +40,13 @@ module H2
40
40
  bind_events
41
41
  end
42
42
 
43
- # mimicing Reel::Connection#respond
43
+ # write status, headers, and body to +@stream+
44
44
  #
45
- # write status, headers, and data to +@stream+
46
- #
47
- def respond response, body_or_headers = nil, body = nil
48
-
49
- # :/
50
- #
51
- if Hash === body_or_headers
52
- headers = body_or_headers
53
- body ||= ''
54
- else
55
- headers = {}
56
- body = body_or_headers ||= ''
57
- end
58
-
59
- @response = case response
60
- when Symbol, Integer
61
- response = Response.new stream: self,
62
- status: response,
63
- headers: headers,
64
- body: body
65
- when Response
66
- response
67
- else raise TypeError, "invalid response: #{response.inspect}"
68
- end
45
+ def respond status:, headers: {}, body: ''
46
+ response = Response.new stream: self,
47
+ status: status,
48
+ headers: headers,
49
+ body: body
69
50
 
70
51
  if @closed
71
52
  log :warn, 'stream closed before response sent'
@@ -85,20 +66,9 @@ module H2
85
66
  @connection.server.async.handle_push_promise pp
86
67
  end
87
68
 
88
- # create a push promise - mimicing Reel::Connection#respond
69
+ # create a push promise
89
70
  #
90
- def push_promise_for path, body_or_headers = {}, body = nil
91
-
92
- # :/
93
- #
94
- case body_or_headers
95
- when Hash
96
- headers = body_or_headers
97
- else
98
- headers = {}
99
- body = body_or_headers
100
- end
101
-
71
+ def push_promise_for path:, headers: {}, body: nil
102
72
  headers.merge! AUTHORITY_KEY => @request.authority,
103
73
  SCHEME_KEY => @request.scheme
104
74
 
@@ -55,8 +55,8 @@ module H2
55
55
 
56
56
  # respond to this request on its stream
57
57
  #
58
- def respond response, body_or_headers = nil, body = nil
59
- @stream.respond response, body_or_headers, body
58
+ def respond status:, headers: {}, body: ''
59
+ @stream.respond status: status, headers: headers, body: body
60
60
  end
61
61
 
62
62
  end
data/lib/h2/stream.rb CHANGED
@@ -13,6 +13,15 @@ module H2
13
13
 
14
14
  attr_reader :body, :client, :headers, :parent, :pushes, :stream
15
15
 
16
+ # create a new h2 stream
17
+ #
18
+ # @param [H2::Client] client the +Client+ bind this +Stream+ to
19
+ # @param [HTTP2::Stream] stream protocol library +HTTP2::Stream+ instance
20
+ # @param [Boolean] push true if a push promise stream, false otherwise
21
+ # @param [H2::Stream] parent the parent stream of this, if push promise stream
22
+ #
23
+ # @return [H2::Stream]
24
+ #
16
25
  def initialize client:, stream:, push: false, parent: nil
17
26
  @body = ''
18
27
  @client = client
@@ -28,46 +37,66 @@ module H2
28
37
  bind_events
29
38
  end
30
39
 
40
+ # @return [Integer] stream ID
41
+ #
31
42
  def id
32
43
  @stream.id
33
44
  end
34
45
 
46
+ # @return [Boolean] true if response status is 200
47
+ #
35
48
  def ok?
36
49
  headers[STATUS_KEY] == '200'
37
50
  end
38
51
 
52
+ # @return [Boolean] true if this +Stream+ is closed
53
+ #
39
54
  def closed?
40
55
  @closed
41
56
  end
42
57
 
58
+ # @return [Boolean] true if this +Stream+ is a push promise
59
+ #
43
60
  def push?
44
61
  @push
45
62
  end
46
63
 
64
+ # add a push promise +Stream+ to this +Stream+'s list of "child" pushes
65
+ #
47
66
  def add_push stream
48
67
  @pushes << stream
49
68
  end
50
69
 
70
+ # call cancel and unblock this +Stream+
71
+ #
51
72
  def cancel!
52
73
  @stream.cancel
53
74
  unblock!
54
75
  end
55
76
 
77
+ # block this stream until unblocked or timeout
78
+ #
56
79
  def block! timeout = nil
57
80
  @pushes.each {|p| p.block! timeout}
58
81
  super
59
82
  end
60
83
 
84
+ # @return [Hash] response headers (blocks)
85
+ #
61
86
  def headers
62
87
  block!
63
88
  @headers
64
89
  end
65
90
 
91
+ # @return [String] response headers (blocks)
92
+ #
66
93
  def body
67
94
  block!
68
95
  @body
69
96
  end
70
97
 
98
+ # binds all stream events to their respective on_ handlers
99
+ #
71
100
  def bind_events
72
101
  @stream.on(:close) do
73
102
  @parent.add_push self if @parent && push?
@@ -87,6 +116,8 @@ module H2
87
116
  end
88
117
  end
89
118
 
119
+ # builds +Hash+ from associative array, merges into response headers
120
+ #
90
121
  def add_headers h
91
122
  h = Hash[h]
92
123
  on :headers, h
@@ -94,6 +125,8 @@ module H2
94
125
  @headers
95
126
  end
96
127
 
128
+ # @return [Hash] a simple +Hash+ with +:headers+ and +:body+ keys/values
129
+ #
97
130
  def to_h
98
131
  { headers: headers, body: body }
99
132
  end
data/lib/h2/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module H2
2
- VERSION = '0.5.0'
2
+ VERSION = '0.6.0'
3
3
 
4
4
  class << self
5
5
 
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.5.0
4
+ version: 0.6.0
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-21 00:00:00.000000000 Z
11
+ date: 2018-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http-2
@@ -16,20 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.9'
19
+ version: '0.10'
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 0.9.1
22
+ version: 0.10.0
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: '0.9'
29
+ version: '0.10'
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 0.9.1
32
+ version: 0.10.0
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: colored
35
35
  requirement: !ruby/object:Gem::Requirement