async-http 0.76.0 → 0.78.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/bake/async/http/h2spec.rb +6 -6
- data/bake/async/http.rb +3 -3
- data/lib/async/http/body/hijack.rb +4 -4
- data/lib/async/http/body/pipe.rb +1 -1
- data/lib/async/http/body/writable.rb +3 -3
- data/lib/async/http/body.rb +3 -3
- data/lib/async/http/client.rb +15 -18
- data/lib/async/http/endpoint.rb +10 -10
- data/lib/async/http/internet/instance.rb +1 -1
- data/lib/async/http/internet.rb +5 -5
- data/lib/async/http/middleware/location_redirector.rb +8 -8
- data/lib/async/http/mock/endpoint.rb +2 -2
- data/lib/async/http/mock.rb +1 -1
- data/lib/async/http/protocol/http.rb +2 -2
- data/lib/async/http/protocol/http1/client.rb +19 -6
- data/lib/async/http/protocol/http1/connection.rb +6 -7
- data/lib/async/http/protocol/http1/finishable.rb +58 -0
- data/lib/async/http/protocol/http1/request.rb +3 -3
- data/lib/async/http/protocol/http1/response.rb +10 -2
- data/lib/async/http/protocol/http1/server.rb +38 -15
- data/lib/async/http/protocol/http1.rb +3 -3
- data/lib/async/http/protocol/http10.rb +1 -1
- data/lib/async/http/protocol/http11.rb +1 -1
- data/lib/async/http/protocol/http2/client.rb +4 -4
- data/lib/async/http/protocol/http2/connection.rb +12 -12
- data/lib/async/http/protocol/http2/input.rb +2 -2
- data/lib/async/http/protocol/http2/output.rb +2 -2
- data/lib/async/http/protocol/http2/request.rb +4 -4
- data/lib/async/http/protocol/http2/response.rb +14 -4
- data/lib/async/http/protocol/http2/server.rb +3 -3
- data/lib/async/http/protocol/http2/stream.rb +12 -4
- data/lib/async/http/protocol/http2.rb +3 -3
- data/lib/async/http/protocol/https.rb +3 -3
- data/lib/async/http/protocol/request.rb +7 -3
- data/lib/async/http/protocol/response.rb +7 -3
- data/lib/async/http/protocol.rb +3 -3
- data/lib/async/http/proxy.rb +4 -3
- data/lib/async/http/reference.rb +2 -2
- data/lib/async/http/relative_location.rb +1 -1
- data/lib/async/http/server.rb +13 -13
- data/lib/async/http/statistics.rb +4 -4
- data/lib/async/http/version.rb +1 -1
- data/lib/async/http.rb +5 -5
- data/readme.md +11 -0
- data/releases.md +11 -0
- data.tar.gz.sig +0 -0
- metadata +7 -6
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76e78af8d20808d557b1c13c850af0a268de5535726ba07708b2012eb8752029
|
4
|
+
data.tar.gz: 53bdf9b950394a03ca8c1fd47befe51e8ba51a5cce82aa47c01111df7efd21b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43c49b50bb88955088b74926e3fe33310f38f4b09d9b9ecdc538a9835c9be5b8be0e172e09794324a53db99e09b0102ae96fc179af13578a758f42644d6f4011
|
7
|
+
data.tar.gz: fa1a0d97f326bdd72010f07cfe21004b0da8f75fe4556778bd3b918f42e2e85f22bc41cd07e2a64b4395540e531a879480e634a8fe401ee0d0d7c146af8b61d7
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/bake/async/http/h2spec.rb
CHANGED
@@ -21,12 +21,12 @@ end
|
|
21
21
|
private
|
22
22
|
|
23
23
|
def server
|
24
|
-
require
|
25
|
-
require
|
26
|
-
require
|
27
|
-
require
|
24
|
+
require "async"
|
25
|
+
require "async/container"
|
26
|
+
require "async/http/server"
|
27
|
+
require "io/endpoint/host_endpoint"
|
28
28
|
|
29
|
-
endpoint = IO::Endpoint.tcp(
|
29
|
+
endpoint = IO::Endpoint.tcp("127.0.0.1", 7272)
|
30
30
|
|
31
31
|
container = Async::Container.new
|
32
32
|
|
@@ -34,7 +34,7 @@ def server
|
|
34
34
|
|
35
35
|
container.run(count: 1) do
|
36
36
|
server = Async::HTTP::Server.for(endpoint, protocol: Async::HTTP::Protocol::HTTP2, scheme: "https") do |request|
|
37
|
-
Protocol::HTTP::Response[200, {
|
37
|
+
Protocol::HTTP::Response[200, {"content-type" => "text/plain"}, ["Hello World"]]
|
38
38
|
end
|
39
39
|
|
40
40
|
Async do
|
data/bake/async/http.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2020-
|
4
|
+
# Copyright, 2020-2024, by Samuel Williams.
|
5
5
|
|
6
6
|
# Fetch the specified URL and print the response.
|
7
7
|
# @param url [String] the URL to parse and fetch.
|
8
8
|
# @param method [String] the HTTP method to use.
|
9
9
|
def fetch(url, method:)
|
10
|
-
require
|
11
|
-
require
|
10
|
+
require "async/http/internet"
|
11
|
+
require "kernel/sync"
|
12
12
|
|
13
13
|
terminal = Console::Terminal.for($stdout)
|
14
14
|
terminal[:request] = terminal.style(:blue, nil, :bold)
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2019-
|
4
|
+
# Copyright, 2019-2024, by Samuel Williams.
|
5
5
|
|
6
|
-
require
|
7
|
-
require
|
6
|
+
require "protocol/http/body/readable"
|
7
|
+
require "protocol/http/body/stream"
|
8
8
|
|
9
|
-
require_relative
|
9
|
+
require_relative "writable"
|
10
10
|
|
11
11
|
module Async
|
12
12
|
module HTTP
|
data/lib/async/http/body/pipe.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2018-
|
4
|
+
# Copyright, 2018-2024, by Samuel Williams.
|
5
5
|
|
6
|
-
require
|
7
|
-
require
|
6
|
+
require "protocol/http/body/writable"
|
7
|
+
require "async/queue"
|
8
8
|
|
9
9
|
module Async
|
10
10
|
module HTTP
|
data/lib/async/http/body.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2018-
|
4
|
+
# Copyright, 2018-2024, by Samuel Williams.
|
5
5
|
|
6
|
-
require
|
7
|
-
require_relative
|
6
|
+
require "protocol/http/body/buffered"
|
7
|
+
require_relative "body/writable"
|
8
8
|
|
9
9
|
module Async
|
10
10
|
module HTTP
|
data/lib/async/http/client.rb
CHANGED
@@ -4,16 +4,16 @@
|
|
4
4
|
# Copyright, 2017-2024, by Samuel Williams.
|
5
5
|
# Copyright, 2022, by Ian Ker-Seymer.
|
6
6
|
|
7
|
-
require
|
7
|
+
require "io/endpoint"
|
8
8
|
|
9
|
-
require
|
9
|
+
require "async/pool/controller"
|
10
10
|
|
11
|
-
require
|
12
|
-
require
|
11
|
+
require "protocol/http/body/completable"
|
12
|
+
require "protocol/http/methods"
|
13
13
|
|
14
|
-
require
|
14
|
+
require "traces/provider"
|
15
15
|
|
16
|
-
require_relative
|
16
|
+
require_relative "protocol"
|
17
17
|
|
18
18
|
module Async
|
19
19
|
module HTTP
|
@@ -140,7 +140,7 @@ module Async
|
|
140
140
|
def inspect
|
141
141
|
"#<#{self.class} authority=#{@authority.inspect}>"
|
142
142
|
end
|
143
|
-
|
143
|
+
|
144
144
|
Traces::Provider(self) do
|
145
145
|
def call(request)
|
146
146
|
attributes = {
|
@@ -151,30 +151,30 @@ module Async
|
|
151
151
|
}
|
152
152
|
|
153
153
|
if protocol = request.protocol
|
154
|
-
attributes[
|
154
|
+
attributes["http.protocol"] = protocol
|
155
155
|
end
|
156
156
|
|
157
157
|
if length = request.body&.length
|
158
|
-
attributes[
|
158
|
+
attributes["http.request.length"] = length
|
159
159
|
end
|
160
160
|
|
161
|
-
Traces.trace(
|
161
|
+
Traces.trace("async.http.client.call", attributes: attributes) do |span|
|
162
162
|
if context = Traces.trace_context
|
163
|
-
request.headers[
|
163
|
+
request.headers["traceparent"] = context.to_s
|
164
164
|
# request.headers['tracestate'] = context.state
|
165
165
|
end
|
166
166
|
|
167
167
|
super.tap do |response|
|
168
168
|
if version = response&.version
|
169
|
-
span[
|
169
|
+
span["http.version"] = version
|
170
170
|
end
|
171
171
|
|
172
172
|
if status = response&.status
|
173
|
-
span[
|
173
|
+
span["http.status_code"] = status
|
174
174
|
end
|
175
175
|
|
176
176
|
if length = response.body&.length
|
177
|
-
span[
|
177
|
+
span["http.response.length"] = length
|
178
178
|
end
|
179
179
|
end
|
180
180
|
end
|
@@ -186,10 +186,7 @@ module Async
|
|
186
186
|
def make_response(request, connection)
|
187
187
|
response = request.call(connection)
|
188
188
|
|
189
|
-
|
190
|
-
::Protocol::HTTP::Body::Completable.wrap(response) do
|
191
|
-
@pool.release(connection)
|
192
|
-
end
|
189
|
+
response.pool = @pool
|
193
190
|
|
194
191
|
return response
|
195
192
|
end
|
data/lib/async/http/endpoint.rb
CHANGED
@@ -7,22 +7,22 @@
|
|
7
7
|
# Copyright, 2024, by Igor Sidorov.
|
8
8
|
# Copyright, 2024, by Hal Brodigan.
|
9
9
|
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
10
|
+
require "io/endpoint"
|
11
|
+
require "io/endpoint/host_endpoint"
|
12
|
+
require "io/endpoint/ssl_endpoint"
|
13
13
|
|
14
|
-
require_relative
|
15
|
-
require_relative
|
14
|
+
require_relative "protocol/http"
|
15
|
+
require_relative "protocol/https"
|
16
16
|
|
17
17
|
module Async
|
18
18
|
module HTTP
|
19
19
|
# Represents a way to connect to a remote HTTP server.
|
20
20
|
class Endpoint < ::IO::Endpoint::Generic
|
21
21
|
SCHEMES = {
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
"http" => URI::HTTP,
|
23
|
+
"https" => URI::HTTPS,
|
24
|
+
"ws" => URI::WS,
|
25
|
+
"wss" => URI::WSS,
|
26
26
|
}
|
27
27
|
|
28
28
|
def self.parse(string, endpoint = nil, **options)
|
@@ -102,7 +102,7 @@ module Async
|
|
102
102
|
end
|
103
103
|
|
104
104
|
def secure?
|
105
|
-
[
|
105
|
+
["https", "wss"].include?(self.scheme)
|
106
106
|
end
|
107
107
|
|
108
108
|
def protocol
|
data/lib/async/http/internet.rb
CHANGED
@@ -4,12 +4,12 @@
|
|
4
4
|
# Copyright, 2018-2024, by Samuel Williams.
|
5
5
|
# Copyright, 2024, by Igor Sidorov.
|
6
6
|
|
7
|
-
require_relative
|
8
|
-
require_relative
|
7
|
+
require_relative "client"
|
8
|
+
require_relative "endpoint"
|
9
9
|
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
10
|
+
require "protocol/http/middleware"
|
11
|
+
require "protocol/http/body/buffered"
|
12
|
+
require "protocol/http/accept_encoding"
|
13
13
|
|
14
14
|
module Async
|
15
15
|
module HTTP
|
@@ -3,10 +3,10 @@
|
|
3
3
|
# Released under the MIT License.
|
4
4
|
# Copyright, 2024, by Samuel Williams.
|
5
5
|
|
6
|
-
require_relative
|
6
|
+
require_relative "../reference"
|
7
7
|
|
8
|
-
require
|
9
|
-
require
|
8
|
+
require "protocol/http/middleware"
|
9
|
+
require "protocol/http/body/rewindable"
|
10
10
|
|
11
11
|
module Async
|
12
12
|
module HTTP
|
@@ -34,10 +34,10 @@ module Async
|
|
34
34
|
|
35
35
|
# Header keys which should be deleted when changing a request from a POST to a GET as defined by <https://fetch.spec.whatwg.org/#request-body-header-name>.
|
36
36
|
PROHIBITED_GET_HEADERS = [
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
"content-encoding",
|
38
|
+
"content-language",
|
39
|
+
"content-location",
|
40
|
+
"content-type",
|
41
41
|
]
|
42
42
|
|
43
43
|
# maximum_hops is the max number of redirects. Set to 0 to allow 1 request with no redirects.
|
@@ -91,7 +91,7 @@ module Async
|
|
91
91
|
hops += 1
|
92
92
|
|
93
93
|
# Get the redirect location:
|
94
|
-
unless location = response.headers[
|
94
|
+
unless location = response.headers["location"]
|
95
95
|
return response
|
96
96
|
end
|
97
97
|
|
data/lib/async/http/mock.rb
CHANGED
@@ -3,18 +3,32 @@
|
|
3
3
|
# Released under the MIT License.
|
4
4
|
# Copyright, 2018-2024, by Samuel Williams.
|
5
5
|
|
6
|
-
require_relative
|
6
|
+
require_relative "connection"
|
7
7
|
|
8
8
|
module Async
|
9
9
|
module HTTP
|
10
10
|
module Protocol
|
11
11
|
module HTTP1
|
12
12
|
class Client < Connection
|
13
|
+
def initialize(...)
|
14
|
+
super
|
15
|
+
|
16
|
+
@pool = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_accessor :pool
|
20
|
+
|
21
|
+
def closed!
|
22
|
+
super
|
23
|
+
|
24
|
+
if pool = @pool
|
25
|
+
@pool = nil
|
26
|
+
pool.release(self)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
13
30
|
# Used by the client to send requests to the remote server.
|
14
31
|
def call(request, task: Task.current)
|
15
|
-
# We need to keep track of connections which are not in the initial "ready" state.
|
16
|
-
@ready = false
|
17
|
-
|
18
32
|
Console.logger.debug(self) {"#{request.method} #{request.path} #{request.headers.inspect}"}
|
19
33
|
|
20
34
|
# Mark the start of the trailers:
|
@@ -54,12 +68,11 @@ module Async
|
|
54
68
|
end
|
55
69
|
|
56
70
|
response = Response.read(self, request)
|
57
|
-
@ready = true
|
58
71
|
|
59
72
|
return response
|
60
73
|
rescue
|
61
74
|
# This will ensure that #reusable? returns false.
|
62
|
-
|
75
|
+
self.close
|
63
76
|
|
64
77
|
raise
|
65
78
|
end
|
@@ -3,10 +3,10 @@
|
|
3
3
|
# Released under the MIT License.
|
4
4
|
# Copyright, 2018-2024, by Samuel Williams.
|
5
5
|
|
6
|
-
require
|
6
|
+
require "protocol/http1"
|
7
7
|
|
8
|
-
require_relative
|
9
|
-
require_relative
|
8
|
+
require_relative "request"
|
9
|
+
require_relative "response"
|
10
10
|
|
11
11
|
module Async
|
12
12
|
module HTTP
|
@@ -16,12 +16,11 @@ module Async
|
|
16
16
|
def initialize(stream, version)
|
17
17
|
super(stream)
|
18
18
|
|
19
|
-
@ready = true
|
20
19
|
@version = version
|
21
20
|
end
|
22
21
|
|
23
22
|
def to_s
|
24
|
-
"\#<#{self.class} negotiated #{@version},
|
23
|
+
"\#<#{self.class} negotiated #{@version}, #{@state}>"
|
25
24
|
end
|
26
25
|
|
27
26
|
def as_json(...)
|
@@ -62,11 +61,11 @@ module Async
|
|
62
61
|
|
63
62
|
# Can we use this connection to make requests?
|
64
63
|
def viable?
|
65
|
-
|
64
|
+
self.idle? && @stream&.readable?
|
66
65
|
end
|
67
66
|
|
68
67
|
def reusable?
|
69
|
-
@
|
68
|
+
@persistent && @stream && !@stream.closed?
|
70
69
|
end
|
71
70
|
end
|
72
71
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require "protocol/http/body/wrapper"
|
7
|
+
require "async/variable"
|
8
|
+
|
9
|
+
module Async
|
10
|
+
module HTTP
|
11
|
+
module Protocol
|
12
|
+
module HTTP1
|
13
|
+
# Keeps track of whether a body is being read, and if so, waits for it to be closed.
|
14
|
+
class Finishable < ::Protocol::HTTP::Body::Wrapper
|
15
|
+
def initialize(body)
|
16
|
+
super(body)
|
17
|
+
|
18
|
+
@closed = Async::Variable.new
|
19
|
+
@error = nil
|
20
|
+
|
21
|
+
@reading = false
|
22
|
+
end
|
23
|
+
|
24
|
+
def reading?
|
25
|
+
@reading
|
26
|
+
end
|
27
|
+
|
28
|
+
def read
|
29
|
+
@reading = true
|
30
|
+
|
31
|
+
super
|
32
|
+
end
|
33
|
+
|
34
|
+
def close(error = nil)
|
35
|
+
unless @closed.resolved?
|
36
|
+
@error = error
|
37
|
+
@closed.value = true
|
38
|
+
end
|
39
|
+
|
40
|
+
super
|
41
|
+
end
|
42
|
+
|
43
|
+
def wait
|
44
|
+
if @reading
|
45
|
+
@closed.wait
|
46
|
+
else
|
47
|
+
self.discard
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def inspect
|
52
|
+
"#<#{self.class} closed=#{@closed} error=#{@error}> | #{super}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
# Released under the MIT License.
|
4
4
|
# Copyright, 2018-2024, by Samuel Williams.
|
5
5
|
|
6
|
-
require_relative
|
6
|
+
require_relative "../request"
|
7
7
|
|
8
8
|
module Async
|
9
9
|
module HTTP
|
@@ -16,13 +16,13 @@ module Async
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
UPGRADE =
|
19
|
+
UPGRADE = "upgrade"
|
20
20
|
|
21
21
|
def initialize(connection, authority, method, path, version, headers, body)
|
22
22
|
@connection = connection
|
23
23
|
|
24
24
|
# HTTP/1 requests with an upgrade header (which can contain zero or more values) are extracted into the protocol field of the request, and we expect a response to select one of those protocols with a status code of 101 Switching Protocols.
|
25
|
-
protocol = headers.delete(
|
25
|
+
protocol = headers.delete("upgrade")
|
26
26
|
|
27
27
|
super(nil, authority, method, path, version, headers, body, protocol, self.public_method(:write_interim_response))
|
28
28
|
end
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# Copyright, 2018-2024, by Samuel Williams.
|
5
5
|
# Copyright, 2023, by Josh Huber.
|
6
6
|
|
7
|
-
require_relative
|
7
|
+
require_relative "../response"
|
8
8
|
|
9
9
|
module Async
|
10
10
|
module HTTP
|
@@ -23,7 +23,7 @@ module Async
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
UPGRADE =
|
26
|
+
UPGRADE = "upgrade"
|
27
27
|
|
28
28
|
# @attribute [String] The HTTP response line reason.
|
29
29
|
attr :reason
|
@@ -39,6 +39,14 @@ module Async
|
|
39
39
|
super(version, status, headers, body, protocol)
|
40
40
|
end
|
41
41
|
|
42
|
+
def pool=(pool)
|
43
|
+
if @connection.idle? or @connection.closed?
|
44
|
+
pool.release(@connection)
|
45
|
+
else
|
46
|
+
@connection.pool = pool
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
42
50
|
def connection
|
43
51
|
@connection
|
44
52
|
end
|
@@ -6,24 +6,43 @@
|
|
6
6
|
# Copyright, 2023, by Thomas Morgan.
|
7
7
|
# Copyright, 2024, by Anton Zhuravsky.
|
8
8
|
|
9
|
-
require_relative
|
10
|
-
|
9
|
+
require_relative "connection"
|
10
|
+
require_relative "finishable"
|
11
|
+
|
12
|
+
require "console/event/failure"
|
11
13
|
|
12
14
|
module Async
|
13
15
|
module HTTP
|
14
16
|
module Protocol
|
15
17
|
module HTTP1
|
16
18
|
class Server < Connection
|
19
|
+
def initialize(...)
|
20
|
+
super
|
21
|
+
|
22
|
+
@ready = Async::Notification.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def closed!
|
26
|
+
super
|
27
|
+
|
28
|
+
@ready.signal
|
29
|
+
end
|
30
|
+
|
17
31
|
def fail_request(status)
|
18
32
|
@persistent = false
|
19
33
|
write_response(@version, status, {})
|
20
34
|
write_body(@version, nil)
|
21
35
|
rescue => error
|
22
36
|
# At this point, there is very little we can do to recover:
|
23
|
-
Console::Event::Failure.for(error).emit(self, "Failed to write failure response
|
37
|
+
Console::Event::Failure.for(error).emit(self, "Failed to write failure response!", severity: :debug)
|
24
38
|
end
|
25
39
|
|
26
40
|
def next_request
|
41
|
+
# Wait for the connection to become idle before reading the next request:
|
42
|
+
unless idle?
|
43
|
+
@ready.wait
|
44
|
+
end
|
45
|
+
|
27
46
|
# The default is true.
|
28
47
|
return unless @persistent
|
29
48
|
|
@@ -35,7 +54,7 @@ module Async
|
|
35
54
|
end
|
36
55
|
|
37
56
|
return request
|
38
|
-
rescue ::Protocol::HTTP1::BadRequest
|
57
|
+
rescue ::Protocol::HTTP1::BadRequest => error
|
39
58
|
fail_request(400)
|
40
59
|
# Conceivably we could retry here, but we don't really know how bad the error is, so it's better to just fail:
|
41
60
|
raise
|
@@ -46,7 +65,13 @@ module Async
|
|
46
65
|
task.annotate("Reading #{self.version} requests for #{self.class}.")
|
47
66
|
|
48
67
|
while request = next_request
|
68
|
+
if body = request.body
|
69
|
+
finishable = Finishable.new(body)
|
70
|
+
request.body = finishable
|
71
|
+
end
|
72
|
+
|
49
73
|
response = yield(request, self)
|
74
|
+
version = request.version
|
50
75
|
body = response&.body
|
51
76
|
|
52
77
|
if hijacked?
|
@@ -77,7 +102,7 @@ module Async
|
|
77
102
|
# This code path is to support legacy behavior where the response status is set to 101, but the protocol is not upgraded. This may not be a valid use case, but it is supported for compatibility. We expect the response headers to contain the `upgrade` header.
|
78
103
|
write_response(@version, response.status, response.headers)
|
79
104
|
|
80
|
-
stream = write_tunnel_body(
|
105
|
+
stream = write_tunnel_body(version)
|
81
106
|
|
82
107
|
# Same as above:
|
83
108
|
request = nil
|
@@ -89,7 +114,7 @@ module Async
|
|
89
114
|
write_response(@version, response.status, response.headers)
|
90
115
|
|
91
116
|
if request.connect? and response.success?
|
92
|
-
stream = write_tunnel_body(
|
117
|
+
stream = write_tunnel_body(version)
|
93
118
|
|
94
119
|
# Same as above:
|
95
120
|
request = nil
|
@@ -99,29 +124,27 @@ module Async
|
|
99
124
|
return body.call(stream)
|
100
125
|
else
|
101
126
|
head = request.head?
|
102
|
-
version = request.version
|
103
127
|
|
104
128
|
# Same as above:
|
105
|
-
request = nil
|
129
|
+
request = nil
|
106
130
|
response = nil
|
107
131
|
|
108
132
|
write_body(version, body, head, trailer)
|
109
133
|
end
|
110
134
|
end
|
111
135
|
|
112
|
-
# We are done with the body
|
136
|
+
# We are done with the body:
|
113
137
|
body = nil
|
114
138
|
else
|
115
139
|
# If the request failed to generate a response, it was an internal server error:
|
116
140
|
write_response(@version, 500, {})
|
117
|
-
write_body(
|
141
|
+
write_body(version, nil)
|
142
|
+
|
143
|
+
request&.finish
|
118
144
|
end
|
119
145
|
|
120
|
-
#
|
121
|
-
|
122
|
-
|
123
|
-
# This ensures we yield at least once every iteration of the loop and allow other fibers to execute.
|
124
|
-
task.yield
|
146
|
+
# Discard or wait for the input body to be consumed:
|
147
|
+
finishable&.wait
|
125
148
|
rescue => error
|
126
149
|
raise
|
127
150
|
ensure
|