h2 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b533a3c1702ec83aad19b84c16dcb97badbc669b
4
- data.tar.gz: e8adb1f561a47a3970d1bed94b276b26220798e5
3
+ metadata.gz: 7026103d2e280847900dbd974196250ef62d1ba0
4
+ data.tar.gz: df6cd50fb58732f2256aa90c85d36a6d8d9cb6c3
5
5
  SHA512:
6
- metadata.gz: c948d743e1a8923c0cfc7e87564aedb6e16fbf27173859aa1fd6316e900adf05e661f223e243b2604c611685fc5280e9984c4d25a5f6053c17862af9d31db9e5
7
- data.tar.gz: bbd51fcf78448aeb6636dc55d0cc22f188c5a44517a4887e01db8d0936efa10133d65c6637237463413224f1d79fbc2c9b2c71b01f22d5ee188ef4c98055f1ae
6
+ metadata.gz: af9a7b61585c3b9a0dc9f4fca518dd7516a57db3ac7299969c95b9790c7e3de965a83b63391fcba731079ef88db30dacabb872e1c05573b2077dc0db3a660c0a
7
+ data.tar.gz: 54ad799634b7cc747cdfa0cf2cf9b42324f67464bcfd941bb86bd7b118d4d44975aab518ab4d558be0d0f54d79a76a4e63e55a9e0b86b7b2e520d3e84310d866
data/CHANGELOG.md ADDED
@@ -0,0 +1,15 @@
1
+ h2 changelog
2
+ ============
3
+
4
+ ### 0.2.0 7 mar 2017
5
+
6
+ * add concurrency alternates
7
+
8
+ ### 0.1.1 -
9
+
10
+ * removed extra rescue/ensure in H2::Client#read
11
+
12
+ ### 0.1.0 - 30 dec 2016
13
+
14
+ * initial release
15
+ * seems to work! :)
data/Gemfile CHANGED
@@ -1,9 +1,17 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'http-2', git: 'https://github.com/igrigorik/http-2'
3
+ gem 'http-2', git: 'https://github.com/kenichi/http-2', branch: 'stream_close_state'
4
4
 
5
5
  gemspec
6
6
 
7
+ group :concurrent_ruby do
8
+ gem 'concurrent-ruby'
9
+ end
10
+
11
+ group :celluloid do
12
+ gem 'celluloid'
13
+ end
14
+
7
15
  group :development, :test do
8
16
  gem 'awesome_print'
9
17
  gem 'pry-byebug'
data/README.md CHANGED
@@ -1,12 +1,11 @@
1
1
  # H2
2
2
 
