From 753603bbc787b7ec23cba4757bf48e09d546ab35 Mon Sep 17 00:00:00 2001 From: ManickaP Date: Tue, 8 Jul 2025 13:45:41 +0200 Subject: [PATCH 1/2] Replace HandleRequestAsync with read request, send response to avoid GO_AWAY. --- ...ClientHandlerTest.MaxResponseHeadersLength.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.MaxResponseHeadersLength.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.MaxResponseHeadersLength.cs index fd9460726f5888..0358fa2bb4ff7c 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.MaxResponseHeadersLength.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.MaxResponseHeadersLength.cs @@ -90,18 +90,23 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => }, async server => { + var connection = await server.EstablishGenericConnectionAsync(); try { - await server.HandleRequestAsync(headers: new[] { new HttpHeaderData("Foo", new string('a', handler.MaxResponseHeadersLength * 1024)) }); + // Do not use HandleRequestAsync. It sends GO_AWAY before sending the response, making client close the connection right after the stream abort. + // QUIC is based on UDP and packet ordering is not preserved, so the connection close might race with the expected stream error in H/3 case. + await connection.ReadRequestDataAsync(); + await connection.SendResponseAsync(headers: new[] { new HttpHeaderData("Foo", new string('a', handler.MaxResponseHeadersLength * 1024)) }); } // Client can respond by closing/aborting the underlying stream while we are still sending the headers, ignore these exceptions catch (IOException ex) when (ex.InnerException is SocketException se && se.SocketErrorCode == SocketError.Shutdown) { } #if !WINHTTPHANDLER_TEST - catch (QuicException ex) when (ex.QuicError == QuicError.StreamAborted && ex.ApplicationErrorCode == Http3ExcessiveLoad) {} + catch (QuicException ex) when (ex.QuicError == QuicError.StreamAborted && ex.ApplicationErrorCode == Http3ExcessiveLoad) { } #endif finally { semaphore.Release(); + await connection.DisposeAsync(); } }); } @@ -148,9 +153,13 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => headers.Add(new HttpHeaderData($"Custom-{i}", new string('a', 480))); } + var connection = await server.EstablishGenericConnectionAsync(); try { - await server.HandleRequestAsync(headers: headers); + // Do not use HandleRequestAsync. It sends GO_AWAY before sending the response, making client close the connection right after the stream abort. + // QUIC is based on UDP and packet ordering is not preserved, so the connection close might race with the expected stream error in H/3 case. + await connection.ReadRequestDataAsync(); + await connection.SendResponseAsync(headers: new[] { new HttpHeaderData("Foo", new string('a', handler.MaxResponseHeadersLength * 1024)) }); } // Client can respond by closing/aborting the underlying stream while we are still sending the headers, ignore these exceptions catch (IOException ex) when (ex.InnerException is SocketException se && se.SocketErrorCode == SocketError.Shutdown) { } @@ -160,6 +169,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => finally { semaphore.Release(); + await connection.DisposeAsync(); } }); } From d6924c528f058c866a82a670e0c160f453b676b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20P=C3=ADchov=C3=A1?= <11718369+ManickaP@users.noreply.github.com> Date: Tue, 8 Jul 2025 15:08:49 +0200 Subject: [PATCH 2/2] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Net/Http/HttpClientHandlerTest.MaxResponseHeadersLength.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.MaxResponseHeadersLength.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.MaxResponseHeadersLength.cs index 0358fa2bb4ff7c..0e8cfc240ceb94 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.MaxResponseHeadersLength.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.MaxResponseHeadersLength.cs @@ -159,7 +159,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => // Do not use HandleRequestAsync. It sends GO_AWAY before sending the response, making client close the connection right after the stream abort. // QUIC is based on UDP and packet ordering is not preserved, so the connection close might race with the expected stream error in H/3 case. await connection.ReadRequestDataAsync(); - await connection.SendResponseAsync(headers: new[] { new HttpHeaderData("Foo", new string('a', handler.MaxResponseHeadersLength * 1024)) }); + await connection.SendResponseAsync(headers: headers); } // Client can respond by closing/aborting the underlying stream while we are still sending the headers, ignore these exceptions catch (IOException ex) when (ex.InnerException is SocketException se && se.SocketErrorCode == SocketError.Shutdown) { }