async-http 0.53.1 → 0.56.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0dd87a790df077e00e75dacd429d72c9c7d0efbe6aef48285acdd253ade705fb
4
- data.tar.gz: 0c3404f38a7687d1fc45d35fd10d1e88c2a0bf00aebf33a662725022548d16d2
3
+ metadata.gz: 7d7ce0d0d3e46cbefd67fdd2064c6a144b8dfda461363462e05ea2bc421a1150
4
+ data.tar.gz: '0075078bcb61b68205d0094047df19f38a469b8b545811336a35e3c160bb5880'
5
5
  SHA512:
6
- metadata.gz: f2f6db17a7fe511f9b1a033a069f0805748f27db56f3ee7e719d5b26fcd36470a0998cc7dc39431a6e8d91861077787f0c42456479f1dd231bec637c74b55218
7
- data.tar.gz: b57dfed936c2e97b1db58ada46fdd5fb155dcc5448546020dbf3bdda0ee2e7e8114533dd856162800435db165f8f505965764cd9916fbf33f02d86065a034d53
6
+ metadata.gz: '061618238094db458acb14c1ce6273af279f0571d5c67b1b49a4cc03d12228c4269e45be544b69edb555a9d304f22564306193bd9205262853285940dd7ccf8b'
7
+ data.tar.gz: 63e7b3767a42cc2fc82e81a55bfb5e3aa64ea16d83226a3452b9453266f9bbff1cbef9ea015958d77c89d142ff38f68c8c2b36216df80ad1c7320e868fd0beba
data/bake/async/http.rb CHANGED
@@ -68,8 +68,8 @@ def fetch(url, method:)
68
68
 
69
69
  response.finish
70
70
 
71
- if trailers = response.headers.trailers
72
- trailers.each do |key, value|
71
+ if trailer = response.headers.trailer
72
+ trailer.each do |key, value|
73
73
  terminal.print_line(
74
74
  :key, key.rjust(align), :reset, ": ", :value, value.inspect
75
75
  )
@@ -29,7 +29,7 @@ def server
29
29
  Async.logger.info(self){"Starting server..."}
30
30
 
31
31
  container.run(count: 1) do
32
- server = Async::HTTP::Server.for(endpoint, Async::HTTP::Protocol::HTTP2, "https") do |request|
32
+ server = Async::HTTP::Server.for(endpoint, protocol: Async::HTTP::Protocol::HTTP2, scheme: "https") do |request|
33
33
  Protocol::HTTP::Response[200, {'content-type' => 'text/plain'}, ["Hello World"]]
34
34
  end
35
35
 
@@ -32,13 +32,13 @@ module Async
32
32
  ::Protocol::HTTP::Response[status, headers, self.wrap(request, &block)]
33
33
  end
34
34
 
35
- def self.wrap(request, &block)
36
- self.new(request.body, &block)
35
+ def self.wrap(request = nil, &block)
36
+ self.new(block, request&.body)
37
37
  end
38
38
 
39
- def initialize(input = nil, &block)
40
- @input = input
39
+ def initialize(block, input = nil)
41
40
  @block = block
41
+ @input = input
42
42
 
43
43
  @task = nil
44
44
  @stream = nil
@@ -45,7 +45,7 @@ module Async
45
45
  # @param protocol [Protocol::HTTP1 | Protocol::HTTP2 | Protocol::HTTPS] the protocol to use.
46
46
  # @param scheme [String] The default scheme to set to requests.
47
47
  # @param authority [String] The default authority to set to requests.
48
- def initialize(endpoint, protocol = endpoint.protocol, scheme = endpoint.scheme, authority = endpoint.authority, retries: DEFAULT_RETRIES, connection_limit: DEFAULT_CONNECTION_LIMIT)
48
+ def initialize(endpoint, protocol: endpoint.protocol, scheme: endpoint.scheme, authority: endpoint.authority, retries: DEFAULT_RETRIES, connection_limit: DEFAULT_CONNECTION_LIMIT)
49
49
  @endpoint = endpoint
50
50
  @protocol = protocol
51
51
 
@@ -22,8 +22,10 @@
22
22
 
23
23
  require_relative 'client'
24
24
  require_relative 'endpoint'