3
- [![Build Status](https://travis-ci.org/kenichi/h2.png?branch=master)](https://travis-ci.org/kenichi/h2)
3
+ [![Build Status](https://travis-ci.org/kenichi/h2.svg?branch=master)](https://travis-ci.org/kenichi/h2)
4
4
 
5
- H2 is a basic HTTP/2 client based on the [http-2](https://github.com/igrigorik/http-2) gem.
5
+ H2 is a basic, _experimental_ HTTP/2 client based on the [http-2](https://github.com/igrigorik/http-2) gem.
6
6
 
7
- H2 currently uses:
7
+ H2 uses:
8
8
 
9
- * one new thread per client (see [TODO](#TODO) item 3)
10
9
  * keyword arguments (>=2.0)
11
10
  * exception-less socket IO (>=2.3).
12
11
 
@@ -70,17 +69,65 @@ end
70
69
  client.goaway!
71
70
  ```
72
71
 
72
+ ## CLI
73
+
74
+ For more info on using the CLI `h2` installed with this gem:
75
+
76
+ `$ h2 --help`
77
+
78
+ ## Alternate Concurrency Models
79
+
80
+ Right now, h2 uses one new thread per connection. This is hardly ideal, so a
81
+ couple other models are tentatively supported out of the box:
82
+
83
+ * [celluloid](https://github.com/celluloid/celluloid)
84
+ * [concurrent-ruby](https://github.com/ruby-concurrency/concurrent-ruby)
85
+
86
+ Neither of these gems are hard dependencies. If you want to use either one, you must
87
+ have it available to your Ruby VM, most likely via Bundler, *and* require the
88
+ sub-component of h2 that will prepend and extend `H2::Client`. They are also intended
89
+ to be mutually exclusive: you can have both in your VM, but you can only use one at a
90
+ time with h2.
91
+
92
+ #### Celluloid Pool
93
+
94
+ To use a celluloid actor pool for reading from `H2::Client` connections:
95
+
96
+ ```ruby
97
+ require 'h2/client/celluloid'
98
+ ```
99
+
100
+ This will lazily fire up a celluloid pool, with defaults defined by Celluloid.
101
+
102
+ #### Concurrent-Ruby ThreadPoolExecutor
103
+
104
+ To use a concurrent-ruby thread pool executor for reading from `H2::Client` connections:
105
+
106
+ ```ruby
107
+ require 'h2/client/concurrent'
108
+ ```
109
+
110
+ This will lazily fire up a `Concurrent::ThreadPoolExecutor` with the following settings:
111
+
112
+ ```ruby
113
+ procs = ::Concurrent.processor_count
114
+
115
+ min_threads: 0,
116
+ max_threads: procs,
117
+ max_queue: procs * 5
118
+ ```
119
+
73
120
  ## TODO
74
121
 
75
122
  * [x] HTTPS / TLS
76
- * [ ] push promise cancellation
77
- * [ ] alternate concurrency models
123
+ * [x] push promise cancellation
124
+ * [x] alternate concurrency models
125
+ * [ ] fix up CLI to be more curlish
78
126
 
79
127
  ## Contributing
80
128
 
81
129
  Bug reports and pull requests are welcome on GitHub at https://github.com/kenichi/h2. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
82
130
 
83
-
84
131
  ## License
85
132
 
86
133
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/bin/console CHANGED
@@ -4,5 +4,22 @@ require 'bundler/setup'
4
4
  require 'h2'
5
5
  require 'irb'
6
6
 
7
- Bundler.require :development
7
+ #Bundler.require :development
8
+
9
+ def trunc_payload f
10
+ x = f.dup
11
+ size = x[:payload]&.to_s&.bytesize || 0
12
+ x[:payload] = "#{size} redacted" if size > 64
13
+ x
14
+ end
15
+
16
+ def new_client
17
+ # H2::Client.new url: 'https://127.0.0.1:4430', tls: { ca_file: '/Users/ken/src/ruby/other_reel/tmp/certs/ca.crt' } do |client|
18
+ # H2::Client.new url: 'http://127.0.0.1:1234' do |client|
19
+ H2::Client.new url: 'https://vux.nakamura.io:4430', tls: { ca_file: '/usr/local/etc/cacert-201611290415.pem' } do |client|
20
+ client.client.on(:frame_sent){|f| STDERR.puts ">> #{trunc_payload(f).inspect}"}
21
+ client.client.on(:frame_received){|f| STDERR.puts "<< #{trunc_payload(f).inspect}"}
22
+ end
23
+ end
24
+
8
25
  IRB.start
data/exe/h2 CHANGED
@@ -22,6 +22,7 @@ end # }}}
22
22
  options = {
23
23
  body: nil,
24
24
  block: false,
25
+ debug: false,
25
26
  headers: {},
26
27
  goaway: false,
27
28
  method: nil,
@@ -52,7 +53,7 @@ OptionParser.new do |o|
52
53
  end
53
54
 
54
55
  o.on '-g', '--goaway', 'send GOAWAY frame when stream is complete' do
55
- options[:debug] = true
56
+ options[:goaway] = true
56
57
  end
57
58
 
58
59
  o.on '-v', '--verbose', 'turn on verbosity' do
@@ -65,6 +66,7 @@ OptionParser.new do |o|
65
66
  options[:method] = meth
66
67
  end
67
68
 
69
+
68
70
  end.parse!
69
71
 
70
72
  options[:method] ||= :get
@@ -0,0 +1,33 @@
1
+ require 'celluloid/current'
2
+ require 'h2'
3
+
4
+ module H2
5
+ class Client
6
+ module Celluloid
7
+
8
+ class Reader
9
+ include ::Celluloid
10
+
11
+ def read client, maxlen = DEFAULT_MAXLEN
12
+ client._read maxlen
13
+ end
14
+ end
15
+
16
+ module ClassMethods
17
+ def thread_pool
18
+ @thread_pool ||= Reader.pool
19
+ end
20
+ end
21
+
22
+ def read maxlen = DEFAULT_MAXLEN
23
+ self.class.thread_pool.async.read self
24
+ end
25
+
26
+ end
27
+
28
+ extend H2::Client::Celluloid::ClassMethods
29
+ prepend H2::Client::Celluloid
30
+ end
31
+ end
32
+
33
+
@@ -0,0 +1,34 @@
1
+ require 'concurrent'
2
+ require 'h2'
3
+
4
+ module H2
5
+ class Client
6
+ module Concurrent
7
+
8
+ module ClassMethods
9
+ def thread_pool
10
+ procs = ::Concurrent.processor_count
11
+ @thread_pool ||= ::Concurrent::ThreadPoolExecutor.new min_threads: 0,
12
+ max_threads: procs,
13
+ max_queue: procs * 5
14
+ end
15
+ end
16
+
17
+ def read maxlen = DEFAULT_MAXLEN
18
+ main = Thread.current
19
+ @reader = self.class.thread_pool.post do
20
+ begin
21
+ _read maxlen
22
+ rescue => e
23
+ main.raise e
24
+ end
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ extend H2::Client::Concurrent::ClassMethods
31
+ prepend H2::Client::Concurrent
32
+ end
33
+ end
34
+
data/lib/h2/client.rb CHANGED
@@ -13,11 +13,6 @@ module H2
13
13
  :promise
14
14
  ]
15
15
 
16
- PROMISE_EVENTS = [
17
- :headers,
18
- :data
19
- ]
20
-
21
16
  ALPN_PROTOCOLS = ['h2']
22
17
  DEFAULT_MAXLEN = 4096
23
18
 
@@ -112,17 +107,16 @@ module H2
112
107
  METHOD_KEY => method.to_s.upcase,
113
108
  PATH_KEY => path,
114
109
  SCHEME_KEY => @scheme
115
- }
110
+ }.merge USER_AGENT
116
111
  h.merge! stringify_headers(headers)
117
112
  end
118
113
 
119
114
  def add_stream method:, path:, stream:, &block
120
- stream_id = stream.id
121
115
  @streams[method] ||= {}
122
116
  @streams[method][path] ||= []
123
117
  stream = Stream.new client: self, stream: stream, &block unless Stream === stream
124
118
  @streams[method][path] << stream
125
- @streams[stream_id] = stream
119
+ @streams[stream.id] = stream
126
120
  stream
127
121
  end
128
122
 
@@ -143,12 +137,6 @@ module H2
143
137
  main.raise e
144
138
  end
145
139
  end
146
- rescue => e
147
- STDERR.puts "#{e.message} - closing socket"
148
- STDERR.puts e.backtrace.map {|l| "\t" + l}
149
- close
150
- ensure
151
- unblock!
152
140
  end
153
141
 
154
142
  def _read maxlen = DEFAULT_MAXLEN
@@ -214,18 +202,18 @@ module H2
214
202
  end
215
203
 
216
204
  def on_promise promise
217
- on :promise, promise
218
-
219
- Stream.new client: self,
220
- parent: @streams[promise.parent.id],
221
- push: true,
222
- stream: promise do |p|
205
+ push_promise = Stream.new client: self,
206
+ parent: @streams[promise.parent.id],
207
+ push: true,
208
+ stream: promise do |p|
223
209
  p.on :close do
224
210
  method = p.headers[METHOD_KEY].downcase.to_sym rescue :error
225
211
  path = p.headers[PATH_KEY]
226
212
  add_stream method: method, path: path, stream: p
227
213
  end
228
214
  end
215
+
216
+ on :promise, push_promise
229
217
  end
230
218
 
231
219
  # ---
data/lib/h2/stream.rb CHANGED
@@ -49,8 +49,8 @@ module H2
49
49
  end
50
50
 
51
51
  def cancel!
52
- unblock!
53
52
  @stream.cancel
53
+ unblock!
54
54
  end
55
55
 
56
56
  def block! timeout = nil
data/lib/h2/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module H2
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/h2.rb CHANGED
@@ -3,6 +3,8 @@
3
3
  require 'http/2'
4
4
  require 'uri'
5
5
 
6
+ require 'h2/version'
7
+
6
8
  module H2
7
9
 
8
10
  # http/2 psuedo-headers
@@ -13,6 +15,10 @@ module H2
13
15
  SCHEME_KEY = ':scheme'
14
16
  STATUS_KEY = ':status'
15
17
 
18
+ USER_AGENT = {
19
+ 'user-agent' => "h2/#{H2::VERSION} #{RUBY_ENGINE}-#{RUBY_VERSION}/#{RUBY_PLATFORM}"
20
+ }
21
+
16
22
  REQUEST_METHODS = [
17
23
  :get,
18
24
  :delete,
@@ -92,4 +98,3 @@ end
92
98
 
93
99
  require 'h2/client'
94
100
  require 'h2/stream'
95
- require 'h2/version'
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.1.0
4
+ version: 0.2.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: 2016-12-31 00:00:00.000000000 Z
11
+ date: 2017-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http-2
@@ -96,6 +96,7 @@ extra_rdoc_files: []
96
96
  files:
97
97
  - ".gitignore"
98
98
  - ".travis.yml"
99
+ - CHANGELOG.md
99
100
  - CODE_OF_CONDUCT.md
100
101
  - Gemfile
101
102
  - LICENSE.txt
@@ -106,6 +107,8 @@ files:
106
107
  - h2.gemspec
107
108
  - lib/h2.rb
108
109
  - lib/h2/client.rb
110
+ - lib/h2/client/celluloid.rb
111
+ - lib/h2/client/concurrent.rb
109
112
  - lib/h2/client/tcp_socket.rb
110
113
  - lib/h2/stream.rb
111
114
  - lib/h2/version.rb
@@ -129,7 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
129
132
  version: '0'
130
133
  requirements: []
131
134
  rubyforge_project:
132
- rubygems_version: 2.6.8
135
+ rubygems_version: 2.6.10
133
136
  signing_key:
134
137
  specification_version: 4
135
138
  summary: an http/2 client based on http-2 and modern ruby