net-http2 0.14.1 → 0.15.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
  SHA1:
3
- metadata.gz: 7ca19f3b01ed565929287e4db629d7c5a3c1522e
4
- data.tar.gz: d31dc0fc2f7cf652dcc8bdac6fcc8b31b6721797
3
+ metadata.gz: 1d1bbb7eb0d7324fb63a671d0f8fbc2075b6a625
4
+ data.tar.gz: 9d4dd0e9e5131ac605292030235b9a68a8087b83
5
5
  SHA512:
6
- metadata.gz: b0b94a8d7e38e0fed916585ff63b8f1686e0cf0ae0107dced66a7de8199155ac62484366fd1808ba2bfeb5e6fc02fb2bcd4cabab061ecfa2833a6bf1621ef22b
7
- data.tar.gz: f88d758b5174c933832c003ce996f0a97277bf0b24da7ba517825bcb2eb4a898b8773f56b008fe256eb247ca0a659117a8cc04be0f22f463145e60fb414ab117
6
+ metadata.gz: 1db0898b540554278ee5a3789bafae4aac29e9a8075fdfbd26c0aca57f360136b9c3c4c60f57b0ff412030ad87c2878b5890f4e9df255535a73ddf7535609ef4
7
+ data.tar.gz: 064cdc09d94dbd1e13623ae2a42b5cb5f695344f83ed60faadfab7aa1e9f7c721099e8fc8187133f9cbb36523f89142a1672c6071b8bf937b9ca342c954d4ada
data/README.md CHANGED
@@ -95,6 +95,16 @@ client.close
95
95
  NetHttp2::Client.new("https://nghttp2.org", ssl_context: ctx)