25
+
25
26
  require 'protocol/http/middleware'
26
27
  require 'protocol/http/body/buffered'
28
+ require 'protocol/http/accept_encoding'
27
29
 
28
30
  module Async
29
31
  module HTTP
@@ -48,13 +50,15 @@ module Async
48
50
  body = Body::Buffered.wrap(body)
49
51
  headers = ::Protocol::HTTP::Headers[headers]
50
52
 
51
- request = ::Protocol::HTTP::Request.new(client.scheme, endpoint.authority, method, endpoint.path, nil, headers, body)
53
+ request = ::Protocol::HTTP::Request.new(endpoint.scheme, endpoint.authority, method, endpoint.path, nil, headers, body)
52
54
 
53
55
  return client.call(request)
54
56
  end
55
57
 
56
58
  def client_for(endpoint)
57
- Client.new(endpoint, **@options)
59
+ ::Protocol::HTTP::AcceptEncoding.new(
60
+ Client.new(endpoint, **@options)
61
+ )
58
62
  end
59
63
 
60
64
  def close
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require_relative '../internet'
24
+ require 'thread/local'
25
+
26
+ module Async
27
+ module HTTP
28
+ class Internet
29
+ # Provide access to a shared thread-local instance.
30
+ extend ::Thread::Local
31
+ end
32
+ end
33
+ end
@@ -33,18 +33,18 @@ module Async
33
33
  true
34
34
  end
35
35
 
36
- def self.trailers?
36
+ def self.trailer?
37
37
  true
38
38
  end
39
39
 
40
40
  def self.client(peer)
41
- stream = IO::Stream.new(peer, sync: false)
41
+ stream = IO::Stream.new(peer, sync: true)
42
42
 
43
43
  return HTTP1::Client.new(stream, VERSION)
44
44
  end
45
45
 
46
46
  def self.server(peer)
47
- stream = IO::Stream.new(peer, sync: false)
47
+ stream = IO::Stream.new(peer, sync: true)
48
48
 
49
49
  return HTTP1::Server.new(stream, VERSION)
50
50
  end
@@ -31,7 +31,7 @@ module Async
31
31
  def call(request, task: Task.current)
32
32
  Async.logger.debug(self) {"#{request.method} #{request.path} #{request.headers.inspect}"}
33
33
 
34
- trailers = request.headers.trailers!
34
+ trailer = request.headers.trailer!
35
35
 
36
36
  # We carefully interpret https://tools.ietf.org/html/rfc7230#section-6.3.1 to implement this correctly.
37
37
  begin
@@ -63,13 +63,13 @@ module Async
63
63
  subtask.annotate("Streaming body.")
64
64
 
65
65
  # Once we start writing the body, we can't recover if the request fails. That's because the body might be generated dynamically, streaming, etc.
66
- write_body(@version, body, false, trailers)
66
+ write_body(@version, body, false, trailer)
67
67
  end
68
68
  end
69
69
  elsif protocol = request.protocol
70
70
  write_upgrade_body(protocol)
71
71
  else
72
- write_body(@version, body, false, trailers)
72
+ write_body(@version, body, false, trailer)
73
73
  end
74
74
 
75
75
  return Response.read(self, request)
@@ -64,7 +64,7 @@ module Async
64
64
  return if @stream.nil? or @stream.closed?
65
65
 
66
66
  if response
67
- trailers = response.headers.trailers!
67
+ trailer = response.headers.trailer!
68
68
 
69
69
  write_response(@version, response.status, response.headers)
70
70
 
@@ -95,7 +95,7 @@ module Async
95
95
  request = nil unless body
96
96
  response = nil
97
97
 
98
- write_body(version, body, head, trailers)
98
+ write_body(version, body, head, trailer)
99
99
  end
100
100
  else
101
101
  # If the request failed to generate a response, it was an internal server error:
@@ -32,18 +32,18 @@ module Async
32
32
  false
33
33
  end
34
34
 
35
- def self.trailers?
35
+ def self.trailer?
36
36
  false
37
37
  end
38
38
 
39
39
  def self.client(peer)
40
- stream = IO::Stream.new(peer, sync: false)
40
+ stream = IO::Stream.new(peer, sync: true)
41
41
 
42
42
  return HTTP1::Client.new(stream, VERSION)
43
43
  end
44
44
 
45
45
  def self.server(peer)
46
- stream = IO::Stream.new(peer, sync: false)
46
+ stream = IO::Stream.new(peer, sync: true)
47
47
 
48
48
  return HTTP1::Server.new(stream, VERSION)
49
49
  end
@@ -32,18 +32,18 @@ module Async
32
32
  true
33
33
  end
34
34
 
35
- def self.trailers?
35
+ def self.trailer?
36
36
  true
37
37
  end
38
38
 
39
39
  def self.client(peer)
40
- stream = IO::Stream.new(peer, sync: false)
40
+ stream = IO::Stream.new(peer, sync: true)
41
41
 
42
42
  return HTTP1::Client.new(stream, VERSION)
43
43
  end
44
44
 
45
45
  def self.server(peer)
46
- stream = IO::Stream.new(peer, sync: false)
46
+ stream = IO::Stream.new(peer, sync: true)
47
47
 
48
48
  return HTTP1::Server.new(stream, VERSION)
49
49
  end
@@ -33,7 +33,7 @@ module Async
33
33
  true
34
34
  end
35
35
 
36
- def self.trailers?
36
+ def self.trailer?
37
37
  true
38
38
  end
39
39
 
@@ -76,24 +76,6 @@ module Async
76
76
  def self.names
77
77
  ["h2"]
78
78
  end
79
-
80
- module WithPush
81
- CLIENT_SETTINGS = HTTP2::CLIENT_SETTINGS.merge(
82
- ::Protocol::HTTP2::Settings::ENABLE_PUSH => 1,
83
- )
84
-
85
- def self.client(peer, settings = CLIENT_SETTINGS)
86
- HTTP2.client(peer, settings)
87
- end
88
-
89
- def self.server(peer, settings = SERVER_SETTINGS)
90
- HTTP2.server(peer, settings)
91
- end
92
-
93
- def self.names
94
- HTTP2.names
95
- end
96
- end
97
79
  end
98
80
  end
99
81
  end
@@ -38,7 +38,7 @@ module Async
38
38
 
39
39
  CONTENT_LENGTH = 'content-length'.freeze
40
40
  CONNECTION = 'connection'.freeze
41
- TRAILERS = 'trailers'.freeze
41
+ TRAILER = 'trailer'.freeze
42
42
 
43
43
  module Connection
44
44
  def initialize(*)
@@ -107,6 +107,13 @@ module Async
107
107
  end
108
108
  rescue SocketError, IOError, EOFError, Errno::ECONNRESET, Errno::EPIPE, Async::Wrapper::Cancelled
109
109
  # Ignore.
110
+ rescue ::Protocol::HTTP2::GoawayError => error
111
+ # Error is raised if a response is actively reading from the
112
+ # connection. The connection is silently closed if GOAWAY is
113
+ # received outside the request/response cycle.
114
+ if @reader
115
+ self.close(error)
116
+ end
110
117
  ensure
111
118
  # Don't call #close twice.
112
119
  if @reader
@@ -27,17 +27,17 @@ module Async
27
27
  module Protocol
28
28
  module HTTP2
29
29
  class Output
30
- def initialize(stream, body, trailers = nil)
30
+ def initialize(stream, body, trailer = nil)
31
31
  @stream = stream
32
32
  @body = body
33
- @trailers = trailers
33
+ @trailer = trailer
34
34
 
35
35
  @task = nil
36
36
 
37
37
  @window_updated = Async::Condition.new
38
38
  end
39
39
 
40
- attr :trailers
40
+ attr :trailer
41
41
 
42
42
  def start(parent: Task.current)
43
43
  raise "Task already started!" if @task
@@ -39,18 +39,6 @@ module Async
39
39
 
40
40
  attr :request
41
41
 
42
- # Create a fake request on the server, with the given headers.
43
- def create_push_promise_stream(headers)
44
- stream = @connection.create_push_promise_stream(&Stream.method(:create))
45
-
46
- stream.headers = ::Protocol::HTTP::Headers.new
47
-
48
- # This will ultimately enqueue the request to be processed by the server:
49
- stream.receive_initial_headers(headers, false)
50
-
51
- return stream
52
- end
53
-
54
42
  def receive_initial_headers(headers, end_stream)
