async-http 0.75.0 → 0.77.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/finishable.rb +56 -0
- data/lib/async/http/body/hijack.rb +5 -5
- data/lib/async/http/body/pipe.rb +8 -4
- data/lib/async/http/body/writable.rb +4 -95
- data/lib/async/http/body.rb +3 -3
- data/lib/async/http/client.rb +16 -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/request.rb +3 -3
- data/lib/async/http/protocol/http1/response.rb +10 -2
- data/lib/async/http/protocol/http1/server.rb +33 -13
- 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 +3 -3
- data/lib/async/http/protocol/http2/output.rb +30 -15
- 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 +15 -7
- 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 +3 -3
- data/lib/async/http/protocol/response.rb +3 -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 -8
- metadata.gz.sig +0 -0
- data/lib/async/http/body/delayed.rb +0 -32
- data/lib/async/http/body/slowloris.rb +0 -55
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a6e20407a7969b8eebeaf3f3a2dac09bdb3fe48130454ae49f46251a03b5c98
|
4
|
+
data.tar.gz: a827ae19dc5c7f60ed338357091f556d1e48b183fe8ab0c119d75547fce4a6cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 116770838b19e96fdc9ed4e1db8af834f0ed8676542d1090ed88c90d02ac0b978bd94378b41edc151108d86e61c39d2fbb9680d217790e1b1cb3f2ceed2aa64e
|
7
|
+
data.tar.gz: 2b05b93835b83052a89127f12db03fdcd79007b6b0f396134d9818352e48ffaf012057c0b818a56633f3e8b510e7861438e8016d2519bd4d0dec425dfd1113f7
|
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)
|
@@ -0,0 +1,56 @@
|
|
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 Body
|
12
|
+
# Keeps track of whether a body is being read, and if so, waits for it to be closed.
|
13
|
+
class Finishable < ::Protocol::HTTP::Body::Wrapper
|
14
|
+
def initialize(body)
|
15
|
+
super(body)
|
16
|
+
|
17
|
+
@closed = Async::Variable.new
|
18
|
+
@error = nil
|
19
|
+
|
20
|
+
@reading = false
|
21
|
+
end
|
22
|
+
|
23
|
+
def reading?
|
24
|
+
@reading
|
25
|
+
end
|
26
|
+
|
27
|
+
def read
|
28
|
+
@reading = true
|
29
|
+
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
def close(error = nil)
|
34
|
+
unless @closed.resolved?
|
35
|
+
@error = error
|
36
|
+
@closed.value = true
|
37
|
+
end
|
38
|
+
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
42
|
+
def wait
|
43
|
+
if @reading
|
44
|
+
@closed.wait
|
45
|
+
else
|
46
|
+
self.discard
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def inspect
|
51
|
+
"#<#{self.class} closed=#{@closed} error=#{@error}> | #{super}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -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
|
@@ -36,7 +36,7 @@ module Async
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def call(stream)
|
39
|
-
|
39
|
+
@block.call(stream)
|
40
40
|
end
|
41
41
|
|
42
42
|
attr :input
|
data/lib/async/http/body/pipe.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# Copyright, 2019-2024, by Samuel Williams.
|
5
5
|
# Copyright, 2020, by Bruno Sutic.
|
6
6
|
|
7
|
-
require_relative
|
7
|
+
require_relative "writable"
|
8
8
|
|
9
9
|
module Async
|
10
10
|
module HTTP
|
@@ -17,7 +17,7 @@ module Async
|
|
17
17
|
|
18
18
|
head, tail = ::Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM)
|
19
19
|
|
20
|
-
@head = ::IO::Stream
|
20
|
+
@head = ::IO::Stream(head)
|
21
21
|
@tail = tail
|
22
22
|
|
23
23
|
@reader = nil
|
@@ -52,8 +52,10 @@ module Async
|
|
52
52
|
end
|
53
53
|
|
54
54
|
@head.close_write
|
55
|
+
rescue => error
|
56
|
+
raise
|
55
57
|
ensure
|
56
|
-
@input.close(
|
58
|
+
@input.close(error)
|
57
59
|
|
58
60
|
close_head if @writer&.finished?
|
59
61
|
end
|
@@ -68,8 +70,10 @@ module Async
|
|
68
70
|
while chunk = @head.read_partial
|
69
71
|
@output.write(chunk)
|
70
72
|
end
|
73
|
+
rescue => error
|
74
|
+
raise
|
71
75
|
ensure
|
72
|
-
@output.
|
76
|
+
@output.close_write(error)
|
73
77
|
|
74
78
|
close_head if @reader&.finished?
|
75
79
|
end
|
@@ -1,106 +1,15 @@
|
|
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
|
11
11
|
module Body
|
12
|
-
|
13
|
-
|
14
|
-
# A dynamic body which you can write to and read from.
|
15
|
-
class Writable < Readable
|
16
|
-
class Closed < StandardError
|
17
|
-
end
|
18
|
-
|
19
|
-
# @param [Integer] length The length of the response body if known.
|
20
|
-
# @param [Async::Queue] queue Specify a different queue implementation, e.g. `Async::LimitedQueue.new(8)` to enable back-pressure streaming.
|
21
|
-
def initialize(length = nil, queue: Async::Queue.new)
|
22
|
-
@queue = queue
|
23
|
-
|
24
|
-
@length = length
|
25
|
-
|
26
|
-
@count = 0
|
27
|
-
|
28
|
-
@finished = false
|
29
|
-
|
30
|
-
@closed = false
|
31
|
-
@error = nil
|
32
|
-
end
|
33
|
-
|
34
|
-
def length
|
35
|
-
@length
|
36
|
-
end
|
37
|
-
|
38
|
-
# Stop generating output; cause the next call to write to fail with the given error.
|
39
|
-
def close(error = nil)
|
40
|
-
unless @closed
|
41
|
-
@queue.enqueue(nil)
|
42
|
-
|
43
|
-
@closed = true
|
44
|
-
@error = error
|
45
|
-
end
|
46
|
-
|
47
|
-
super
|
48
|
-
end
|
49
|
-
|
50
|
-
def closed?
|
51
|
-
@closed
|
52
|
-
end
|
53
|
-
|
54
|
-
def ready?
|
55
|
-
!@queue.empty?
|
56
|
-
end
|
57
|
-
|
58
|
-
# Has the producer called #finish and has the reader consumed the nil token?
|
59
|
-
def empty?
|
60
|
-
@finished
|
61
|
-
end
|
62
|
-
|
63
|
-
# Read the next available chunk.
|
64
|
-
def read
|
65
|
-
return if @finished
|
66
|
-
|
67
|
-
unless chunk = @queue.dequeue
|
68
|
-
@finished = true
|
69
|
-
end
|
70
|
-
|
71
|
-
return chunk
|
72
|
-
end
|
73
|
-
|
74
|
-
# Write a single chunk to the body. Signal completion by calling `#finish`.
|
75
|
-
def write(chunk)
|
76
|
-
# If the reader breaks, the writer will break.
|
77
|
-
# The inverse of this is less obvious (*)
|
78
|
-
if @closed
|
79
|
-
raise(@error || Closed)
|
80
|
-
end
|
81
|
-
|
82
|
-
@count += 1
|
83
|
-
@queue.enqueue(chunk)
|
84
|
-
end
|
85
|
-
|
86
|
-
alias << write
|
87
|
-
|
88
|
-
def inspect
|
89
|
-
"\#<#{self.class} #{@count} chunks written, #{status}>"
|
90
|
-
end
|
91
|
-
|
92
|
-
private
|
93
|
-
|
94
|
-
def status
|
95
|
-
if @finished
|
96
|
-
'finished'
|
97
|
-
elsif @closed
|
98
|
-
'closing'
|
99
|
-
else
|
100
|
-
'waiting'
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
12
|
+
Writable = ::Protocol::HTTP::Body::Writable
|
104
13
|
end
|
105
14
|
end
|
106
15
|
end
|
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,17 @@
|
|
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
|
+
require_relative "body/finishable"
|
17
18
|
|
18
19
|
module Async
|
19
20
|
module HTTP
|
@@ -140,7 +141,7 @@ module Async
|
|
140
141
|
def inspect
|
141
142
|
"#<#{self.class} authority=#{@authority.inspect}>"
|
142
143
|
end
|
143
|
-
|
144
|
+
|
144
145
|
Traces::Provider(self) do
|
145
146
|
def call(request)
|
146
147
|
attributes = {
|
@@ -151,30 +152,30 @@ module Async
|
|
151
152
|
}
|
152
153
|
|
153
154
|
if protocol = request.protocol
|
154
|
-
attributes[
|
155
|
+
attributes["http.protocol"] = protocol
|
155
156
|
end
|
156
157
|
|
157
158
|
if length = request.body&.length
|
158
|
-
attributes[
|
159
|
+
attributes["http.request.length"] = length
|
159
160
|
end
|
160
161
|
|
161
|
-
Traces.trace(
|
162
|
+
Traces.trace("async.http.client.call", attributes: attributes) do |span|
|
162
163
|
if context = Traces.trace_context
|
163
|
-
request.headers[
|
164
|
+
request.headers["traceparent"] = context.to_s
|
164
165
|
# request.headers['tracestate'] = context.state
|
165
166
|
end
|
166
167
|
|
167
168
|
super.tap do |response|
|
168
169
|
if version = response&.version
|
169
|
-
span[
|
170
|
+
span["http.version"] = version
|
170
171
|
end
|
171
172
|
|
172
173
|
if status = response&.status
|
173
|
-
span[
|
174
|
+
span["http.status_code"] = status
|
174
175
|
end
|
175
176
|
|
176
177
|
if length = response.body&.length
|
177
|
-
span[
|
178
|
+
span["http.response.length"] = length
|
178
179
|
end
|
179
180
|
end
|
180
181
|
end
|
@@ -186,10 +187,7 @@ module Async
|
|
186
187
|
def make_response(request, connection)
|
187
188
|
response = request.call(connection)
|
188
189
|
|
189
|
-
|
190
|
-
::Protocol::HTTP::Body::Completable.wrap(response) do
|
191
|
-
@pool.release(connection)
|
192
|
-
end
|
190
|
+
response.pool = @pool
|
193
191
|
|
194
192
|
return response
|
195
193
|
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
|
@@ -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
|