Ocelot not passing websockets to microservice

浪子不回头ぞ 提交于 2021-01-27 21:02:36

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!