55
43
  headers.each do |key, value|
56
44
  if key == SCHEME
@@ -133,32 +121,6 @@ module Async
133
121
  false
134
122
  end
135
123
 
136
- def push?
137
- @stream.connection.enable_push?
138
- end
139
-
140
- # @return [Stream] the promised stream, on which to send data.
141
- def push(path, headers = nil, scheme = @scheme, authority = @authority)
142
- raise ArgumentError, "Missing scheme!" unless scheme
143
- raise ArgumentError, "Missing authority!" unless authority
144
-
145
- push_headers = [
146
- [SCHEME, scheme],
147
- [METHOD, ::Protocol::HTTP::Methods::GET],
148
- [PATH, path],
149
- [AUTHORITY, authority]
150
- ]
151
-
152
- if headers
153
- push_headers = Headers::Merged.new(
154
- push_headers,
155
- headers
156
- )
157
- end
158
-
159
- @stream.send_push_promise(push_headers)
160
- end
161
-
162
124
  NO_RESPONSE = [
163
125
  [STATUS, '500'],
164
126
  ]
@@ -183,12 +145,12 @@ module Async
183
145
  headers = ::Protocol::HTTP::Headers::Merged.new(protocol_headers, response.headers)
184
146
 
185
147
  if body = response.body and !self.head?
186
- # 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.
187
- trailers = response.headers.trailers!
148
+ # This function informs the headers object that any subsequent headers are going to be trailer. Therefore, it must be called *before* sending the headers, to avoid any race conditions.
149
+ trailer = response.headers.trailer!
188
150
 
189
151
  @stream.send_headers(nil, headers)
190
152
 
191
- @stream.send_body(body, trailers)
153
+ @stream.send_body(body, trailer)
192
154
  else
193
155
  # Ensure the response body is closed if we are ending the stream:
194
156
  response.close
@@ -50,13 +50,7 @@ module Async
50
50
  end
51
51
 
52
52
  def accept_push_promise_stream(promised_stream_id, headers)
53
- stream = @connection.accept_push_promise_stream(promised_stream_id, &Stream.method(:create))
54
-
55
- stream.response.build_request(headers)
56
-
57
- @response.promises.enqueue(stream.response)
58
-
59
- return stream
53
+ raise ProtocolError, "Cannot accept push promise stream!"
60
54
  end
61
55
 
62
56
  # This should be invoked from the background reader, and notifies the task waiting for the headers that we are done.
@@ -113,7 +107,6 @@ module Async
113
107
  super
114
108
 
115
109
  if @response
116
- @response.promises.enqueue nil
117
110
  @response = nil
118
111
  end
119
112
 
@@ -128,7 +121,6 @@ module Async
128
121
 
129
122
  @stream = stream
130
123
  @request = nil
131
- @promises = nil
132
124
  end
133
125
 
134
126
  attr :stream
@@ -150,10 +142,6 @@ module Async
150
142
  !!@status
151
143
  end
152
144
 
153
- def promises
154
- @promises ||= Async::Queue.new
155
- end
156
-
157
145
  def build_request(headers)
158
146
  request = ::Protocol::HTTP::Request.new
159
147
  request.headers = ::Protocol::HTTP::Headers.new
@@ -220,8 +208,8 @@ module Async
220
208
  pseudo_headers << [CONTENT_LENGTH, length]
221
209
  end
222
210
 
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.
224
- trailers = request.headers.trailers!
211
+ # This function informs the headers object that any subsequent headers are going to be trailer. Therefore, it must be called *before* sending the headers, to avoid any race conditions.
212
+ trailer = request.headers.trailer!
225
213
 
226
214
  begin
227
215
  @stream.send_headers(nil, headers)
@@ -229,7 +217,7 @@ module Async
229
217
  raise RequestFailed
230
218
  end
231
219
 
232
- @stream.send_body(request.body, trailers)
220
+ @stream.send_body(request.body, trailer)
233
221
  end
234
222
  end
235
223
  end
@@ -34,7 +34,7 @@ module Async
34
34
  super
35
35
 
36
36
  @headers = nil
37
- @trailers = nil
37
+ @trailer = nil
38
38
 
