async-http 0.94.2 → 0.94.3
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/lib/async/http/body/hijack.rb +17 -0
- data/lib/async/http/body/pipe.rb +3 -0
- data/lib/async/http/body.rb +3 -0
- data/lib/async/http/client.rb +16 -4
- data/lib/async/http/endpoint.rb +33 -0
- data/lib/async/http/internet.rb +7 -0
- data/lib/async/http/middleware/location_redirector.rb +9 -0
- data/lib/async/http/mock/endpoint.rb +10 -0
- data/lib/async/http/protocol/configurable.rb +15 -0
- data/lib/async/http/protocol/http1/client.rb +3 -0
- data/lib/async/http/protocol/http1/connection.rb +13 -0
- data/lib/async/http/protocol/http1/finishable.rb +9 -0
- data/lib/async/http/protocol/http1/request.rb +22 -0
- data/lib/async/http/protocol/http1/response.rb +10 -0
- data/lib/async/http/protocol/http1/server.rb +7 -0
- data/lib/async/http/protocol/http1.rb +1 -0
- data/lib/async/http/protocol/http10.rb +1 -0
- data/lib/async/http/protocol/http11.rb +1 -0
- data/lib/async/http/protocol/http2/client.rb +10 -0
- data/lib/async/http/protocol/http2/connection.rb +16 -0
- data/lib/async/http/protocol/http2/input.rb +5 -0
- data/lib/async/http/protocol/http2/output.rb +13 -0
- data/lib/async/http/protocol/http2/request.rb +17 -0
- data/lib/async/http/protocol/http2/response.rb +23 -0
- data/lib/async/http/protocol/http2/server.rb +16 -0
- data/lib/async/http/protocol/http2/stream.rb +19 -0
- data/lib/async/http/protocol/http2.rb +1 -0
- data/lib/async/http/protocol/https.rb +7 -0
- data/lib/async/http/protocol/request.rb +9 -1
- data/lib/async/http/protocol/response.rb +6 -1
- data/lib/async/http/proxy.rb +12 -0
- data/lib/async/http/server.rb +14 -0
- data/lib/async/http/statistics.rb +19 -0
- data/lib/async/http/version.rb +3 -1
- data/lib/async/http.rb +0 -3
- data/readme.md +20 -4
- data/releases.md +4 -0
- data.tar.gz.sig +0 -0
- metadata +3 -3
- metadata.gz.sig +0 -0
data/lib/async/http/proxy.rb
CHANGED
|
@@ -13,7 +13,10 @@ module Async
|
|
|
13
13
|
# Wraps a client, address and headers required to initiate a connectio to a remote host using the CONNECT verb.
|
|
14
14
|
# Behaves like a TCP endpoint for the purposes of connecting to a remote host.
|
|
15
15
|
class Proxy
|
|
16
|
+
# Raised when a CONNECT tunnel through a proxy cannot be established.
|
|
16
17
|
class ConnectFailure < StandardError
|
|
18
|
+
# Initialize the failure with the unsuccessful response.
|
|
19
|
+
# @parameter response [Protocol::HTTP::Response] The failed response from the proxy.
|
|
17
20
|
def initialize(response)
|
|
18
21
|
super "Failed to connect: #{response.status}"
|
|
19
22
|
@response = response
|
|
@@ -22,7 +25,12 @@ module Async
|
|
|
22
25
|
attr :response
|
|
23
26
|
end
|
|
24
27
|
|
|
28
|
+
# Extends {Async::HTTP::Client} with proxy capabilities.
|
|
25
29
|
module Client
|
|
30
|
+
# Create a proxy instance for the given endpoint.
|
|
31
|
+
# @parameter endpoint [Endpoint] The target endpoint to tunnel to.
|
|
32
|
+
# @parameter headers [Hash | Nil] Optional headers to send with the CONNECT request.
|
|
33
|
+
# @returns [Proxy] A proxy instance for establishing tunnels.
|
|
26
34
|
def proxy(endpoint, headers = nil)
|
|
27
35
|
Proxy.new(self, endpoint.authority(false), headers)
|
|
28
36
|
end
|
|
@@ -34,6 +42,10 @@ module Async
|
|
|
34
42
|
return self.class.new(proxy.wrap_endpoint(endpoint))
|
|
35
43
|
end
|
|
36
44
|
|
|
45
|
+
# Create an endpoint that connects via this proxy.
|
|
46
|
+
# @parameter endpoint [Endpoint] The target endpoint.
|
|
47
|
+
# @parameter headers [Hash | Nil] Optional headers for the CONNECT request.
|
|
48
|
+
# @returns [Endpoint] An endpoint that tunnels through the proxy.
|
|
37
49
|
def proxied_endpoint(endpoint, headers = nil)
|
|
38
50
|
proxy = self.proxy(endpoint, headers)
|
|
39
51
|
|
data/lib/async/http/server.rb
CHANGED
|
@@ -12,11 +12,20 @@ require_relative "protocol"
|
|
|
12
12
|
|
|
13
13
|
module Async
|
|
14
14
|
module HTTP
|
|
15
|
+
# An HTTP server that accepts connections on a specific endpoint and dispatches requests to an application handler.
|
|
15
16
|
class Server < ::Protocol::HTTP::Middleware
|
|
17
|
+
# Create a server using a block as the application handler.
|
|
18
|
+
# @parameter arguments [Array] Arguments to pass to {initialize}.
|
|
19
|
+
# @parameter options [Hash] Options to pass to {initialize}.
|
|
16
20
|
def self.for(*arguments, **options, &block)
|
|
17
21
|
self.new(block, *arguments, **options)
|
|
18
22
|
end
|
|
19
23
|
|
|
24
|
+
# Initialize the server with an application handler and endpoint.
|
|
25
|
+
# @parameter app [Protocol::HTTP::Middleware] The Rack-compatible application to serve.
|
|
26
|
+
# @parameter endpoint [Endpoint] The endpoint to bind to.
|
|
27
|
+
# @parameter protocol [Protocol] The protocol to use for incoming connections.
|
|
28
|
+
# @parameter scheme [String] The default scheme to set on requests.
|
|
20
29
|
def initialize(app, endpoint, protocol: endpoint.protocol, scheme: endpoint.scheme)
|
|
21
30
|
super(app)
|
|
22
31
|
|
|
@@ -25,6 +34,7 @@ module Async
|
|
|
25
34
|
@scheme = scheme
|
|
26
35
|
end
|
|
27
36
|
|
|
37
|
+
# @returns [Hash] A JSON-compatible representation of this server.
|
|
28
38
|
def as_json(...)
|
|
29
39
|
{
|
|
30
40
|
endpoint: @endpoint.to_s,
|
|
@@ -33,6 +43,7 @@ module Async
|
|
|
33
43
|
}
|
|
34
44
|
end
|
|
35
45
|
|
|
46
|
+
# @returns [String] A JSON string representation of this server.
|
|
36
47
|
def to_json(...)
|
|
37
48
|
as_json.to_json(...)
|
|
38
49
|
end
|
|
@@ -41,6 +52,9 @@ module Async
|
|
|
41
52
|
attr :protocol
|
|
42
53
|
attr :scheme
|
|
43
54
|
|
|
55
|
+
# Accept an incoming connection and process requests.
|
|
56
|
+
# @parameter peer [IO] The connected peer.
|
|
57
|
+
# @parameter address [Addrinfo] The remote address of the peer.
|
|
44
58
|
def accept(peer, address, task: Task.current)
|
|
45
59
|
connection = @protocol.server(peer)
|
|
46
60
|
|
|
@@ -9,15 +9,23 @@ require "async/clock"
|
|
|
9
9
|
|
|
10
10
|
module Async
|
|
11
11
|
module HTTP
|
|
12
|
+
# Tracks response timing statistics including time to first byte and total duration.
|
|
12
13
|
class Statistics
|
|
14
|
+
# Start tracking statistics from the current time.
|
|
15
|
+
# @returns [Statistics] A new statistics instance.
|
|
13
16
|
def self.start
|
|
14
17
|
self.new(Clock.now)
|
|
15
18
|
end
|
|
16
19
|
|
|
20
|
+
# Initialize the statistics tracker.
|
|
21
|
+
# @parameter start_time [Float] The start time for measuring durations.
|
|
17
22
|
def initialize(start_time)
|
|
18
23
|
@start_time = start_time
|
|
19
24
|
end
|
|
20
25
|
|
|
26
|
+
# Wrap a response body with a statistics-collecting wrapper.
|
|
27
|
+
# @parameter response [Protocol::HTTP::Response] The response to wrap.
|
|
28
|
+
# @returns [Protocol::HTTP::Response] The wrapped response.
|
|
21
29
|
def wrap(response, &block)
|
|
22
30
|
if response and response.body
|
|
23
31
|
response.body = Body::Statistics.new(@start_time, response.body, block)
|
|
@@ -30,6 +38,10 @@ module Async
|
|
|
30
38
|
module Body
|
|
31
39
|
# Invokes a callback once the body has finished reading.
|
|
32
40
|
class Statistics < ::Protocol::HTTP::Body::Wrapper
|
|
41
|
+
# Initialize the statistics body wrapper.
|
|
42
|
+
# @parameter start_time [Float] The start time for measuring durations.
|
|
43
|
+
# @parameter body [Protocol::HTTP::Body::Readable] The body to wrap.
|
|
44
|
+
# @parameter callback [Proc] A callback to invoke when the body is closed.
|
|
33
45
|
def initialize(start_time, body, callback)
|
|
34
46
|
super(body)
|
|
35
47
|
|
|
@@ -48,24 +60,29 @@ module Async
|
|
|
48
60
|
|
|
49
61
|
attr :sent
|
|
50
62
|
|
|
63
|
+
# @returns [Float | Nil] The total duration from start to close, in seconds.
|
|
51
64
|
def total_duration
|
|
52
65
|
if @end_time
|
|
53
66
|
@end_time - @start_time
|
|
54
67
|
end
|
|
55
68
|
end
|
|
56
69
|
|
|
70
|
+
# @returns [Float | Nil] The duration from start until the first chunk was read, in seconds.
|
|
57
71
|
def first_chunk_duration
|
|
58
72
|
if @first_chunk_time
|
|
59
73
|
@first_chunk_time - @start_time
|
|
60
74
|
end
|
|
61
75
|
end
|
|
62
76
|
|
|
77
|
+
# Close the body and record the end time.
|
|
63
78
|
def close(error = nil)
|
|
64
79
|
complete_statistics(error)
|
|
65
80
|
|
|
66
81
|
super
|
|
67
82
|
end
|
|
68
83
|
|
|
84
|
+
# Read the next chunk from the body, tracking timing and bytes sent.
|
|
85
|
+
# @returns [String | Nil] The next chunk of data.
|
|
69
86
|
def read
|
|
70
87
|
chunk = super
|
|
71
88
|
|
|
@@ -78,6 +95,7 @@ module Async
|
|
|
78
95
|
return chunk
|
|
79
96
|
end
|
|
80
97
|
|
|
98
|
+
# @returns [String] A human-readable summary of the statistics.
|
|
81
99
|
def to_s
|
|
82
100
|
parts = ["sent #{@sent} bytes"]
|
|
83
101
|
|
|
@@ -92,6 +110,7 @@ module Async
|
|
|
92
110
|
return parts.join("; ")
|
|
93
111
|
end
|
|
94
112
|
|
|
113
|
+
# @returns [String] A detailed representation including the wrapped body.
|
|
95
114
|
def inspect
|
|
96
115
|
"#{super} | \#<#{self.class} #{self.to_s}>"
|
|
97
116
|
end
|
data/lib/async/http/version.rb
CHANGED
data/lib/async/http.rb
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.94.3
|
|
20
|
+
|
|
21
|
+
- Fix response body leak in HTTP/2 server when stream is reset before `send_response` completes (e.g. client-side gRPC cancellation). The response body's `close` was never called, leaking any resources tied to body lifecycle (such as `rack.response_finished` callbacks and utilization metrics).
|
|
22
|
+
|
|
19
23
|
### v0.94.1
|
|
20
24
|
|
|
21
25
|
- Fix `defer_stop` usage in `HTTP1::Server`, improving server graceful shutdown behavior.
|
|
@@ -52,10 +56,6 @@ Please see the [project releases](https://socketry.github.io/async-http/releases
|
|
|
52
56
|
|
|
53
57
|
- Add support for HTTP/2 `NO_RFC7540_PRIORITIES`. See <https://www.rfc-editor.org/rfc/rfc9218.html> for more details.
|
|
54
58
|
|
|
55
|
-
### v0.84.0
|
|
56
|
-
|
|
57
|
-
- Minor consistency fixes to `Async::HTTP::Internet` singleton methods.
|
|
58
|
-
|
|
59
59
|
## See Also
|
|
60
60
|
|
|
61
61
|
- [benchmark-http](https://github.com/socketry/benchmark-http) — A benchmarking tool to report on web server concurrency.
|
|
@@ -74,6 +74,22 @@ We welcome contributions to this project.
|
|
|
74
74
|
4. Push to the branch (`git push origin my-new-feature`).
|
|
75
75
|
5. Create new Pull Request.
|
|
76
76
|
|
|
77
|
+
### Running Tests
|
|
78
|
+
|
|
79
|
+
To run the test suite:
|
|
80
|
+
|
|
81
|
+
``` shell
|
|
82
|
+
bundle exec sus
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Making Releases
|
|
86
|
+
|
|
87
|
+
To make a new release:
|
|
88
|
+
|
|
89
|
+
``` shell
|
|
90
|
+
bundle exec bake gem:release:patch # or minor or major
|
|
91
|
+
```
|
|
92
|
+
|
|
77
93
|
### Developer Certificate of Origin
|
|
78
94
|
|
|
79
95
|
In order to protect users of this project, we require all contributors to comply with the [Developer Certificate of Origin](https://developercertificate.org/). This ensures that all contributions are properly licensed and attributed.
|
data/releases.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Releases
|
|
2
2
|
|
|
3
|
+
## v0.94.3
|
|
4
|
+
|
|
5
|
+
- Fix response body leak in HTTP/2 server when stream is reset before `send_response` completes (e.g. client-side gRPC cancellation). The response body's `close` was never called, leaking any resources tied to body lifecycle (such as `rack.response_finished` callbacks and utilization metrics).
|
|
6
|
+
|
|
3
7
|
## v0.94.1
|
|
4
8
|
|
|
5
9
|
- Fix `defer_stop` usage in `HTTP1::Server`, improving server graceful shutdown behavior.
|
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.94.
|
|
4
|
+
version: 0.94.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Samuel Williams
|
|
@@ -277,14 +277,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
277
277
|
requirements:
|
|
278
278
|
- - ">="
|
|
279
279
|
- !ruby/object:Gem::Version
|
|
280
|
-
version: '3.
|
|
280
|
+
version: '3.3'
|
|
281
281
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
282
282
|
requirements:
|
|
283
283
|
- - ">="
|
|
284
284
|
- !ruby/object:Gem::Version
|
|
285
285
|
version: '0'
|
|
286
286
|
requirements: []
|
|
287
|
-
rubygems_version: 4.0.
|
|
287
|
+
rubygems_version: 4.0.6
|
|
288
288
|
specification_version: 4
|
|
289
289
|
summary: A HTTP client and server library.
|
|
290
290
|
test_files: []
|
metadata.gz.sig
CHANGED
|
Binary file
|