On Wed, 3 Dec 2025 12:08:33 GMT, EunHyunsu <[email protected]> wrote:

> ### Problem
> 
>   When the HTTP/2 client receives a GOAWAY frame with a non-zero error code, 
> the current implementation discards both the error code and debug data. Users 
> only see generic "Connection closed by peer" errors without any information 
> about why the server terminated the connection.
> 
>   ### Solution
> 
>   Per [RFC 9113 
> §5.4.1](https://www.rfc-editor.org/rfc/rfc9113.html#section-5.4.1), a GOAWAY 
> frame with a non-zero error code indicates a connection error requiring 
> immediate closure. This fix:
> 
>   1. **Distinguishes** graceful shutdown (NO_ERROR) from connection errors
>   2. **Preserves** error code and debug data in exception messages
>   3. **Categorizes** streams based on `lastStreamId`:
>      - Streams with ID > `lastStreamId`: Marked as unprocessed for automatic 
> retry
>      - Streams with ID ≤ `lastStreamId`: Failed with detailed error 
> information
> 
>   ### Changes
> 
>   **Core Implementation** (`Http2Connection.java`):
>   - Modified `handleGoAway()` to check error code and route appropriately
>   - Added `handleGoAwayWithError()` method that:
>     - Extracts error code and debug data from GOAWAY frame
>     - Creates meaningful error messages with error name, hex code, and debug 
> data
>     - Properly categorizes streams for retry or failure
> 
>   **Test Infrastructure**:
>   - `Http2TestServerConnection.sendGoAway(int, int, byte[])`: Supports custom 
> error codes
>   - `Http2TestExchangeImpl.getServerConnection()`: Accessor for test handlers
>   - `GoAwayWithErrorTest`: Verifies proper error propagation
> 
>   ### Example
> 
>   **Before:**
>   IOException: Connection closed by peer
> 
>   **After:**
>   IOException: Received GOAWAY with error code Protocol error (0x1): Invalid 
> HEADERS frame
> 
>   ### Testing
> 
>   - New `GoAwayWithErrorTest` passes
>   - Existing HTTP/2 tests unaffected (NO_ERROR path unchanged)
>   - Backward compatible (no public API changes)

src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java line 
1481:

> 1479:                 // Stream was being processed - fail it with the 
> connection error
> 1480:                 final IOException error = new IOException(errorMsg);
> 1481:                 stream.connectionClosing(error);

Suggestion:

                stream.connectionClosing(cause.getCloseCause());

test/jdk/java/net/httpclient/http2/GoAwayWithErrorTest.java line 173:

> 171:                 System.out.println("Handler: sending 
> GOAWAY(PROTOCOL_ERROR) and closing connection");
> 172: 
> 173:                 impl.getServerConnection().sendGoAway(Integer.MAX_VALUE, 
> PROTOCOL_ERROR, DEBUG_DATA);

Please add a test to verify that the requests above lastStreamId are retried

test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServerConnection.java
 line 283:

> 281:      * @throws IOException if an I/O error occurs
> 282:      */
> 283:     public void sendGoAway(int lastStreamId, int errorCode, byte[] 
> debugData) throws IOException {

please merge this method with the other sendGoAway (make the other one call 
this one?)

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/28632#discussion_r2585342808
PR Review Comment: https://git.openjdk.org/jdk/pull/28632#discussion_r2585689936
PR Review Comment: https://git.openjdk.org/jdk/pull/28632#discussion_r2585370317

Reply via email to