From fe786f9d94a4f319ddb332f6b11ca437ef011d21 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Nov 2025 21:26:17 +0000 Subject: [PATCH 1/3] Initial plan From 13c9ace7e957ebc805eba2993a7eea726d3cf9c1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Nov 2025 21:30:30 +0000 Subject: [PATCH 2/3] Add detailed documentation for HTTP/3 graceful shutdown and GOAWAY frames Co-authored-by: marten-seemann <1478487+marten-seemann@users.noreply.github.com> --- content/docs/http3/client.md | 14 ++++++++++++++ content/docs/http3/server.md | 14 +++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/content/docs/http3/client.md b/content/docs/http3/client.md index fce057f..0eaf229 100644 --- a/content/docs/http3/client.md +++ b/content/docs/http3/client.md @@ -76,6 +76,20 @@ The code snippet shows all the knobs that need to be turned to send a request in 1. TLS session resumption must be enabled by configuring a `tls.ClientSessionCache` on the `tls.Config`. 2. The request method needs to be set to `http3.MethodGet0RTT`. +## Handling Server Shutdown (GOAWAY) + +When a server initiates a graceful shutdown, it sends a [GOAWAY frame](https://datatracker.ietf.org/doc/html/rfc9114#section-5.2) to inform clients that it will not accept new requests. The `http3.Transport` handles GOAWAY frames automatically: + +1. When a GOAWAY frame is received, the transport stops sending new requests on that connection. +2. Requests that are already in-flight continue to completion normally. +3. New requests automatically trigger establishment of a new connection to the server. + +{{< callout type="info" >}} + The `http3.Transport` manages GOAWAY handling transparently. Applications using `http.Client` with `http3.Transport` don't need to implement special logic for server shutdown scenarios - the transport will automatically retry requests on new connections as needed. +{{< /callout >}} + +If a request is rejected by the server after a GOAWAY (with the `H3_REQUEST_REJECTED` error code), the transport treats this as a retriable error. The `http.Client` can be configured to automatically retry such requests by using a custom `http.RoundTripper` wrapper or by handling the error at the application level. + ## 📝 Future Work {#future-work} * Support for zstd Content Encoding: [#4100](https://github.com/quic-go/quic-go/issues/4100) diff --git a/content/docs/http3/server.md b/content/docs/http3/server.md index 440ccf9..4018d8e 100644 --- a/content/docs/http3/server.md +++ b/content/docs/http3/server.md @@ -126,10 +126,22 @@ defer cancel() server.Shutdown(ctx) ``` -On the wire, graceful shutdown is signaled by sending a GOAWAY frame. This tells clients that the server will not accept any new requests. Requests received after sending the GOAWAY frame are rejected (using the `H3_REQUEST_REJECTED` error code). Existing connections are not closed; clients are expected to close them after they finish processing their requests. +### How GOAWAY Works + +On the wire, graceful shutdown is signaled by sending a [GOAWAY frame](https://datatracker.ietf.org/doc/html/rfc9114#section-5.2). The GOAWAY frame informs the client that the server will not accept any new requests. It contains a stream ID that indicates the highest request stream ID that the server might have processed. Clients can use this information to determine which requests were potentially processed and which were not. + +When a server sends a GOAWAY frame: +1. The server stops accepting new HTTP/3 connections. +2. The server rejects any new requests received on existing connections after the GOAWAY frame was sent (using the `H3_REQUEST_REJECTED` error code). +3. Existing requests that were initiated before the GOAWAY are allowed to complete normally. +4. The QUIC connection itself remains open; clients are expected to close it once they've finished processing their requests. `Shutdown` returns when all existing connections have been closed, or when the context is canceled. In that case, all remaining active QUIC connections are closed, which abruptly terminates the remaining requests. +{{< callout type="info" >}} + Unlike HTTP/2, HTTP/3 uses a GOAWAY frame to perform graceful shutdown, but does not require immediate connection closure. The underlying QUIC connection can remain open to allow in-flight requests to complete. +{{< /callout >}} + ## 📝 Future Work From 1d65f512a8fb0e9d6473879e1404d3ff1e52a757 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Nov 2025 21:31:52 +0000 Subject: [PATCH 3/3] Address code review feedback: clarify HTTP/2 comparison and automatic retry behavior Co-authored-by: marten-seemann <1478487+marten-seemann@users.noreply.github.com> --- content/docs/http3/client.md | 2 +- content/docs/http3/server.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/content/docs/http3/client.md b/content/docs/http3/client.md index 0eaf229..5c56b06 100644 --- a/content/docs/http3/client.md +++ b/content/docs/http3/client.md @@ -88,7 +88,7 @@ When a server initiates a graceful shutdown, it sends a [GOAWAY frame](https://d The `http3.Transport` manages GOAWAY handling transparently. Applications using `http.Client` with `http3.Transport` don't need to implement special logic for server shutdown scenarios - the transport will automatically retry requests on new connections as needed. {{< /callout >}} -If a request is rejected by the server after a GOAWAY (with the `H3_REQUEST_REJECTED` error code), the transport treats this as a retriable error. The `http.Client` can be configured to automatically retry such requests by using a custom `http.RoundTripper` wrapper or by handling the error at the application level. +When a request is rejected by the server after a GOAWAY (with the `H3_REQUEST_REJECTED` error code), the `http3.Transport` automatically retries it on a new connection. This retry behavior is built into the transport and requires no additional configuration. ## 📝 Future Work {#future-work} diff --git a/content/docs/http3/server.md b/content/docs/http3/server.md index 4018d8e..cbff9bd 100644 --- a/content/docs/http3/server.md +++ b/content/docs/http3/server.md @@ -139,7 +139,7 @@ When a server sends a GOAWAY frame: `Shutdown` returns when all existing connections have been closed, or when the context is canceled. In that case, all remaining active QUIC connections are closed, which abruptly terminates the remaining requests. {{< callout type="info" >}} - Unlike HTTP/2, HTTP/3 uses a GOAWAY frame to perform graceful shutdown, but does not require immediate connection closure. The underlying QUIC connection can remain open to allow in-flight requests to complete. + HTTP/3's GOAWAY behavior is similar to HTTP/2, but operates over QUIC connections instead of TCP connections, allowing the underlying transport to remain open for in-flight requests. {{< /callout >}}