async-http 0.52.2 → 0.53.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/async/http/body/delayed.rb +2 -2
  3. data/lib/async/http/body/hijack.rb +5 -0
  4. data/lib/async/http/body/pipe.rb +15 -7
  5. data/lib/async/http/body/slowloris.rb +2 -2
  6. data/lib/async/http/body/stream.rb +1 -1
  7. data/lib/async/http/client.rb +2 -2
  8. data/lib/async/http/endpoint.rb +2 -2
  9. data/lib/async/http/internet.rb +4 -0
  10. data/lib/async/http/protocol/http1/connection.rb +0 -5
  11. data/lib/async/http/protocol/http1/server.rb +4 -3
  12. data/lib/async/http/protocol/http2/output.rb +1 -1
  13. data/lib/async/http/protocol/http2/response.rb +5 -0
  14. data/lib/async/http/proxy.rb +24 -8
  15. data/lib/async/http/version.rb +1 -1
  16. metadata +22 -65
  17. data/.editorconfig +0 -6
  18. data/.github/workflows/development.yml +0 -52
  19. data/.gitignore +0 -15
  20. data/.rspec +0 -3
  21. data/.travis.yml +0 -35
  22. data/README.md +0 -365
  23. data/async-http.gemspec +0 -39
  24. data/bake.rb +0 -0
  25. data/examples/compare/Gemfile +0 -9
  26. data/examples/compare/benchmark.rb +0 -78
  27. data/examples/download/chunked.rb +0 -86
  28. data/examples/fetch/Gemfile +0 -3
  29. data/examples/fetch/Gemfile.lock +0 -74
  30. data/examples/fetch/README.md +0 -3
  31. data/examples/fetch/config.ru +0 -28
  32. data/examples/fetch/public/index.html +0 -23
  33. data/examples/fetch/public/stream.js +0 -56
  34. data/examples/google/search.rb +0 -47
  35. data/examples/request.rb +0 -38
  36. data/examples/stream/stop.rb +0 -28
  37. data/examples/trenni/Gemfile +0 -5
  38. data/examples/trenni/streaming.rb +0 -35
  39. data/examples/upload/client.rb +0 -39
  40. data/examples/upload/data.txt +0 -41
  41. data/examples/upload/server.rb +0 -19
  42. data/examples/upload/upload.rb +0 -26
  43. data/gems.locked +0 -103
  44. data/gems.rb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ed1627df4ea6935559ad738ac3c8d71fefdf17374a0cf9fcfe61f7b0de272fd
4
- data.tar.gz: f98c998cd157d5899e1c9625e878d7eec7c9aa1eecde0d4f2e3364d8b4c3825d
3
+ metadata.gz: 0dd87a790df077e00e75dacd429d72c9c7d0efbe6aef48285acdd253ade705fb
4
+ data.tar.gz: 0c3404f38a7687d1fc45d35fd10d1e88c2a0bf00aebf33a662725022548d16d2
5
5
  SHA512:
6
- metadata.gz: 80a5c210bb4cdafe27b1f0e8c44379ee15980a18aff2e26e070db3c5f0cccfca8045c0d9275174e9dc84f54b776e20a400bc77d9b728f969f52681c3747338ba
7
- data.tar.gz: a429070d12bfcdcccf92dbd44c8c1753f0ec90098e27c8c176e8c6a2cde75e789eb9398054b4a93201778efb8f827bf10c65be57bc35f76de68ebb7181ba68d3
6
+ metadata.gz: f2f6db17a7fe511f9b1a033a069f0805748f27db56f3ee7e719d5b26fcd36470a0998cc7dc39431a6e8d91861077787f0c42456479f1dd231bec637c74b55218
7
+ data.tar.gz: b57dfed936c2e97b1db58ada46fdd5fb155dcc5448546020dbf3bdda0ee2e7e8114533dd856162800435db165f8f505965764cd9916fbf33f02d86065a034d53
@@ -20,12 +20,12 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require_relative 'wrapper'
23
+ require 'protocol/http/body/wrapper'
24
24
 
25
25
  module Async
26
26
  module HTTP
27
27
  module Body
28
- class Delayed < Async::HTTP::Body::Wrapper
28
+ class Delayed < Protocol::HTTP::Body::Wrapper
29
29
  def initialize(body, delay = 0.01)
30
30
  super(body)
31
31
 
@@ -44,6 +44,11 @@ module Async
44
44
  @stream = nil
45
45
  end
46
46
 
47
+ # We prefer streaming directly as it's the lowest overhead.
48
+ def stream?
49
+ true
50
+ end
51
+
47
52
  def call(stream)
48
53
  return @block.call(stream)
49
54
  end
@@ -20,6 +20,9 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
+ require 'async/io/socket'
24
+ require 'async/io/stream'
25
+
23
26
  require_relative 'writable'
24
27
 
25
28
  module Async
@@ -39,8 +42,8 @@ module Async
39
42
  @reader = nil
40
43
  @writer = nil
41
44
 
42
- task.async(&self.method(:reader))
43
- task.async(&self.method(:writer))
45
+ task.async(transient: true, &self.method(:reader))
46
+ task.async(transient: true, &self.method(:writer))
44
47
  end
45
48
 
46
49
  def to_io
@@ -69,10 +72,9 @@ module Async
69
72
 
70
73
  @head.close_write
71
74
  ensure
72
- @reader = nil
73
75
  @input.close($!)
74
76
 
75
- @head.close if @writer.nil?
77
+ close_head if @writer&.finished?
76
78
  end
77
79
 
78
80
  # Read from the head of the pipe and write to the @output stream.
@@ -86,11 +88,17 @@ module Async
86
88
  @output.write(chunk)
87
89
  end
88
90
  ensure
89
- @writer = nil
90
-
91
91
  @output.close($!)
92
92
 
93
- @head.close if @reader.nil?
93
+ close_head if @reader&.finished?
94
+ end
95
+
96
+ def close_head
97
+ @head.close
98
+
99
+ # Both tasks are done, don't keep references:
100
+ @reader = nil
101
+ @writer = nil
94
102
  end
95
103
  end
96
104
  end
@@ -37,8 +37,8 @@ module Async
37
37
 
38
38
  # In order for this implementation to work correctly, you need to use a LimitedQueue.
39
39
  # @param minimum_throughput [Integer] the minimum bytes per second otherwise this body will be forcefully closed.
40
- def initialize(*args, minimum_throughput: 1024, **options)
41
- super(*args, **options)
40
+ def initialize(*arguments, minimum_throughput: 1024, **options)
41
+ super(*arguments, **options)
42
42
 
43
43
  @minimum_throughput = minimum_throughput
44
44
 
@@ -139,7 +139,7 @@ module Async
139
139
  end
140
140
 
141
141
  # Close the input and output bodies.
142
- def close
142
+ def close(error = nil)
143
143
  self.close_read
144
144
  self.close_write
145
145
  ensure
@@ -25,7 +25,7 @@ require 'async/io/stream'
25
25
 
26
26
  require 'async/pool/controller'
27
27
 
28
- require 'protocol/http/body/streamable'
28
+ require 'protocol/http/body/completable'
29
29
  require 'protocol/http/methods'
30
30
 
31
31
  require_relative 'protocol'
@@ -143,7 +143,7 @@ module Async
143
143
  response = request.call(connection)
144
144
 
145
145
  # The connection won't be released until the body is completely read/released.
146
- ::Protocol::HTTP::Body::Streamable.wrap(response) do
146
+ ::Protocol::HTTP::Body::Completable.wrap(response) do
147
147
  @pool.release(connection)
148
148
  end
149
149
 
@@ -193,8 +193,8 @@ module Async
193
193
  @endpoint ||= build_endpoint
194
194
  end
195
195
 
196
- def bind(*args, &block)
197
- endpoint.bind(*args, &block)
196
+ def bind(*arguments, &block)
197
+ endpoint.bind(*arguments, &block)
198
198
  end
199
199
 
200
200
  def connect(&block)
@@ -33,6 +33,10 @@ module Async
33
33
  @options = options
34
34
  end
35
35
 
36
+ # A cache of clients.
37
+ # @attribute [Hash(URI, Client)]
38
+ attr :clients
39
+
36
40
  def call(method, url, headers = nil, body = nil)
37
41
  endpoint = Endpoint.parse(url)
38
42
  key = host_key(endpoint)
@@ -74,11 +74,6 @@ module Async
74
74
  def reusable?
75
75
  @persistent && @stream && !@stream.closed?
76
76
  end
77
-
78
- def close
79
- Async.logger.debug(self) {"Closing connection"}
80
- super
81
- end
82
77
  end
83
78
  end
84
79
  end
@@ -56,7 +56,7 @@ module Async
56
56
 
57
57
  # Server loop.
58
58
  def each(task: Task.current)
59
- task.annotate("Reading #{version} requests for #{self.class}.")
59
+ task.annotate("Reading #{self.version} requests for #{self.class}.")
60
60
 
61
61
  while request = next_request
62
62
  response = yield(request, self)
@@ -80,7 +80,7 @@ module Async
80
80
  response = nil
81
81
 
82
82
  body.call(stream)
83
- elsif body and request.connect?
83
+ elsif request.connect? and response.success?
84
84
  stream = write_tunnel_body(request.version)
85
85
 
86
86
  # Same as above:
@@ -90,11 +90,12 @@ module Async
90
90
  body.call(stream)
91
91
  else
92
92
  head = request.head?
93
+ version = request.version
93
94
 
94
95
  request = nil unless body
95
96
  response = nil
96
97
 
97
- write_body(request.version, body, head, trailers)
98
+ write_body(version, body, head, trailers)
98
99
  end
99
100
  else
100
101
  # If the request failed to generate a response, it was an internal server error:
@@ -42,7 +42,7 @@ module Async
42
42
  def start(parent: Task.current)
43
43
  raise "Task already started!" if @task
44
44
 
45
- if @body.respond_to?(:call)
45
+ if @body.stream?
46
46
  @task = parent.async(&self.method(:stream))
47
47
  else
48
48
  @task = parent.async(&self.method(:passthrough))
@@ -215,6 +215,11 @@ module Async
215
215
  if request.body.nil?
216
216
  @stream.send_headers(nil, headers, ::Protocol::HTTP2::END_STREAM)
217
217
  else
218
+ if length = request.body.length
219
+ # This puts it at the end of the pseudo-headers:
220
+ pseudo_headers << [CONTENT_LENGTH, length]
221
+ end
222
+
218
223
  # This function informs the headers object that any subsequent headers are going to be trailers. Therefore, it must be called *before* sending the headers, to avoid any race conditions.
219
224
  trailers = request.headers.trailers!
220
225
 
@@ -30,6 +30,15 @@ module Async
30
30
  # Wraps a client, address and headers required to initiate a connectio to a remote host using the CONNECT verb.
31
31
  # Behaves like a TCP endpoint for the purposes of connecting to a remote host.
32
32
  class Proxy
33
+ class ConnectFailure < StandardError
34
+ def initialize(response)
35
+ super "Failed to connect: #{response.status}"
36
+ @response = response
37
+ end
38
+
39
+ attr :response
40
+ end
41
+
33
42
  module Client
34
43
  def proxy(endpoint, headers = nil)
35
44
  Proxy.new(self, endpoint.authority(false), headers)
@@ -92,14 +101,21 @@ module Async
92
101
 
93
102
  response = @client.connect(@address.to_s, @headers, input)
94
103
 
95
- pipe = Body::Pipe.new(response.body, input)
96
-
97
- return pipe.to_io unless block_given?
98
-
99
- begin
100
- yield pipe.to_io
101
- ensure
102
- pipe.close
104
+ if response.success?
105
+ pipe = Body::Pipe.new(response.body, input)
106
+
107
+ return pipe.to_io unless block_given?
108
+
109
+ begin
110
+ yield pipe.to_io
111
+ ensure
112
+ pipe.close
113
+ end
114
+ else
115
+ # This ensures we don't leave a response dangling:
116
+ response.close
117
+
118
+ raise ConnectFailure, response
103
119
  end
104
120
  end
105
121
 
@@ -22,6 +22,6 @@
22
22
 
23
23
  module Async
24
24
  module HTTP
25
- VERSION = "0.52.2"
25
+ VERSION = "0.53.1"
26
26
  end
