Reputation: 2157
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
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
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
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
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
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
{ }
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
Reputation: 161
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/websockets?view=aspnetcore-7.0
Upvotes: 16
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:
Upvotes: 9