Ocelot: support SignalR

Created on 4 May 2018  路  12Comments  路  Source: ThreeMammals/Ocelot

Expected Behavior / New Feature

SignalR websockets can be successfully rerouted with Ocelot

Actual Behavior / Motivation for New Feature

Fails on the handshake due to inability to map websockets and xhr requests for the same upstream url

Steps to Reproduce the Problem

  1. Clone https://github.com/cristianiorga/OcelotSignalRTest
  2. Start DummySignalR
  3. Start APIGatewayTest

  4. Start DummySignalRClient
    Expected: logs dummy test message to console
    Actual: cannot enstablish connection

  5. Open DummySignalRWebClient.html in browser
    Expected: logs dummy test message to browser console
    Actual: cannot establish connection

Browser network log:
error

Detailed error:
detailed error

How a successfull handshake looks like:
signalr handshake

Specifications

  • Version: 6.0.0
  • Platform: Windows
  • Subsystem: Windows 10 Enterprise 64 bit

Notes:
In order to have a successful handshake with SignalR not only the websocket has to be rerouted.

enhancement help wanted large effort merged

Most helpful comment

Hi, sorry to ask as it may be a stupid question but i don't really get how it fix the original issue "Fails on the handshake due to inability to map websockets and xhr requests for the same upstream url".
For the http(s) negociate part, should be still add an http(s) DownstreamScheme plus a ws DownstreamScheme for the same route ?

All 12 comments

@cristianiorga Thanks for your interest in the project! 馃槃 Ocelot doesn't currently support SignalR.

I do not have time to follow everything! Do you know if SignalR has an official release for .net core 2.0? Last time I checked it did not :(

I think this would be a useful feature so I will keep this issue open!

@TomPallister SignalR will be part of the .NET Core 2.1 release coming mid-2018. You can read more about that at https://blogs.msdn.microsoft.com/webdev/2018/02/02/asp-net-core-2-1-roadmap/ , https://blogs.msdn.microsoft.com/webdev/2018/02/27/asp-net-core-2-1-0-preview1-getting-started-with-signalr/ and https://github.com/aspnet/SignalR/milestones
Currently there is a .NET Core 2.1 Developer preview for SignalR and is the one I used in reporting this issue.

I believe that this would be a great feature for Ocelot and I would be willing to help where I can if you can plan and coordinate the work.

I am building a mobile app using Ionic, when I test it on mobile signalR and ocelot work perfectly, the only problem i have is when testing on the browser. It brings an error i believe could be as result of cors but i can't solve it. here is the error

Failed to load resource: the server responded with a status of 405 (Method Not Allowed)
?ionicplatform=android&http://localhost:8100/ionic-lab&http://localhost:8100/ionic-lab&http://localhost:8100/ionic-lab#/products:1 Failed to load http://myIp/NotificationHub/negotiate: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access. The response had HTTP status code 405.

my configuration is as follows
{
"DownstreamPathTemplate": "/NotificationHub/negotiate",
"UpstreamPathTemplate": "/NotificationHub/negotiate",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "servicename",
"Port": 80
}
],
"UpstreamHttpMethod": ["Options", "Post" ]
},

{
  "DownstreamPathTemplate": "/NotificationHub",
  "UpstreamPathTemplate": "/NotificationHub",
  "DownstreamScheme": "http",
  "DownstreamHostAndPorts": [
    {
      "Host": "servicename",
      "Port": 80
    }
  ],
  "UpstreamHttpMethod": [ "Options", "Get", "Post" ]

},

public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder
.WithOrigins("http://localhost:8100")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
);
});
services.AddMvc();
}

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        app.UseCors("CorsPolicy");
        app.UseMvc();
    }

@ogomaemmanuel it is probably the same problem as @cristianiorga mentioned to open this ticket. I have not had time to look into the issue yet I'm afraid. I cannot give a time frame either. Maybe I will have time in the next few months. If you want to help out I would suggest forking the Ocelot repository and debugging the code to see whats going on. I'm more than happy to accept PRs and give advice.

@cristianiorga APIGatewayTest project will be changed.
ocelot.json
{ "ReRoutes": [ { "DownstreamPathTemplate": "/dummy", "DownstreamScheme": "ws", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 50000 } ], "UpstreamPathTemplate": "/api/dummy" }, { "DownstreamPathTemplate": "/dummy/negotiate", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 50000 } ], "UpstreamPathTemplate": "/api/dummy/negotiate" } ], "GlobalConfiguration": { "BaseUrl": "http://localhost", "AdministrationPath": "/administration", "RequestIdKey": "OcRequestId" } }

and Program.cs
.Configure(app => { app.UseWebSockets(); app.UseOcelot().Wait(); })
you can try. I get the same result as DummySignalR

from #524

Expected Behavior / New Feature
We are using ocelot with the feature websockets. We are using Signalr Core and trying to forward it to the correct server. With that we are using headers on the requests.

The headers disappear once it goes through ocelot. Is this on purpose?
We verified that the headers will be send to the signalr server when it doen't use ocelot.

Config:

"ReRoutes": [{
"DownstreamPathTemplate": "/{catchAll}",
"DownstreamScheme": "ws",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5000
}
],
"UpstreamPathTemplate": "/gateway/{catchAll}",
"UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE", "OPTIONS" ]
}]
Actual Behavior / Motivation for New Feature
The headers are being forwarded with the websockets

Steps to Reproduce the Problem
Start a signalr core server
Configure ocelot as described in http://ocelot.readthedocs.io/en/latest/features/websockets.html
Connect a client throuh ocelot and send a header with it.
Check the headers received on the server
Specifications
Version: 8.0.2
Platform: Windows 10
Subsystem: Microsoft.AspNetCore.SignalR.Client 1.0.1

I created a pull request to add headers to the request.

With the following templates it works:

Do not run it in IISExpress or install the websockets feature in the IIS features

Target framework: 2.1.2
Microsoft.AspNetCore.SignalR.Client 1.0.2
Ocelot develop with my pull-request

 public class Program
    {
        public static void Main(string[] args)
        {
            var webHost = WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .UseIISIntegration()
                .Build();

            webHost.Run();
        }
    }

    public class Startup : IStartup
    {
        public IConfiguration Configuration { get; }

        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("ocelot.json")
                .AddEnvironmentVariables();

            Configuration = builder.Build();
        }

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddOcelot(Configuration);
            return services.BuildServiceProvider();
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseWebSockets();
            app.UseOcelot().Wait();
        }
    }

ocelot.json

{
  "ReRoutes": [
    {
      "DownstreamPathTemplate": "/{catchAll}",
      "DownstreamScheme": "ws",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 50000
        }
      ],
      "UpstreamPathTemplate": "/gateway/{catchAll}",
      "UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE", "OPTIONS" ]
    }
 ]
}

Just released in 8.0.7

Hi, sorry to ask as it may be a stupid question but i don't really get how it fix the original issue "Fails on the handshake due to inability to map websockets and xhr requests for the same upstream url".
For the http(s) negociate part, should be still add an http(s) DownstreamScheme plus a ws DownstreamScheme for the same route ?

image

hi, there's no typo here?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Marusyk picture Marusyk  路  3Comments

mogliang picture mogliang  路  3Comments

secret-agent-B picture secret-agent-B  路  4Comments

yangzhongke picture yangzhongke  路  6Comments

ruimaciel picture ruimaciel  路  3Comments