39
39
  # Input buffer, reading request body, or response body (receive_data):
40
40
  @length = nil
@@ -62,7 +62,7 @@ module Async
62
62
 
63
63
  def receive_trailing_headers(headers, end_stream)
64
64
  headers.each do |key, value|
65
- if @trailers.include?(key)
65
+ if @trailer.include?(key)
66
66
  add_header(key, value)
67
67
  else
68
68
  raise ::Protocol::HTTP2::HeaderError, "Cannot add trailer #{key} as it was not specified as a trailer!"
@@ -75,8 +75,8 @@ module Async
75
75
  @headers = ::Protocol::HTTP::Headers.new
76
76
  self.receive_initial_headers(super, frame.end_stream?)
77
77
 
78
- @trailers = @headers[TRAILERS]
79
- elsif @trailers and frame.end_stream?
78
+ @trailer = @headers[TRAILER]
79
+ elsif @trailer and frame.end_stream?
80
80
  self.receive_trailing_headers(super, frame.end_stream?)
81
81
  else
82
82
  raise ::Protocol::HTTP2::HeaderError, "Unable to process headers!"
@@ -136,24 +136,24 @@ module Async
136
136
  end
137
137
 
138
138
  # Set the body and begin sending it.
139
- def send_body(body, trailers = nil)
140
- @output = Output.new(self, body, trailers)
139
+ def send_body(body, trailer = nil)
140
+ @output = Output.new(self, body, trailer)
141
141
 
142
142
  @output.start
143
143
  end
144
144
 
145
145
  # Called when the output terminates normally.
146
146
  def finish_output(error = nil)
147
- trailers = @output&.trailers
147
+ trailer = @output&.trailer
148
148
 
149
149
  @output = nil
150
150
 
151
151
  if error
152
152
  send_reset_stream(::Protocol::HTTP2::Error::INTERNAL_ERROR)
153
153
  else
154
- # Write trailers?
155
- if trailers
156
- send_headers(nil, trailers, ::Protocol::HTTP2::END_STREAM)
154
+ # Write trailer?
155
+ if trailer
156
+ send_headers(nil, trailer, ::Protocol::HTTP2::END_STREAM)
157
157
  else
158
158
  send_data(nil, ::Protocol::HTTP2::END_STREAM)
159
159
  end
@@ -42,10 +42,6 @@ module Async
42
42
  false
43
43
  end
44
44
 
45
- def push?
46
- false
47
- end
48
-
49
45
  def peer
50
46
  if connection = self.connection
51
47
  connection.peer
@@ -29,11 +29,11 @@ require 'protocol/http/middleware'
29
29
  module Async
30
30
  module HTTP
31
31
  class Server < ::Protocol::HTTP::Middleware
32
- def self.for(*arguments, &block)
33
- self.new(block, *arguments)
32
+ def self.for(*arguments, **options, &block)
33
+ self.new(block, *arguments, **options)
34
34
  end
35
35
 
36
- def initialize(app, endpoint, protocol = endpoint.protocol, scheme = endpoint.scheme)
36
+ def initialize(app, endpoint, protocol: endpoint.protocol, scheme: endpoint.scheme)
37
37
  super(app)
38
38
 
39
39
  @endpoint = endpoint
@@ -22,6 +22,6 @@
22
22
 
23
23
  module Async
24
24
  module HTTP
25
- VERSION = "0.53.1"
25
+ VERSION = "0.56.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.53.1
4
+ version: 0.56.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-15 00:00:00.000000000 Z
11
+ date: 2021-04-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -58,28 +58,28 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.21.0
61
+ version: 0.22.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.21.0
68
+ version: 0.22.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: protocol-http1
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 0.13.0
75
+ version: 0.14.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 0.13.0
82
+ version: 0.14.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: protocol-http2
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -197,6 +197,7 @@ files:
197
197
  - lib/async/http/client.rb
198
198
  - lib/async/http/endpoint.rb
199
199
  - lib/async/http/internet.rb
200
+ - lib/async/http/internet/instance.rb
200
201
  - lib/async/http/protocol.rb
201
202
  - lib/async/http/protocol/http1.rb
202
203
  - lib/async/http/protocol/http1/client.rb