ThreeMammals / Ocelot

.NET API Gateway
https://www.nuget.org/packages/Ocelot
MIT License
8.31k stars 1.63k forks source link

Routing with different Upstream Hosts #932

Open DrVaskee opened 5 years ago

DrVaskee commented 5 years ago

Expected Behavior / New Feature

The API-Gateway is listening for multiple hosts. For a few endpoints the routing is based on the host. For example the frontend for each host is different. Though the business logic is exactly the same. So the configuration has entries which contain no upstreamhost and entries with upstream host.

I expect that the endpoints without upstream host get routet reagardless of the host.

Actual Behavior / Motivation for New Feature

What actually happens is that for some endpoints without a upstreamhost the route is not catched and the default route is returned.

I can work around that fix if i add an entry in the config file for each host. I didn't had to do that workaround in older versions. The logs also do not show a connection error and return the default route as backup. They return it because of the only match.

Steps to Reproduce the Problem

  1. Create an ocelot webservice with multiple route configurations. Some with upstream host, some without
  2. Try to connect to one without upstream host
  3. Some of thoose routes work however
  4. I didn't found the exact way to reproduce

See for example my configurationfile, where the first entry ("/api/{version}/tariff/{url}") is always routed to the default entry. routerconfig.zip

Specifications

DrVaskee commented 5 years ago

I checked out the code and looked around a little. I found that routes that are with a upstreamHost are priorizied. Maybe the function should consider the Priority Value from the config.

In the DownstreamRouteFinder i got two "applicableReRoutes". The one that i need and the default one. Because the default one has a host assigned it always picks the default route over the better matching one.

https://github.com/ThreeMammals/Ocelot/blob/f4803c24bf9e9ca3929c78ca8eb23401e3c31c23/src/Ocelot/DownstreamRouteFinder/Finder/DownstreamRouteFinder.cs#L36-L42

I don't know why this is, but do you have a solution for this one?

Fabman08 commented 4 years ago

Hi, I've the same problem. I also add Priority to the route before digging into the source code and finding the same code reported by @DrVaskee . I think Priority property should have a higher "priority" than UpstreamHost property, isn't it? Thank you

raman-m commented 7 months ago

Does this issue still persist in the latest version?

raman-m commented 7 months ago

@DrVaskee commented on Jun 18, 2019:

I don't know why this is, but do you have a solution for this one?

We would expect a solution and fix rather from you than from other developers who don't understand your scenario.


What I see now, is this config ```json { "Routes": [ { "DownstreamPathTemplate": "/api/{version}/tariff/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "tariffwebshopservice.wvg", "Port": 80 } ], "UpstreamPathTemplate": "/api/{version}/tariff/{url}", "UpstreamHttpMethod": [ "POST", "GET" ], "Priority": 10 }, { "DownstreamPathTemplate": "/api/{version}/user/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "userwebshopservice.wvg", "Port": 80 } ], "UpstreamPathTemplate": "/api/{version}/user/{url}", "UpstreamHttpMethod": [ "POST", "PUT", "GET", "DELETE" ], "Priority": 10 }, { "DownstreamPathTemplate": "/api/{version}/sales/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "saleswebshopservice.wvg", "Port": 80 } ], "UpstreamPathTemplate": "/api/{version}/sales/{url}", "UpstreamHttpMethod": [ "POST", "PUT", "GET", "DELETE" ], "Priority": 10 }, { "DownstreamPathTemplate": "/api/{version}/payment/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "paymentservice.wvg", "Port": 80 } ], "UpstreamPathTemplate": "/api/{version}/payment/{url}", "UpstreamHttpMethod": [ "POST", "PUT", "GET", "DELETE" ], "Priority": 10 }, { "DownstreamPathTemplate": "/api/{version}/orderfulfillment/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "orderfulfillmentwebshopservice.wvg", "Port": 80 } ], "UpstreamPathTemplate": "/api/{version}/orderfulfillment/{url}", "UpstreamHttpMethod": [ "GET" ], "Priority": 10 }, { "DownstreamPathTemplate": "/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "frontend-rvm.wvg", "Port": 80 } ], "UpstreamPathTemplate": "/{url}", "UpstreamHttpMethod": [ "GET" ], "UpstreamHost": "webshop.rvm.wvg.prod.ufho.de", "Priority": 5 }, { "DownstreamPathTemplate": "/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "frontend-rlg.wvg", "Port": 80 } ], "UpstreamPathTemplate": "/{url}", "UpstreamHttpMethod": [ "GET" ], "UpstreamHost": "webshop.rlg.wvg.prod.ufho.de", "Priority": 5 }, { "DownstreamPathTemplate": "/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "frontend-vku.wvg", "Port": 80 } ], "UpstreamPathTemplate": "/{url}", "UpstreamHttpMethod": [ "GET" ], "UpstreamHost": "webshop.vku.wvg.prod.ufho.de", "Priority": 5 }, { "DownstreamPathTemplate": "/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "frontend-rvm.wvg", "Port": 80 } ], "UpstreamPathTemplate": "/{url}", "UpstreamHttpMethod": [ "GET" ], "UpstreamHost": "wvg.prod.ufho.de", "Priority": 5 } ] } ```

I see manipulation by Priority and all templates are Catch-All ones which has the lowest priority 0. See our docs: Routing Priority From the second side, Upstream Host is defined in each route. And, I would say, I see misconfiguration issue rather than Ocelot bug...

For your better understanding of your routes and priorities, I recommend you to:

Finally, assigning highest priority to Catch-All routes is wrong because they have lowest priority, see docs.

raman-m commented 7 months ago

@DrVaskee

I found that routes that are with a UpstreamHost are prioritized.

Correct! Upstream Host routes has "highest" implicit priority.


Maybe the function should consider the Priority Value from the config.

Not correct! Priority is considered for routes without UpstreamHost :grey_exclamation::grey_exclamation::grey_exclamation: This is the current logic. Imagine Priority has been applied for all routes then UpstreamHost routes will be ignored incidentally which is totally wrong!

raman-m commented 7 months ago

@DrVaskee

In the DownstreamRouteFinder i got two "applicableReRoutes". The one that i need and the default one. Because the default one has a host assigned it always picks the default route over the better matching one. https://github.com/ThreeMammals/Ocelot/blob/f4803c24bf9e9ca3929c78ca8eb23401e3c31c23/src/Ocelot/DownstreamRouteFinder/Finder/DownstreamRouteFinder.cs#L36-L42 I don't know why this is, but do you have a solution for this one?

As I said above, this is current implementation! So, we search for routes with UpstreamHost first. If No, return routes without UpstreamHost. It looks like a life hack, but this is current logic.

Do you think we still have an issue?

raman-m commented 7 months ago

@Fabman08 commented on Feb 18, 2020

I think Priority property should have a higher "priority" than UpstreamHost property, isn't it?

I don't think so... UpstreamHost is the filter of Host header. _urlMatcher does this :point_right: https://github.com/ThreeMammals/Ocelot/blob/f4803c24bf9e9ca3929c78ca8eb23401e3c31c23/src/Ocelot/DownstreamRouteFinder/Finder/DownstreamRouteFinder.cs#L28 So, my understanding

How it is implemented, I am not sure. But if you still see an issue, let us know once again... I assume that current logic is not ideal.