From da1127057cd766ec72316dee1ffcb11aed77904b Mon Sep 17 00:00:00 2001 From: Blake Matthes Date: Fri, 10 Oct 2025 08:07:34 -0500 Subject: [PATCH] refactor(wrapper): changes to allow both controller and app to connect via wss:// --- lstWrapper/Program.cs | 99 +++++++++++++++++++++++++++++-------------- lstWrapper/web.config | 2 +- 2 files changed, 69 insertions(+), 32 deletions(-) diff --git a/lstWrapper/Program.cs b/lstWrapper/Program.cs index 666d918..b129481 100644 --- a/lstWrapper/Program.cs +++ b/lstWrapper/Program.cs @@ -97,45 +97,82 @@ app.Run(async (HttpContext context) => } // Handle WebSocket requests - if (context.WebSockets.IsWebSocketRequest) + // if (context.WebSockets.IsWebSocketRequest) + // { + // try + // { + // var backendUri = new UriBuilder(backendWsBase) + // { + // Path = context.Request.Path, + // Query = context.Request.QueryString.ToString() + // }.Uri; + + // using var backendSocket = new ClientWebSocket(); + + // // Forward incoming headers + // foreach (var header in context.Request.Headers) + // { + // try { backendSocket.Options.SetRequestHeader(header.Key, header.Value); } + // catch { /* ignore headers WS client doesn't like */ } + // } + + // await backendSocket.ConnectAsync(backendUri, context.RequestAborted); + + // using var frontendSocket = await context.WebSockets.AcceptWebSocketAsync(); + // var cts = new CancellationTokenSource(); + + // var forwardToBackend = ForwardWebSocketAsync(frontendSocket, backendSocket, cts.Token); + // var forwardToFrontend = ForwardWebSocketAsync(backendSocket, frontendSocket, cts.Token); + + // await Task.WhenAny(forwardToBackend, forwardToFrontend); + // cts.Cancel(); + // } + // catch (Exception ex) + // { + // LogToFile($"WebSocket proxy error: {ex.Message}"); + // context.Response.StatusCode = (int)HttpStatusCode.BadGateway; + // await context.Response.WriteAsync($"WebSocket proxy error: {ex.Message}"); + // } + // return; + // } + +if (context.WebSockets.IsWebSocketRequest) +{ + try { - try + // Accept the incoming client WebSocket + using var frontendSocket = await context.WebSockets.AcceptWebSocketAsync(); + + // Build the backend WebSocket URI + var backendUri = new UriBuilder(backendWsBase) { - var backendUri = new UriBuilder(backendWsBase) - { - Path = context.Request.Path, - Query = context.Request.QueryString.ToString() - }.Uri; + Path = context.Request.Path, + Query = context.Request.QueryString.ToString() + }.Uri; - using var backendSocket = new ClientWebSocket(); + // Connect to the Node.js backend + using var backendSocket = new ClientWebSocket(); + await backendSocket.ConnectAsync(backendUri, context.RequestAborted); - // Forward incoming headers - foreach (var header in context.Request.Headers) - { - try { backendSocket.Options.SetRequestHeader(header.Key, header.Value); } - catch { /* ignore headers WS client doesn't like */ } - } + // Forward frames both ways until one side closes + var cts = new CancellationTokenSource(); + var forwardToBackend = ForwardWebSocketAsync(frontendSocket, backendSocket, cts.Token); + var forwardToFrontend = ForwardWebSocketAsync(backendSocket, frontendSocket, cts.Token); - await backendSocket.ConnectAsync(backendUri, context.RequestAborted); + await Task.WhenAny(forwardToBackend, forwardToFrontend); - using var frontendSocket = await context.WebSockets.AcceptWebSocketAsync(); - var cts = new CancellationTokenSource(); - - var forwardToBackend = ForwardWebSocketAsync(frontendSocket, backendSocket, cts.Token); - var forwardToFrontend = ForwardWebSocketAsync(backendSocket, frontendSocket, cts.Token); - - await Task.WhenAny(forwardToBackend, forwardToFrontend); - cts.Cancel(); - } - catch (Exception ex) - { - LogToFile($"WebSocket proxy error: {ex.Message}"); - context.Response.StatusCode = (int)HttpStatusCode.BadGateway; - await context.Response.WriteAsync($"WebSocket proxy error: {ex.Message}"); - } - return; + // Cancel the other direction once one side closes + cts.Cancel(); + } + catch (Exception ex) + { + LogToFile($"WebSocket proxy error: {ex.Message}"); + context.Response.StatusCode = (int)HttpStatusCode.BadGateway; + await context.Response.WriteAsync($"WebSocket proxy error: {ex.Message}"); } + return; +} // Otherwise: normal HTTP request var client = context.RequestServices.GetRequiredService().CreateClient(); var targetUri = backendHttpBase + context.Request.Path + context.Request.QueryString; diff --git a/lstWrapper/web.config b/lstWrapper/web.config index 2a0c2a2..cbc2cfe 100644 --- a/lstWrapper/web.config +++ b/lstWrapper/web.config @@ -24,6 +24,6 @@ arguments=".\lstWrapper.dll" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" - hostingModel="inprocess" /> + hostingModel="outofprocess" /> \ No newline at end of file