-
Notifications
You must be signed in to change notification settings - Fork 106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add check for h2.connection.ConnectionState.CLOSED
in AsyncHTTP2Connection.is_available
#679
Conversation
…nnection.is_available`
You can see how this changes things in my reproduction at https://github.com/madkinsz/httpcore-h2-closed Without this change, when the NGINX proxy is reset a With this change, the first error is raised but subsequent requests succeed. |
Looks like a good start, thanks! 💛
Hrm, yes it's not immediately obvious what the most graceful approach is here but let's start at the start. It might(?) be worth rounding out this PR a bit with a test case in:
(I can help out if needed.) A test there wouldn't really be sufficient because all we can demonstrate at that level is "if we send these frames, then the connection interface will behave like X", but it'd be something. |
Thanks for the response Tom! I'll take a swing at the test and ping you when it's added or if I run into any problems. |
We can add a test like def test_http2_connection_closed_unexpectedly():
origin = Origin(b"https", b"example.com", 443)
stream = MockStream(
[
hyperframe.frame.SettingsFrame().serialize(),
]
)
with HTTP2Connection(origin=origin, stream=stream, keepalive_expiry=5.0) as conn:
conn._h2_state.close_connection()
with pytest.raises(ProtocolError):
conn.request("GET", "https://example.com/")
assert not conn.is_available() If you want to add something that doesn't reach into the underlying |
Maybe a test where the server sends one response and then sends a |
@tomchristie yep that works to reproduce the issue, added in 00f98c5 |
Looking good! I verified locally that without the implementation change, the test fails with the connection stuck in an We can improve on this further by ensuring that requests after a GOAWAY frame get a * Ideally we'd also allow existing streams to complete after a GOAWAY frame, so long as they are |
Great that makes sense to me! Let's merge this and I'll open a follow up that raises the Unfortunate that there's no traction in that |
Addresses encode/httpx#2112 and PrefectHQ/prefect#7442
The issue here is that the underlying h2 connection can reached a CLOSED state without the httpcore connection being marked as CLOSED. This causes subsequent requests to continue to reuse the closed connection but they will always fail with a protocol error. By adding a check to
is_available
, we'll avoid using this bad connection after the first request fails.It seems likely that we could check the h2 connection state somewhere else as well i.e. before handling every request. I'd appreciate some guidance from other maintainers.
Ideally we'd avoid sending any events when there's a closed connection which would avoid the
LocalProtocolError
in the first place, but first let's avoid holding closed connections in the pool.