Skip to content

http-netty: reset cancelled HTTP/2 streams whose request body is still writing - #3678

Draft
bryce-anderson wants to merge 1 commit into
apple:mainfrom
bryce-anderson:h2-cancel-reset-5e766195
Draft

bryce-anderson wants to merge 1 commit into
apple:mainfrom
bryce-anderson:h2-cancel-reset-5e766195

Conversation

@bryce-anderson

Copy link
Copy Markdown
Contributor

Motivation

An HTTP/2 client request cancelled after its response finished but before its request body did was never reset. The server kept waiting for the rest of the body, and the stream held a concurrent-stream slot on both peers until the server reset it or the connection closed. Enough of these made the client open extra connections. The client's close-on-cancel skipped HTTP/2 because it once ran on the parent connection, where closing failed every stream (#1307), but it now runs on each stream.

Modifications

  • The client's close-on-cancel now applies to HTTP/2 too, where it closes only the cancelled stream.

Result

A cancelled HTTP/2 request no longer leaves its stream open.

@bryce-anderson

Copy link
Copy Markdown
Contributor Author

This should be sequenced after #3676 since technically this can expand the number of cases where the ST stream counter is less than the netty stream counter.

@bryce-anderson
bryce-anderson force-pushed the h2-cancel-reset-5e766195 branch 2 times, most recently from b329c8e to 60b31c9 Compare October 6, 2026 17:43
…l writing

#### Motivation

An HTTP/2 client request cancelled after its response finished but before its
request body did was never reset. A gRPC client does this without any user
cancel when a server rejects a client-streaming or bidirectional call with a
Trailers-Only response while the request stream is still open. The server kept
waiting for the rest of the body, and the stream held a concurrent-stream slot
on both peers until the server reset it or the connection closed. Enough of
these made the client open extra connections. The client's close-on-cancel
skipped HTTP/2 because it once ran on the parent connection, where closing
failed every stream (apple#1307), but it now runs on each stream.

#### Modifications

- The client's close-on-cancel now applies to HTTP/2 too, where it closes only
  the cancelled stream.

#### Result

Cancelling an HTTP/2 request whose request body is still streaming resets its
stream.

Behavior change: an HTTP/2 server now receives RST_STREAM(CANCEL) for these
streams, including after it has sent its full response. A server that counts
such resets against a rapid-reset limit, as the ServiceTalk server does, can
reach that limit sooner, for example when it rejects many streaming gRPC calls
on one connection. If that happens, raise the server's limit on received resets.
@bryce-anderson
bryce-anderson force-pushed the h2-cancel-reset-5e766195 branch from 60b31c9 to 6289389 Compare October 6, 2026 18:16

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant