WebSockets 在部署到 Prod 时不能与 SignalR Core 一起使用

WebSockets don't work with SignalR Core when deployed to Prod

ASP.NET Core 2.1 运行 落后于 IIS 8.5

SignalR 在连接时似乎没有协商子协议,因此无法完成连接。永远不会收到从客户端发送到服务器的消息。

我无法将站点配置为直接从 Kestrel 提供服务,因为这是共享服务器。 将传输更改为长轮询工作。 我试过禁用 HTTPS/HSTS 重定向。

附上来自客户端和服务器的日志:

客户端日志:

Information: Normalizing 'hubs/screen' to 'https://<url>/hubs/screen'.
Utils.ts:173 Information: WebSocket connected to ws://<url>/hubs/screen?id=
...
Error: Connection disconnected with error 'Error: Server timeout elapsed without receiving a message from the server.'.<id>

服务器日志:

dbug: Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionManager[1]
      New connection <id> created.
dbug: Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionDispatcher[10]
      Sending negotiation response.
dbug: Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionDispatcher[4]
      Establishing new connection.
dbug: Microsoft.AspNetCore.SignalR.HubConnectionHandler[5]
      OnConnectedAsync started.
dbug: Microsoft.AspNetCore.Http.Connections.Internal.Transports.WebSocketsTransport[1]
      Socket opened using Sub-Protocol: '(null)'.
dbug: Microsoft.AspNetCore.Http.Connections.Internal.Transports.WebSocketsTransport[14]
      Socket connection closed prematurely.
System.Net.WebSockets.WebSocketException (0x80004005): The remote party closed the WebSocket connection without completing the close handshake. ---> System.Net.WebSockets.WebSocketException (0x80004005): The remote party closed the WebSocket connection without completing the close handshake.
   at System.Net.WebSockets.ManagedWebSocket.ThrowIfEOFUnexpected(Boolean throwOnPrematureClosure)
   at System.Net.WebSockets.ManagedWebSocket.EnsureBufferContainsAsync(Int32 minimumRequiredBytes, Boolean throwOnPrematureClosure)
   at System.Net.WebSockets.ManagedWebSocket.ReceiveAsyncPrivate[TWebSocketReceiveResultGetter,TWebSocketReceiveResult](Memory`1 payloadBuffer, CancellationToken cancellationToken, TWebSocketReceiveResultGetter resultGetter)
   at System.Net.WebSockets.ManagedWebSocket.ReceiveAsyncPrivate[TWebSocketReceiveResultGetter,TWebSocketReceiveResult](Memory`1 payloadBuffer, CancellationToken cancellationToken, TWebSocketReceiveResultGetter resultGetter)
   at System.Net.WebSockets.WebSocket.ReceiveAsync(Memory`1 buffer, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Internal.Transports.WebSocketsTransport.StartReceiving(WebSocket socket)
fail: Microsoft.AspNetCore.SignalR.HubConnectionContext[5]
      Failed connection handshake.
dbug: Microsoft.AspNetCore.Http.Connections.Internal.Transports.WebSocketsTransport[4]
      Waiting for the application to finish sending data.
dbug: Microsoft.AspNetCore.Http.Connections.Internal.Transports.WebSocketsTransport[2]
      Socket closed.

我找到问题了!

我们有一个自定义 IIS 模块,它以 HTTP header 的形式注入服务器名称 + 请求时间,这导致 SignalR 失败。 (该模块可能只是盲目地注入它的 header,而不考虑 Websockets)