Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/async/http/protocol/http2/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ def call(request)
# The remote peer has sent a GOAWAY frame, so it will not process any new streams on this connection. The request has not been sent yet, so it is safe to retry it on a new connection, even if it is not idempotent. This is checked first, because a connection with no streams left to drain is closed by the GOAWAY itself.
raise ::Protocol::HTTP::RefusedError, "Connection is going away!" if self.goaway_received?

raise ::Protocol::HTTP2::Error, "Connection closed!" if self.closed?
# The connection can close after being acquired from the pool. No stream has been created yet, so the request has not been written and is safe to retry.
raise ::Protocol::HTTP::RefusedError, "Connection closed!" if self.closed?

response = create_response
write_request(response, request)
Expand Down
1 change: 1 addition & 0 deletions releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased

- Requests assigned to an HTTP/2 connection which has already closed are refused before being written, allowing them to be retried safely.
- HTTP/2 connections which received a graceful `GOAWAY` are removed from availability immediately, but remain in the pool until the server has finished answering the streams it accepted. The connection is closed after its final user releases it, so those requests no longer fail with `EOFError: Connection closed with N active stream(s)!`.

## v0.101.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,17 @@
expect(client_connection).to be(:closed?)
end.wait
end

it "refuses a request when the connection is already closed" do
Async do
client_connection = Async::HTTP::Protocol::HTTP2::Client.new(client_stream)
client_connection.open!
client_connection.close

expect do
client_connection.call(Protocol::HTTP::Request["POST", "/", {}, ["Hello"]])
end.to raise_exception(Protocol::HTTP::RefusedError)
end.wait
end
end
end
Loading