ASP.NET Core中HTTPS下静态文件与WebSocket共存问题排查
ASP.NET Core单服务器同时提供HTTPS静态文件与WebSocket连接的405错误问题
问题背景
使用C#的WebApplication搭建ASP.NET Core服务器,需求是同时提供静态文件服务与HTTPS协议的WebSocket连接。HTTP环境下使用ws://连接完全正常,页面加载、WebSocket通信、重连均无问题,但切换为HTTPS(wss://与https://)后出现异常。
基础测试代码
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();
WebSocket处理方法仅实现消息回显逻辑,静态文件包含简单HTML页面与图片,页面脚本会循环尝试建立WebSocket连接并发送消息。
错误现象
HTTPS环境下首次启动服务器并加载页面时,静态文件可正常获取,但WebSocket连接触发服务器405错误,日志如下:
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.7369ms info: Microsoft.AspNetCore.Server.Kestrel[32] Connection id "0HN410OGAJS3S", Request id "0HN410OGAJS3S:00000005": the application completed without reading the entire request body.
WebSocket处理方法从未被调用。但保持脚本运行并重启服务器后,WebSocket即可正常连接。
当前临时方案与疑问
目前采用两个不同端口的WebApplication分别处理静态文件与WebSocket的方案可正常运行,但怀疑HTTPS下浏览器加载静态文件的长连接无法升级为WebSocket连接。需确认:
- 该猜测是否正确
- 当前配置是否存在问题
- 是否必须使用双服务器,或能否通过单服务器实现需求
补充WebSocket处理方法代码
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); }
内容的提问来源于stack exchange,提问作者Mars
相关产品推荐
相关产品推荐

