M K
M K

Reputation: 2157

Failed to start the connection: Error: WebSocket failed to connect

Error: Failed to start the connection: Error: WebSocket failed to connect. The connection could not be found on the server, either the endpoint may not be a SignalR endpoint, the connection ID is not present on the server, or there is a proxy blocking WebSockets. If you have multiple servers check that sticky sessions are enabled.

WebSocketTransport.js:49 WebSocket connection to 'ws://xxxxxx/production/web-services/hubs/spreadhub' failed:

Angular.ts

 ngOnInit(): void {

      // For signalR Hub connection
      this.connection  = new HubConnectionBuilder()  
      .withUrl('http://xxx.xxx.com/production/web-services/hubs/spreadhub', {  // localhost from **AspNetCore3.1 service**
        skipNegotiation: true,
        transport: signalR.HttpTransportType.WebSockets
      })  
      .build();

        this.connection.on('dataReceived', (data: string) => {
          var model = JSON.parse(data);

      });
  
      this.connection.start().then(() => { // to start the server
             console.log('server connected!!!');
         }).catch(err => console.log(err));
  }

Upvotes: 18

Views: 68898

Answers (7)

Karson Jo
Karson Jo

Reputation: 1702

In my case it's just because I'm not authorized. My hub needs authorization, but I wasn't logged into the site when I tried connecting, so no cookie was sent, and then I got this error.

My hub is protected by nginx reverse proxy. I don't know if it's nginx that makes the error so counterintuitive. This error lists a number of possible problems, but the only thing it doesn't state is an authorization error.

Anyway, if anyone else encounters the same error and has tried everything else, make sure your credentials are valid.

Upvotes: 0

Umair Sarfraz
Umair Sarfraz

Reputation: 31

This issue was caused by program restrictions on utilizing JWT with WebSockets/ServerSentEvents. Solution to this problem

.AddJwtBearer(configureOptions =>
        {
            configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
            configureOptions.TokenValidationParameters = tokenValidationParameters;
            configureOptions.SaveToken = true;
            configureOptions.Events = new JwtBearerEvents
            {
                OnMessageReceived = context =>
                {
                    var accessToken = context.Request.Query["access_token"];
                    var path = context.HttpContext.Request.Path;
                    if (!string.IsNullOrEmpty(accessToken)
                        && path.StartsWithSegments("/hubs/spreadhub"))
                    {
                        context.Token = accessToken;
                    }
                    return Task.CompletedTask;
                }
            };

Upvotes: 3

Eugene Ihnatsyeu
Eugene Ihnatsyeu

Reputation: 1585

If you use createProxyMiddleware don't forget to include ws: true:

const appProxy = createProxyMiddleware(context, {
    target: 'https://localhost:7288',
    secure: false,
    ws: true
});

I used Visual Studio's templates to generate ASP.NET Core + React application, it automatically included createProxyMiddleware inside setupProxy.js file

Upvotes: 1

Ilya Chernomordik
Ilya Chernomordik

Reputation: 30195

We have figured out there is one more case for this exception if one uses negotiate with a redirect url (as e.g. common with Azure SignalR Service).

If it takes few seconds between the call to the negotiate url and the redirect url returned by negotiate, we get this/similar error message. The reason I assume is that Azure SignalR Service does not allow for a long time window after backend communication for the client to connect.

The reason why it did take few seconds even though it should connect at once was for us that javascript thread switched to do some heavy updates of DOM and did not execute the next call right away.

Upvotes: 1

knoxgon
knoxgon

Reputation: 1243

There have been few cases I've got this error with no further details of the reason.

I could find some solutions to some of the problems I encountered by digging around.

  • Excluding app.UseHttpsRedirection() in the server side of SignalR (C#). (Beware that this is not an appropriate solution in production.) This is often needed in your development environment.

  • Invalid/expired access token. The AuthenticationSchemes needed to be defined in the Authorize attribute in the Hub class.

code:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class HubBase : Hub
{ }
  • Sending the token by accessTokenFactory in the client side.

code:

const connection = new signalR.HubConnectionBuilder()
    .withUrl("http://localhost:5001/hub", {
      skipNegotiation: true,
      transport: signalR.HttpTransportType.WebSockets,
      //Adding this line
      accessTokenFactory: async () => { return this.token}
    })
    .build();

this.token is the token that you generate/fetch and send with the request.

Upvotes: 3

Ha Phan
Ha Phan

Reputation: 161

  1. Navigate to Control Panel > Programs > Programs and Features > Turn Windows features on or off (left side of the screen).
  2. Open the following nodes: Internet Information Services > World Wide Web Services > Application Development Features.
  3. Select the WebSocket Protocol feature. Select OK.

enter image description here

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/websockets?view=aspnetcore-7.0

Upvotes: 16

Kiril1512
Kiril1512

Reputation: 3621

You don't need to specify the full url, just the hub you want to connect to... Assuming your hub name is spreadhub you just need:

this.connection  = new HubConnectionBuilder()  
    .withUrl('https://localhost:5001/spreadhub', {  // localhost from **AspNetCore3.1 service**
    skipNegotiation: true,
    transport: signalR.HttpTransportType.WebSockets
    })  
    .build();

On the server, if deployed to azure, don't forget to turn on websockets like:

Configuration

Upvotes: 9

Related Questions