Quantcast
Channel: Active questions tagged https - Stack Overflow
Viewing all articles
Browse latest Browse all 1529

Serving files and WebSocket via ASP.NET Core and HTTPS

$
0
0

I have an issue with setting up an ASP.NET Core web server in C# using WebApplication, which is supposed to serve static files and handle WebSocket connections via HTTPS. Let me first establish what I'm working with. My basic test code looks like this:

var builder = WebApplication.CreateBuilder();builder.Services.Configure<KestrelServerOptions>(options =>{    var cert = new X509Certificate2("cert.pfx", "password");    options.Listen(IPAddress.Any, 80);    options.Listen(IPAddress.Any, 443, listenOptions =>    {        listenOptions.UseHttps(cert);    });});var app = builder.Build();app.UseWebSockets();app.MapGet("/ws", HandleWebSocket);app.UseDefaultFiles();app.UseStaticFiles();app.RunAsync();

The ws handler method does nothing but echo incoming messages and should not matter. The static files meanwhile consist of a very simple HTML file and a couple images. The index.html contains a simple script that establishes a connection via WebSocket and sends messages in a loop, which, as mentioned before, get echoed by the server. Also, if the script is not connected, it will try to establish a connection in a loop until it gets it.

Now, if I run this on HTTP and connect with ws://, this works entirely without issues. I can load the page, it connects, messages are sent and received, all good. I can also keep the script running and restart the server, and the script will automatically reconnect and keep going.

The problem is that it does not work properly via HTTPS. All I do is change ws:// to wss:// and change the URL from http:// to https://. As a result, when I start the server and then load the page, I get the files no problem, but when the script tries to establish a connection, I get the following error on the server and the WebSocket handler is never called.

info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]      Executing endpoint '405 HTTP Method Not Supported'info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]      Executed endpoint '405 HTTP Method Not Supported'info: Microsoft.AspNetCore.Hosting.Diagnostics[2]      Request finished HTTP/2 CONNECT https://127.0.0.1/ws - 405 0 - 2.7369msinfo: Microsoft.AspNetCore.Server.Kestrel[32]      Connection id "0HN410OGAJS3S", Request id "0HN410OGAJS3S:00000005": the application completed without reading the entire request body.

However, when I load the page, let the script running, and then restart the server, the script is able to connect fine with HTTPS, with no changes at all. My workaround is to create two WebApplications on different ports, one serving the files and one being a dedicated WebSocket server, and this works fine with both of them using HTTPS.

Based on this behavior, I have the suspicion that the connection the browser establishes, and presumably keeps open, to load the static files, can't be upgraded to a WebSocket connection after serving files if it's using HTTPS, which is why this is working fine under HTTP. But I don't know if this is actually the case, and I have yet to find anything about this. Also, I tested it in Chrome and Firefox, same issue.

That's why I finally came here, and I'm hoping someone can shed some light on this. Is my suspicion right? Or is my setup somehow faulty? Do I need two servers to do this via HTTPS? Or can I accomplish it with one?

Any answers or theories would be much appreciated.

Edit

I'll include my handler method after all, to demonstrate that there's nothing special going on.

private static async Task HandleWebSocket(HttpContext context){    if (!context.WebSockets.IsWebSocketRequest)    {        context.Response.StatusCode = StatusCodes.Status400BadRequest;        await context.Response.WriteAsync("Expected a WebSocket request");        return;    }    var socket = await context.WebSockets.AcceptWebSocketAsync();    var buffer = new byte[1024];    var result = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);    while (socket.State == WebSocketState.Open)    {        var data = Encoding.UTF8.GetString(buffer, 0, result.Count);        Console.WriteLine("Received: " + data);        var response = Encoding.UTF8.GetBytes("Echo - " + data);        await socket.SendAsync(new ArraySegment<byte>(response), result.MessageType, result.EndOfMessage, CancellationToken.None);        result = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);    }    await socket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);}

Viewing all articles
Browse latest Browse all 1529

Trending Articles