From 944f738b093170e0bca3eb85a02786dddd390078 Mon Sep 17 00:00:00 2001 From: Brennan Date: Wed, 10 Jan 2024 13:26:42 -0800 Subject: [PATCH 1/2] Fix closing SignalR Websocket connection on server close --- .../src/Internal/HttpConnectionDispatcher.cs | 8 +++++ .../test/HttpConnectionDispatcherTests.cs | 29 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionDispatcher.cs b/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionDispatcher.cs index 7f97e1e29761..c47953e4eebb 100644 --- a/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionDispatcher.cs +++ b/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionDispatcher.cs @@ -168,6 +168,14 @@ private async Task ExecuteAsync(HttpContext context, ConnectionDelegate connecti { transport = HttpTransportType.WebSockets; connection = await GetOrCreateConnectionAsync(context, options); + + if (connection is not null) + { + Log.EstablishedConnection(_logger); + + // Allow the reads to be canceled + connection.Cancellation ??= new CancellationTokenSource(); + } } else { diff --git a/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs b/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs index 558a974d1830..1c274068d2b9 100644 --- a/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs +++ b/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs @@ -2842,6 +2842,35 @@ public async Task WebSocketConnectionClosingTriggersConnectionClosedToken() } } + [Fact] + public async Task ServerClosingClosesWebSocketConnection() + { + using (StartVerifiableLog()) + { + var manager = CreateConnectionManager(LoggerFactory); + var connection = manager.CreateConnection(); + + var dispatcher = CreateDispatcher(manager, LoggerFactory); + var services = new ServiceCollection(); + services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + SetTransport(context, HttpTransportType.WebSockets); + + var builder = new ConnectionBuilder(services.BuildServiceProvider()); + builder.UseConnectionHandler(); + var app = builder.Build(); + var options = new HttpConnectionDispatcherOptions(); + options.WebSockets.CloseTimeout = TimeSpan.FromSeconds(1); + + _ = dispatcher.ExecuteAsync(context, options, app); + + // "close" server, since we're not using a server in these tests we just simulate what would be called when the server closes + await connection.DisposeAsync().DefaultTimeout(); + + await connection.ConnectionClosed.WaitForCancellationAsync().DefaultTimeout(); + } + } + public class CustomHttpRequestLifetimeFeature : IHttpRequestLifetimeFeature { public CancellationToken RequestAborted { get; set; } From 2426ad6565615c70d07e73370ed800310f37bb82 Mon Sep 17 00:00:00 2001 From: Brennan Date: Thu, 11 Jan 2024 14:16:11 -0800 Subject: [PATCH 2/2] fb --- .../Http.Connections/test/HttpConnectionDispatcherTests.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs b/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs index 1c274068d2b9..3389cebfdd9b 100644 --- a/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs +++ b/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs @@ -2862,12 +2862,14 @@ public async Task ServerClosingClosesWebSocketConnection() var options = new HttpConnectionDispatcherOptions(); options.WebSockets.CloseTimeout = TimeSpan.FromSeconds(1); - _ = dispatcher.ExecuteAsync(context, options, app); + var executeTask = dispatcher.ExecuteAsync(context, options, app); // "close" server, since we're not using a server in these tests we just simulate what would be called when the server closes await connection.DisposeAsync().DefaultTimeout(); await connection.ConnectionClosed.WaitForCancellationAsync().DefaultTimeout(); + + await executeTask.DefaultTimeout(); } }