问题
I'm trying to connect to SignalR hubs using Ocelot as proxy. SignalR is plugged in microservice that gateway passing through websockets traffic. Negotation via HTTP request is executed successfully, but further communication via websockets seems to be lost. I don't have an idea what is going on, especially that communication with the same configuration works perfectly when Azure SignalR on another environment is used. Below I present my configuration for gateway:
ocelot.json
{
"DownstreamPathTemplate": "/{anyHub}/negotiate",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "communication",
"Port": 80
}
],
"UpstreamHttpMethod": [ "POST" ],
"UpstreamPathTemplate": "/{anyHub}/negotiate",
"ReRouteIsCaseSensitive": false,
"AuthenticationOptions": {
"AuthenticationProviderKey": "Bearer",
"AllowedScopes": []
},
"DelegatingHandlers": [
"IdentityInQuery"
]
},
{
"DownstreamPathTemplate": "/{anyHub}",
"ReRouteIsCaseSensitive": false,
"DownstreamScheme": "ws",
"DownstreamHostAndPorts": [
{
"Host": "communication",
"Port": 80
}
],
"UpstreamPathTemplate": "/{anyHub}",
"UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE", "OPTIONS" ]
},
Part of gateway's Program.cs
.Configure(async app =>
{
await app
.UseCors(cors =>
{
cors.AllowAnyHeader()
.AllowAnyMethod()
.SetIsOriginAllowed(x => true)
.AllowCredentials();
}).UseOcelot();
if (turnOnWebsockets)
app.UseWebSockets();
Particular microservice collection extensions:
public static ISignalRBuilder AddSignalRConfiguration(this IServiceCollection services, bool isDevelopment)
{
var newServices = services.AddSignalR();
if (!isDevelopment) newServices.AddAzureSignalR(Config.AzureSignalROptions.ConnectionString);
return newServices;
}
public static IServiceCollection AddSignalRCors(this IServiceCollection services)
{
services.AddCors(options => options.AddPolicy("CorsPolicy",
builder =>
{
builder
.AllowAnyHeader()
.AllowAnyMethod()
.SetIsOriginAllowed(x => true)
.AllowCredentials();
}));
return services;
}
Part of IApplicationBuilder extension in particular microservice:
public static IApplicationBuilder AddSignalR(this IApplicationBuilder app, bool isDevelopment)
{
app.UseRouting()
.UseCors("CorsPolicy");
if (isDevelopment)
{
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<UserHub>("/userHub");
endpoints.MapHub<ConversationHub>("/conversationHub");
endpoints.MapHub<DiscussionHub>("/discussionHub");
});
}
....
return app;
}
How can I use websockets with Ocelot and SignalR? The only transport method which gateway currently is able to communicate with SignalR is long polling, but for me it is not fully satisfactioning. Thank you in advance for any help!
回答1:
Middleware order matters.
if (turnOnWebsockets)
app.UseWebSockets();
Needs to happen before the UseOcelot
call.
Example
Something like this should work for you
.Configure(async app =>
{
app.UseCors(cors =>
{
cors.AllowAnyHeader()
.AllowAnyMethod()
.SetIsOriginAllowed(x => true)
.AllowCredentials();
});
if (turnOnWebsockets)
app.UseWebSockets();
app.UseOcelot().Wait();
Note
AFAIK async Configure
is not supported as of now in ASP.NET Core. Using .Wait()
is generally frowned upon but in this case it is needed, and is the way encouraged by the Ocelot documentation as well.
来源:https://stackoverflow.com/questions/63472028/ocelot-not-passing-websockets-to-microservice