I am using ASP.NET Microservices plus a separate Ocelot API Gateway which serves for authentication/ authorization and rerouting.
This is my config file:
{
"Routes": [
// *** User API ***
{
"UpstreamPathTemplate": "/User/{id}",
"UpstreamHttpMethod": [ "Get"],
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7268
}
],
"DownstreamPathTemplate": "/api/User/{id}",
"DownstreamHttpMethod": "Get",
"AuthenticationOptions": {
"AuthenticationProviderKey": "Bearer",
"AllowedScopes": [
"Cart.API",
"Catalogue.API",
"Identity.API",
"offline_access"
]
},
"RouteClaimsRequirement": {
"Administrator": "true"
}
},
{
"UpstreamPathTemplate": "/User/{id}",
"UpstreamHttpMethod": [ "Put" ],
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7268
}
],
"DownstreamPathTemplate": "/api/User/{id}",
"DownstreamHttpMethod": "Put",
"AuthenticationOptions": {
"AuthenticationProviderKey": "Bearer",
"AllowedScopes": [
"Cart.API",
"Catalogue.API",
"Identity.API",
"offline_access"
]
},
"RouteClaimsRequirement": {
"Administrator": "true"
}
},
{
"UpstreamPathTemplate": "/User/{id}",
"UpstreamHttpMethod": [ "Delete" ],
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7268
}
],
"DownstreamPathTemplate": "/api/User/{id}",
"DownstreamHttpMethod": "Delete",
"AuthenticationOptions": {
"AuthenticationProviderKey": "Bearer",
"AllowedScopes": [
"Cart.API",
"Catalogue.API",
"Identity.API",
"offline_access"
]
},
"RouteClaimsRequirement": {
"Administrator": "true"
}
},
//edit,get logged user
{
"UpstreamPathTemplate": "/User/LoggedUser",
"UpstreamHttpMethod": [ "Put" ],
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7268
}
],
"DownstreamPathTemplate": "/api/User/LoggedUser",
"DownstreamHttpMethod": "Put",
"AuthenticationOptions": {
"AuthenticationProviderKey": "Bearer",
"AllowedScopes": [
"Cart.API",
"Catalogue.API",
"Identity.API",
"offline_access"
]
}
},
{
"UpstreamPathTemplate": "/User/LoggedUser",
"UpstreamHttpMethod": [ "Get" ],
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7268
}
],
"DownstreamPathTemplate": "/api/User/LoggedUser",
"DownstreamHttpMethod": "Get",
"AuthenticationOptions": {
"AuthenticationProviderKey": "Bearer",
"AllowedScopes": [
"Cart.API",
"Catalogue.API",
"Identity.API",
"offline_access"
]
}
}
//edit,get logged user
],
"GlobalConfiguration": {
"BaseUrl": "https://localhost:7193"
}
}
Now here is the problem.
I have the endpoint [GET] /User/LoggedUser (at the bottom) and it is configured without any authorization and it calls /api/User/LoggedUser.
I also have the endpoint [GET] /User/{id} and it is configured WITH authorization and it calls /api/User/{id}
If I use the current configuration as a whole and try calling [GET] /User/LoggedUser with authenticated user, but without the claim Administrator : true -> ** it does not work**
If I delete the rerouting for [GET] /User/{id}, which as you can see, is a totally separate endpoint rerouting - the above problem disappears.
It is as if Ocelot treats these 2 endpoints as one. But I do not understand why.
And here is the console log:
The problem is only with these 2 endpoints. If I call [PUT] /User/LoggedUser it does not work until I delete [PUT] /User/{id} .No other problems were detected. At least for now.
Update 1
So I renamed my API endpoints from /api/User/LoggedUser to be /LoggedUser (downstream path), changed my upstream path to /Test/LoggedUser and it worked.
So, clearly it is an url conflict. How should I handle such problem?
Update 2
Again, I changed the endpoints to the following:
{
"UpstreamPathTemplate": "/Get/LoggedUser",
"UpstreamHttpMethod": [ "Get" ],
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7268
}
],
"DownstreamPathTemplate": "/api/User/Get/LoggedUser",
"DownstreamHttpMethod": "Get",
"AuthenticationOptions": {
"AuthenticationProviderKey": "Bearer",
"AllowedScopes": [
"Cart.API",
"Catalogue.API",
"Identity.API",
"offline_access"
]
}
},
{
"UpstreamPathTemplate": "/Edit/LoggedUser",
"UpstreamHttpMethod": [ "Put" ],
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7268
}
],
"DownstreamPathTemplate": "/api/User/Edit/LoggedUser",
"DownstreamHttpMethod": "Put",
"AuthenticationOptions": {
"AuthenticationProviderKey": "Bearer",
"AllowedScopes": [
"Cart.API",
"Catalogue.API",
"Identity.API",
"offline_access"
]
}
}
And still, there is conflict.
Update 3
I have other endpoints which are overlapping to some extend. For example:
{
"UpstreamPathTemplate": "/User/Login",
"UpstreamHttpMethod": [ "Post" ],
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7268
}
],
"DownstreamPathTemplate": "/api/User/Login",
"DownstreamHttpMethod": "Post"
},
{
"UpstreamPathTemplate": "/User/Register",
"UpstreamHttpMethod": [ "Post" ],
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7268
}
],
"DownstreamPathTemplate": "/api/User/Register",
"DownstreamHttpMethod": "Post"
}
Yet, no problem with these endpoints. They are both POST, they both start with api/User and /User. I do not see what is the problem with the other endpoints.
I think the problem should be fixed from the routing configuration of the backend api, rather than the ocelot configuration. You should configure the default routes order (precedence) from specific to generic. In the above case /api/User/LoggedUser should be matched before /api/User/{id}. Take a look at this article for some more info about routing precedence in asp.net mvc and web.api.
I have ASP.NET Web API microservices and currently I am implementing API gateway for routing and authentication.
From my 3 APIs, one of them is for User (crud) operations, so I decided to use it for a gateway, as well. And while I was implementing the routing I came across a strange problem.
With this (test) configuration (again, using my User API running on port 7268)
{
"Routes": [
//User API
{
"UpstreamPathTemplate": "/User/Login",
"UpstreamHttpMethod": [ "Post" ],
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7124
}
],
"DownstreamPathTemplate": "/api/Product",
"DownstreamHttpMethod": "Get"
}
],
"GlobalConfiguration": {
"BaseUrl": "https://localhost:7268"
}
}
... I am able to get list of products from the Product API on port 7124, when I navigate to /User/Login.
Now if I change the configuration to access any endpoint of the same User API (which matches the BaseUrl path), it does not work. Example:
{
"Routes": [
//User API
{
"UpstreamPathTemplate": "/User/Login",
"UpstreamHttpMethod": [ "Post" ],
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7268
}
],
"DownstreamPathTemplate": "/api/User/Login",
"DownstreamHttpMethod": "Post"
}
],
"GlobalConfiguration": {
"BaseUrl": "https://localhost:7268"
}
}
It gives me 404 Not Found and the following message in the console:
Is this because I am using an existing API to re-route itself and it is expected behavior, or I am doing something wrong?
I need to integrate .net core gateway with rabbit mq.
Iam using angular 10 as client.
The architecture is=> Client(Angular 10) -> Gateway(Ocelot) -> Rabbitmq with easy netq -> .Net core Console app.
.Net core gateway route structure is given below
{
"Routes": [
{
"DownstreamPathTemplate": "/api/product",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44337
}
],
"UpstreamPathTemplate": "/gateway/product",
"UpstreamHttpMethod": [ "POST", "PUT", "GET" ]
},
{
"DownstreamPathTemplate": "/api/product/{id}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44337
}
],
"UpstreamPathTemplate": "/gateway/product/{id}",
"UpstreamHttpMethod": [ "GET", "DELETE" ]
}
],
"GlobalConfiguration": {
"BaseUrl": "http://localhost:44382"
}
}
We know that rabbit mq pattern is messaging with publish and subscribe method.
My question is do i need to add the code of consumer(subscribe) section of rabbit mq in gatway api and publish code in console app?
{
"DownstreamPathTemplate": "/ProceedToBuy/PostWishList",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 8003
}
],
"UpstreamPathTemplate": "/AddToWishlist",
"UpstreamHttpMethod": [ "POST" ]
}
I want to send json body with this route request.
Actually you don't have to route json the request will automatically route to the downstream path, we can just directly make request to upstream path with json and it'll work!
I'm using MMLib.SwaggerForOcelot for gateway. in .Net core
I got this error. Any idea?
My Upstream and DownStream:
"SwaggerEndPoints": [
{
"Key": "skIndustry",
"Config": [
{
"Name": "Industry API",
"Version": "v1",
"Url": "http://industryapi:80/swagger/v1/swagger.json"
}
]
}
]
My ReRoutes:
"ReRoutes": [
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "industryapi/",
"Port": 80
}
],
"UpstreamPathTemplate": "/Industry/{everything}",
"UpstreamHttpMethod": [ "POST", "PUT", "GET" ],
"SwaggerKey": "skIndustry"
}
]
Thanks,
Croos.
Please try new version 1.3.1.
This PR probably solve similar problem.