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

1

ASP.NET Core 2.1 running behind IIS 8.5

SignalR doesn't seem to negotiate a Sub-Protocol when connecting and fails to complete the connection. Messages sent from the client to the server are never received.

I can't configure the site to serve from Kestrel directly as this is a shared server. Changing the transport to long-polling works. I have tried disabling HTTPS/HSTS redirection.

Attached are the logs from the client and the server:

Client logs:

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>

Server logs:

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.
asp.net-core
iis-8
asp.net-core-signalr
asked on Stack Overflow Jan 15, 2019 by Sam

1 Answer

1

I found the problem!

We had a custom IIS module that injected server name + request timing as an HTTP header and this was causing SignalR to fail. (The module was probably just blindly injecting its header, without respect to Websockets)

answered on Stack Overflow Jan 22, 2019 by Sam

User contributions licensed under CC BY-SA 3.0