96
96
  ```
97
97
 
98
+ * **on(event, &block)**
99
+
100
+ Allows to set a callback for the client. The only available event is `:error`, which allows to set a callback when an error is raised at socket level, hence in the underlying socket thread.
101
+
102
+ ```ruby
103
+ client.on(:error) { |exception| puts "Exception has been raised: #{exception}" }
104
+ ```
105
+
106
+ > It is RECOMMENDED to set the `:error` callback: if none is defined, the underlying socket thread may raise an error in the main thread at unexpected execution times.
107
+
98
108
  * **uri** → **`URI`**
99
109
 
100
110
  Returns the URI of the endpoint.
@@ -202,7 +212,10 @@ The real benefit of HTTP/2 is being able to receive body and header streams. Ins
202
212
 
203
213
 
204
214
  ## Thread-Safety
205
- NetHttp2 is thread-safe.
215
+ NetHttp2 is thread-safe. However, some caution is imperative:
216
+
217
+ * The async callbacks will be executed in a different thread, so ensure that your code in the callbacks is thread-safe.
218
+ * Errors in the underlying socket loop thread will be raised in the main thread at unexpected execution times, unless you specify the `:error` callback on the Client (recommended).
206
219
 
207
220
  ## Contributing
208
221
  So you want to contribute? That's great! Please follow the guidelines below. It will make it easier to get merged in.
@@ -0,0 +1,49 @@
1
+ require 'http/2/connection'
2
+
3
+ # We are currently locked to using the Http2 library v0.8.2 since v0.8.3 still has some compatibility issues:
4
+ # <https://github.com/igrigorik/http-2/issues/92>
5
+ #
6
+ # However, v0.8.2 had a memory leak that was reported in the following issues:
7
+ # <https://github.com/igrigorik/http-2/issues/73>
8
+ # <https://github.com/ostinelli/net-http2/issues/7>
9
+ #
10
+ # Hence, this is a temporary monkey-patch to the HTTP2 library in order to solve the mentioned leak
11
+ # while waiting to fix the issues on v0.8.3.
12
+
13
+ module HTTP2
14
+
15
+ class Connection
16
+
17
+ private
18
+
19
+ def activate_stream(id: nil, **args)
20
+ connection_error(msg: 'Stream ID already exists') if @streams.key?(id)
21
+
22
+ stream = Stream.new({ connection: self, id: id }.merge(args))
23
+
24
+ # Streams that are in the "open" state, or either of the "half closed"
25
+ # states count toward the maximum number of streams that an endpoint is
26
+ # permitted to open.
27
+ stream.once(:active) { @active_stream_count += 1 }
28
+
29
+ @streams_recently_closed ||= {}
30
+ stream.once(:close) do
31
+ @active_stream_count -= 1
32
+
33
+ @streams_recently_closed.delete_if do |closed_stream_id, v|
34
+ to_be_deleted = (Time.now - v) > 15
35
+ @streams.delete(closed_stream_id) if to_be_deleted
36
+ to_be_deleted
37
+ end
38
+
39
+ @streams_recently_closed[id] = Time.now
40
+ end
41
+
42
+ stream.on(:promise, &method(:promise)) if self.is_a? Server
43
+ stream.on(:frame, &method(:send))
44
+ stream.on(:window_update, &method(:window_update))
45
+
46
+ @streams[id] = stream
47
+ end
48
+ end
49
+ end
data/lib/net-http2.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'net-http2/callbacks'
1
2
  require 'net-http2/client'
2
3
  require 'net-http2/response'
3
4
  require 'net-http2/request'
@@ -5,6 +6,8 @@ require 'net-http2/socket'
5
6
  require 'net-http2/stream'
6
7
  require 'net-http2/version'
7
8
 
9
+ require 'http2_patch'
10
+
8
11
  module NetHttp2
9
12
  raise "Cannot require NetHttp2, unsupported engine '#{RUBY_ENGINE}'" unless RUBY_ENGINE == "ruby"
10
13
  end
@@ -0,0 +1,22 @@
1
+ module NetHttp2
2
+
3
+ module Callbacks
4
+
5
+ def on(event, &block)
6
+ raise ArgumentError, 'on event must provide a block' unless block_given?
7
+
8
+ @callback_events ||= {}
9
+ @callback_events[event] ||= []
10
+ @callback_events[event] << block
11
+ end
12
+
13
+ def emit(event, arg)
14
+ return unless @callback_events && @callback_events[event]
15
+ @callback_events[event].each { |b| b.call(arg) }
16
+ end
17
+
18
+ def callback_events
19
+ @callback_events || {}
20
+ end
21
+ end
22
+ end
@@ -9,6 +9,9 @@ module NetHttp2
9
9
  PROXY_SETTINGS_KEYS = [:proxy_addr, :proxy_port, :proxy_user, :proxy_pass]
10
10
 
11
11
  class Client
12
+
13
+ include Callbacks
14
+
12
15
  attr_reader :uri
13
16
 
14
17
  def initialize(url, options={})
@@ -101,17 +104,25 @@ module NetHttp2
101
104
  rescue EOFError
102
105
  # socket closed
103
106
  init_vars
104
- raise SocketError.new 'Socket was remotely closed'
107
+ callback_or_raise SocketError.new('Socket was remotely closed')
105
108
 
106
109
  rescue Exception => e
107
110
  # error on socket
108
111
  init_vars
109
- raise e
112
+ callback_or_raise e
110
113
  end
111
114
  end.tap { |t| t.abort_on_exception = true }
112
115
  end
113
116
  end
114
117
 
118
+ def callback_or_raise(exception)
119
+ if callback_events.keys.include?(:error)
120
+ emit(:error, exception)
121
+ else
122
+ raise exception
123
+ end
124
+ end
125
+
115
126
  def socket_loop
116
127
 
117
128
  ensure_sent_before_receiving
@@ -4,6 +4,8 @@ module NetHttp2
4
4
 
5
5
  class Request
6
6
 
7
+ include Callbacks
8
+
7
9
  DEFAULT_TIMEOUT = 60
8
10
 
9
11
  attr_reader :method, :uri, :path, :params, :body, :timeout
@@ -30,11 +32,13 @@ module NetHttp2
30
32
  @headers.merge!(':authority' => "#{@uri.host}:#{@uri.port}") unless @headers[':authority']
31
33
 
32
34
  if @body
33
- @headers.merge!('content-length' => @body.bytesize.to_s)
35
+ @headers.merge!('content-length' => @body.bytesize)
34
36
  else
35
37
  @headers.delete('content-length')
36
38
  end
37
39
 
40
+ @headers.update(@headers) { |_k, v| v.to_s }
41
+
38
42
  @headers
39
43
  end
40
44
 
@@ -44,18 +48,6 @@ module NetHttp2
44
48
  path
45
49
  end
46
50
 
47
- def on(event, &block)
48
- raise ArgumentError, 'on event must provide a block' unless block_given?
49
-
50
- @events[event] ||= []
51
- @events[event] << block
52
- end
53
-
54
- def emit(event, arg)
55
- return unless @events[event]
56
- @events[event].each { |b| b.call(arg) }
57
- end
58
-
59
51
  private
60
52
 
61
53
  # The to_param and to_query code here below is a free adaptation from the original code in:
@@ -1,3 +1,3 @@
1
1
  module NetHttp2
2
- VERSION = "0.14.1"
2
+ VERSION = '0.15.0'.freeze
3
3
  end
data/net-http2.gemspec CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.add_dependency "http-2", "~> 0.8.2"
22
+ spec.add_dependency "http-2", "0.8.2"
23
23
 
24
24
  spec.add_development_dependency "bundler", "~> 1.3"
25
25
  spec.add_development_dependency "rake", "~> 10.0"
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net-http2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.1
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roberto Ostinelli
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-12-30 00:00:00.000000000 Z
11
+ date: 2017-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http-2
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - '='
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.8.2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - '='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.8.2
27
27
  - !ruby/object:Gem::Dependency
@@ -84,7 +84,9 @@ files:
84
84
  - Rakefile
85
85
  - bin/console
86
86
  - bin/setup
87
+ - lib/http2_patch.rb
87
88
  - lib/net-http2.rb
89
+ - lib/net-http2/callbacks.rb
88
90
  - lib/net-http2/client.rb
89
91
  - lib/net-http2/request.rb
90
92
  - lib/net-http2/response.rb