27
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-http
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.52.2
4
+ version: 0.53.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-05 00:00:00.000000000 Z
11
+ date: 2020-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.19.0
61
+ version: 0.21.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 0.19.0
68
+ version: 0.21.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: protocol-http1
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -95,35 +95,35 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.14.0
97
97
  - !ruby/object:Gem::Dependency
98
- name: async-rspec
98
+ name: async-container
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '1.10'
103
+ version: '0.14'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '1.10'
110
+ version: '0.14'
111
111
  - !ruby/object:Gem::Dependency
112
- name: async-container
112
+ name: async-rspec
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: 0.14.0
117
+ version: '1.10'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: 0.14.0
124
+ version: '1.10'
125
125
  - !ruby/object:Gem::Dependency
126
- name: rack-test
126
+ name: covered
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - ">="
@@ -137,7 +137,7 @@ dependencies:
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
139
  - !ruby/object:Gem::Dependency
140
- name: covered
140
+ name: rack-test
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - ">="
@@ -151,21 +151,21 @@ dependencies:
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
153
  - !ruby/object:Gem::Dependency
154
- name: bundler
154
+ name: rspec
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
- - - ">="
157
+ - - "~>"
158
158
  - !ruby/object:Gem::Version
159
- version: '0'
159
+ version: '3.6'
160
160
  type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
- - - ">="
164
+ - - "~>"
165
165
  - !ruby/object:Gem::Version
166
- version: '0'
166
+ version: '3.6'
167
167
  - !ruby/object:Gem::Dependency
168
- name: bake-bundler
168
+ name: localhost
169
169
  requirement: !ruby/object:Gem::Requirement
170
170
  requirements:
171
171
  - - ">="
@@ -178,57 +178,14 @@ dependencies:
178
178
  - - ">="
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
- - !ruby/object:Gem::Dependency
182
- name: rspec
183
- requirement: !ruby/object:Gem::Requirement
184
- requirements:
185
- - - "~>"
186
- - !ruby/object:Gem::Version
187
- version: '3.6'
188
- type: :development
189
- prerelease: false
190
- version_requirements: !ruby/object:Gem::Requirement
191
- requirements:
192
- - - "~>"
193
- - !ruby/object:Gem::Version
194
- version: '3.6'
195
- description:
181
+ description:
196
182
  email:
197
- - samuel.williams@oriontransfer.co.nz
198
183
  executables: []
199
184
  extensions: []
200
185
  extra_rdoc_files: []
201
186
  files:
202
- - ".editorconfig"
203
- - ".github/workflows/development.yml"
204
- - ".gitignore"
205
- - ".rspec"
206
- - ".travis.yml"
207
- - README.md
208
- - async-http.gemspec
209
- - bake.rb
210
187
  - bake/async/http.rb
211
188
  - bake/async/http/h2spec.rb
212
- - examples/compare/Gemfile
213
- - examples/compare/benchmark.rb
214
- - examples/download/chunked.rb
215
- - examples/fetch/Gemfile
216
- - examples/fetch/Gemfile.lock
217
- - examples/fetch/README.md
218
- - examples/fetch/config.ru
219
- - examples/fetch/public/index.html
220
- - examples/fetch/public/stream.js
221
- - examples/google/search.rb
222
- - examples/request.rb
223
- - examples/stream/stop.rb
224
- - examples/trenni/Gemfile
225
- - examples/trenni/streaming.rb
226
- - examples/upload/client.rb
227
- - examples/upload/data.txt
228
- - examples/upload/server.rb
229
- - examples/upload/upload.rb
230
- - gems.locked
231
- - gems.rb
232
189
  - lib/async/http.rb
233
190
  - lib/async/http/body.rb
234
191
  - lib/async/http/body/delayed.rb
@@ -271,7 +228,7 @@ homepage: https://github.com/socketry/async-http
271
228
  licenses:
272
229
  - MIT
273
230
  metadata: {}
274
- post_install_message:
231
+ post_install_message:
275
232
  rdoc_options: []
276
233
  require_paths:
277
234
  - lib
@@ -287,7 +244,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
287
244
  version: '0'
288
245
  requirements: []
289
246
  rubygems_version: 3.1.2
290
- signing_key:
247
+ signing_key:
291
248
  specification_version: 4
292
249
  summary: A HTTP client and server library.
293
250
  test_files: []