async-http 0.86.0 → 0.87.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/async/http/protocol/http1/client.rb +11 -2
- data/lib/async/http/protocol/http1/request.rb +29 -5
- data/lib/async/http/protocol/http2/request.rb +2 -2
- data/lib/async/http/protocol/http2/response.rb +5 -2
- data/lib/async/http/proxy.rb +2 -2
- data/lib/async/http/version.rb +1 -1
- data/license.md +1 -1
- data/readme.md +4 -0
- data/releases.md +24 -0
- data.tar.gz.sig +0 -0
- metadata +20 -25
- metadata.gz.sig +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7fb9ca49f85d321261c3a3ee9cccf0459841fc09e5df5981289c6d4a6dc6a973
|
4
|
+
data.tar.gz: 2a8310e595b65f51001f0b871de5992476153cd0de3eb175d1060e7743ffe6d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b2c843acae23369e6fcffffea81ee443bac6caa2bb21acd80a72af00a831326700e0b0c6e57128f300b11bcbaf435f03e59a84c3de17c59b170241a0dce0cfb
|
7
|
+
data.tar.gz: b851a56d637736f82cc48b68c00ca4562daa9756548792d4f41c21771150e6b1bd1385eb429cfa43937936454d4719e3535f9273254dc81e26880ce30aa3eeb6
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2018-
|
4
|
+
# Copyright, 2018-2025, by Samuel Williams.
|
5
5
|
|
6
6
|
require_relative "connection"
|
7
7
|
|
@@ -39,7 +39,16 @@ module Async
|
|
39
39
|
|
40
40
|
# We carefully interpret https://tools.ietf.org/html/rfc7230#section-6.3.1 to implement this correctly.
|
41
41
|
begin
|
42
|
-
|
42
|
+
target = request.path
|
43
|
+
authority = request.authority
|
44
|
+
|
45
|
+
# If we are using a CONNECT request, we need to use the authority as the target:
|
46
|
+
if request.connect?
|
47
|
+
target = authority
|
48
|
+
authority = nil
|
49
|
+
end
|
50
|
+
|
51
|
+
write_request(authority, request.method, target, @version, request.headers)
|
43
52
|
rescue
|
44
53
|
# If we fail to fully write the request and body, we can retry this request.
|
45
54
|
raise RequestFailed
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2018-
|
4
|
+
# Copyright, 2018-2025, by Samuel Williams.
|
5
5
|
|
6
6
|
require_relative "../request"
|
7
7
|
|
@@ -10,21 +10,45 @@ module Async
|
|
10
10
|
module Protocol
|
11
11
|
module HTTP1
|
12
12
|
class Request < Protocol::Request
|
13
|
+
def self.valid_path?(target)
|
14
|
+
if target.start_with?("/")
|
15
|
+
return true
|
16
|
+
elsif target == "*"
|
17
|
+
return true
|
18
|
+
else
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
URI_PATTERN = %r{\A(?<scheme>[^:/]+)://(?<authority>[^/]+)(?<path>.*)\z}
|
24
|
+
|
13
25
|
def self.read(connection)
|
14
|
-
|
15
|
-
|
26
|
+
connection.read_request do |authority, method, target, version, headers, body|
|
27
|
+
if method == ::Protocol::HTTP::Methods::CONNECT
|
28
|
+
# We put the target into the authority field for CONNECT requests, as per HTTP/2 semantics.
|
29
|
+
self.new(connection, nil, target, method, nil, version, headers, body)
|
30
|
+
elsif valid_path?(target)
|
31
|
+
# This is a valid request.
|
32
|
+
self.new(connection, nil, authority, method, target, version, headers, body)
|
33
|
+
elsif match = target.match(URI_PATTERN)
|
34
|
+
# We map the incoming absolute URI target to the scheme, authority, and path fields of the request.
|
35
|
+
self.new(connection, match[:scheme], match[:authority], method, match[:path], version, headers, body)
|
36
|
+
else
|
37
|
+
# This is an invalid request.
|
38
|
+
raise ::Protocol::HTTP1::BadRequest.new("Invalid request target: #{target}")
|
39
|
+
end
|
16
40
|
end
|
17
41
|
end
|
18
42
|
|
19
43
|
UPGRADE = "upgrade"
|
20
44
|
|
21
|
-
def initialize(connection, authority, method, path, version, headers, body)
|
45
|
+
def initialize(connection, scheme, authority, method, path, version, headers, body)
|
22
46
|
@connection = connection
|
23
47
|
|
24
48
|
# 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
49
|
protocol = headers.delete("upgrade")
|
26
50
|
|
27
|
-
super(
|
51
|
+
super(scheme, authority, method, path, version, headers, body, protocol, self.public_method(:write_interim_response))
|
28
52
|
end
|
29
53
|
|
30
54
|
def connection
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2018-
|
4
|
+
# Copyright, 2018-2025, by Samuel Williams.
|
5
5
|
|
6
6
|
require_relative "../request"
|
7
7
|
require_relative "stream"
|
@@ -99,7 +99,7 @@ module Async
|
|
99
99
|
end
|
100
100
|
|
101
101
|
def valid?
|
102
|
-
@scheme and @method and @path
|
102
|
+
@scheme and @method and (@path or @method == ::Protocol::HTTP::Methods::CONNECT)
|
103
103
|
end
|
104
104
|
|
105
105
|
def hijack?
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2018-
|
4
|
+
# Copyright, 2018-2025, by Samuel Williams.
|
5
5
|
|
6
6
|
require_relative "../response"
|
7
7
|
require_relative "stream"
|
@@ -204,9 +204,12 @@ module Async
|
|
204
204
|
pseudo_headers = [
|
205
205
|
[SCHEME, request.scheme],
|
206
206
|
[METHOD, request.method],
|
207
|
-
[PATH, request.path],
|
208
207
|
]
|
209
208
|
|
209
|
+
if path = request.path
|
210
|
+
pseudo_headers << [PATH, path]
|
211
|
+
end
|
212
|
+
|
210
213
|
# To ensure that the HTTP/1.1 request line can be reproduced accurately, this pseudo-header field MUST be omitted when translating from an HTTP/1.1 request that has a request target in origin or asterisk form (see [RFC7230], Section 5.3). Clients that generate HTTP/2 requests directly SHOULD use the :authority pseudo-header field instead of the Host header field.
|
211
214
|
if authority = request.authority
|
212
215
|
pseudo_headers << [AUTHORITY, authority]
|
data/lib/async/http/proxy.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2019-
|
4
|
+
# Copyright, 2019-2025, by Samuel Williams.
|
5
5
|
|
6
6
|
require_relative "client"
|
7
7
|
require_relative "endpoint"
|
@@ -82,7 +82,7 @@ module Async
|
|
82
82
|
def connect(&block)
|
83
83
|
input = Body::Writable.new
|
84
84
|
|
85
|
-
response = @client.connect(@address
|
85
|
+
response = @client.connect(authority: @address, headers: @headers, body: input)
|
86
86
|
|
87
87
|
if response.success?
|
88
88
|
pipe = Body::Pipe.new(response.body, input)
|
data/lib/async/http/version.rb
CHANGED
data/license.md
CHANGED
data/readme.md
CHANGED
@@ -16,6 +16,10 @@ Please see the [project documentation](https://socketry.github.io/async-http/) f
|
|
16
16
|
|
17
17
|
Please see the [project releases](https://socketry.github.io/async-http/releases/index) for all releases.
|
18
18
|
|
19
|
+
### v0.87.0
|
20
|
+
|
21
|
+
- [Unify HTTP/1 and HTTP/2 `CONNECT` semantics](https://socketry.github.io/async-http/releases/index#unify-http/1-and-http/2-connect-semantics)
|
22
|
+
|
19
23
|
### v0.86.0
|
20
24
|
|
21
25
|
- Add support for HTTP/2 `NO_RFC7540_PRIORITIES`. See <https://www.rfc-editor.org/rfc/rfc9218.html> for more details.
|
data/releases.md
CHANGED
@@ -1,5 +1,29 @@
|
|
1
1
|
# Releases
|
2
2
|
|
3
|
+
## v0.87.0
|
4
|
+
|
5
|
+
### Unify HTTP/1 and HTTP/2 `CONNECT` semantics
|
6
|
+
|
7
|
+
HTTP/1 has a request line "target" which takes different forms depending on the kind of request. For `CONNECT` requests, the target is the authority (host and port) of the target server, e.g.
|
8
|
+
|
9
|
+
CONNECT example.com:443 HTTP/1.1
|
10
|
+
|
11
|
+
In HTTP/2, the `CONNECT` method uses the `:authority` pseudo-header to specify the target, e.g.
|
12
|
+
|
13
|
+
``` http
|
14
|
+
[HEADERS FRAME]
|
15
|
+
:method: connect
|
16
|
+
:authority: example.com:443
|
17
|
+
```
|
18
|
+
|
19
|
+
In HTTP/1, the `Request#path` attribute was previously used to store the target, and this was incorrectly mapped to the `:path` pseudo-header in HTTP/2. This has been corrected, and the `Request#authority` attribute is now used to store the target for both HTTP/1 and HTTP/2, and mapped accordingly. Thus, to make a `CONNECT` request, you should set the `Request#authority` attribute, e.g.
|
20
|
+
|
21
|
+
``` ruby
|
22
|
+
response = client.connect(authority: "example.com:443")
|
23
|
+
```
|
24
|
+
|
25
|
+
For HTTP/1, the authority is mapped back to the request line target, and for HTTP/2, it is mapped to the `:authority` pseudo-header.
|
26
|
+
|
3
27
|
## v0.86.0
|
4
28
|
|
5
29
|
- Add support for HTTP/2 `NO_RFC7540_PRIORITIES`. See <https://www.rfc-editor.org/rfc/rfc9218.html> for more details.
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: async-http
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.87.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
@@ -26,7 +26,6 @@ authors:
|
|
26
26
|
- Trevor Turk
|
27
27
|
- Viacheslav Koval
|
28
28
|
- dependabot[bot]
|
29
|
-
autorequire:
|
30
29
|
bindir: bin
|
31
30
|
cert_chain:
|
32
31
|
- |
|
@@ -58,7 +57,7 @@ cert_chain:
|
|
58
57
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
59
58
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
60
59
|
-----END CERTIFICATE-----
|
61
|
-
date:
|
60
|
+
date: 2025-01-29 00:00:00.000000000 Z
|
62
61
|
dependencies:
|
63
62
|
- !ruby/object:Gem::Dependency
|
64
63
|
name: async
|
@@ -117,77 +116,75 @@ dependencies:
|
|
117
116
|
- !ruby/object:Gem::Version
|
118
117
|
version: '0.6'
|
119
118
|
- !ruby/object:Gem::Dependency
|
120
|
-
name:
|
119
|
+
name: metrics
|
121
120
|
requirement: !ruby/object:Gem::Requirement
|
122
121
|
requirements:
|
123
122
|
- - "~>"
|
124
123
|
- !ruby/object:Gem::Version
|
125
|
-
version: '0.
|
124
|
+
version: '0.12'
|
126
125
|
type: :runtime
|
127
126
|
prerelease: false
|
128
127
|
version_requirements: !ruby/object:Gem::Requirement
|
129
128
|
requirements:
|
130
129
|
- - "~>"
|
131
130
|
- !ruby/object:Gem::Version
|
132
|
-
version: '0.
|
131
|
+
version: '0.12'
|
133
132
|
- !ruby/object:Gem::Dependency
|
134
|
-
name: protocol-
|
133
|
+
name: protocol-http
|
135
134
|
requirement: !ruby/object:Gem::Requirement
|
136
135
|
requirements:
|
137
|
-
- - "
|
136
|
+
- - "~>"
|
138
137
|
- !ruby/object:Gem::Version
|
139
|
-
version: 0.
|
138
|
+
version: '0.49'
|
140
139
|
type: :runtime
|
141
140
|
prerelease: false
|
142
141
|
version_requirements: !ruby/object:Gem::Requirement
|
143
142
|
requirements:
|
144
|
-
- - "
|
143
|
+
- - "~>"
|
145
144
|
- !ruby/object:Gem::Version
|
146
|
-
version: 0.
|
145
|
+
version: '0.49'
|
147
146
|
- !ruby/object:Gem::Dependency
|
148
|
-
name: protocol-
|
147
|
+
name: protocol-http1
|
149
148
|
requirement: !ruby/object:Gem::Requirement
|
150
149
|
requirements:
|
151
150
|
- - "~>"
|
152
151
|
- !ruby/object:Gem::Version
|
153
|
-
version: '0.
|
152
|
+
version: '0.30'
|
154
153
|
type: :runtime
|
155
154
|
prerelease: false
|
156
155
|
version_requirements: !ruby/object:Gem::Requirement
|
157
156
|
requirements:
|
158
157
|
- - "~>"
|
159
158
|
- !ruby/object:Gem::Version
|
160
|
-
version: '0.
|
159
|
+
version: '0.30'
|
161
160
|
- !ruby/object:Gem::Dependency
|
162
|
-
name:
|
161
|
+
name: protocol-http2
|
163
162
|
requirement: !ruby/object:Gem::Requirement
|
164
163
|
requirements:
|
165
164
|
- - "~>"
|
166
165
|
- !ruby/object:Gem::Version
|
167
|
-
version: '0.
|
166
|
+
version: '0.22'
|
168
167
|
type: :runtime
|
169
168
|
prerelease: false
|
170
169
|
version_requirements: !ruby/object:Gem::Requirement
|
171
170
|
requirements:
|
172
171
|
- - "~>"
|
173
172
|
- !ruby/object:Gem::Version
|
174
|
-
version: '0.
|
173
|
+
version: '0.22'
|
175
174
|
- !ruby/object:Gem::Dependency
|
176
|
-
name:
|
175
|
+
name: traces
|
177
176
|
requirement: !ruby/object:Gem::Requirement
|
178
177
|
requirements:
|
179
178
|
- - "~>"
|
180
179
|
- !ruby/object:Gem::Version
|
181
|
-
version: '0.
|
180
|
+
version: '0.10'
|
182
181
|
type: :runtime
|
183
182
|
prerelease: false
|
184
183
|
version_requirements: !ruby/object:Gem::Requirement
|
185
184
|
requirements:
|
186
185
|
- - "~>"
|
187
186
|
- !ruby/object:Gem::Version
|
188
|
-
version: '0.
|
189
|
-
description:
|
190
|
-
email:
|
187
|
+
version: '0.10'
|
191
188
|
executables: []
|
192
189
|
extensions: []
|
193
190
|
extra_rdoc_files: []
|
@@ -244,7 +241,6 @@ licenses:
|
|
244
241
|
metadata:
|
245
242
|
documentation_uri: https://socketry.github.io/async-http/
|
246
243
|
source_code_uri: https://github.com/socketry/async-http.git
|
247
|
-
post_install_message:
|
248
244
|
rdoc_options: []
|
249
245
|
require_paths:
|
250
246
|
- lib
|
@@ -259,8 +255,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
259
255
|
- !ruby/object:Gem::Version
|
260
256
|
version: '0'
|
261
257
|
requirements: []
|
262
|
-
rubygems_version: 3.
|
263
|
-
signing_key:
|
258
|
+
rubygems_version: 3.6.2
|
264
259
|
specification_version: 4
|
265
260
|
summary: A HTTP client and server library.
|
266
261
|
test_files: []
|
metadata.gz.sig
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
��H��;�w1$O��i�\�q>�������ؕ���5����ʪe��5��P4ǭ;�JmVO��������bC����W��:��W..4ګb��UDw��Kx����&��VYt
|
2
|
+
�1�{��g��\u�w��e����-q�Ɓƃ=B�<i)�Ԝ��0=-Y2Q��x]��s�o[^b��*��`ܼV���yM��-�7�bg{{[�{D ����z�_� �K>0���Og��ץ��9x�)�n�Y]��ow��f 'yD��G3B��ba��TQ���t+`X��'ٔ���`��
|