Ocelot API Gateway Optional Parameter - asp.net-core

Is there a way to tell Ocelot that a parameter is optional?
Let's say the query param below is optional:
"DownstreamPathTemplate": "/api/SearchAPI/?query={query}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5000
}
],
"UpstreamPathTemplate": "/api/SearchAPI/?query={query}",
"UpstreamHttpMethod": [ "GET" ],
"FileCacheOptions": {
"TtlSeconds": 60
}
If I send a request to /SearchAPI/?query= I get a 404 as response. I need to duplicate the Upstream to not use the param to fix. Is there another way to fix that?

You can use {everything} like
"DownstreamPathTemplate": "/api/SearchAPI/{everything}"

Related

Why is Ocelot ignoring the first route in my JSON file?

I have implemented Ocelot API Gateway in my Net Core 7 application. One of the JSON files containing routes is set up as follows:
{
"Routes": [
{
"DownstreamPathTemplate": "/storedfiletype",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "<<<HOST DELETED FOR SECURITY>>>",
"Port": 443
}
],
"UpstreamPathTemplate": "/fileserver/storedfiletype",
"UpstreamHttpMethod": [ "Post" ]
},
{
"DownstreamPathTemplate": "/storedfiletype/fileextension",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "<<<HOST DELETED FOR SECURITY>>>",
"Port": 443
}
],
"UpstreamPathTemplate": "/fileserver/storedfiletype/fileextension",
"UpstreamHttpMethod": [ "Post" ]
}
]
}
Now when I try and post to the first route (/storedfiletype in this case), I get a 404 error but the second route works. When I swap them over (making /storedfiletype/fileextension the first route), /storedfiletype works and /storedfiletype/fileextension gives me the 404 error.
Any ideas?

Ocelot - adding multiple AuthenticationProviderKeys for one Downstream

I have 2 authentication methods (2 different login pages) for my project that return the JWT token. Some microservices are supposed to accept only one of the two methods, but others should be accessible and authorized by both methods (either one or the other). Essentially my problem is in the AuthenticationOptions part of the Ocelot configuration:
{
"DownstreamPathTemplate": "/FM",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5285
}
],
"AuthenticationOptions": {
"AuthenticationProviderKey": "firstauthenticationmethod",
"AllowedScopes": []
},
"UpstreamPathTemplate": "/API/GetFMData",
"UpstreamHttpMethod": [ "Get" ]
},
Here I can provide only one AuthenticationProviderKey for the FM microservice. However this one I would like to be authorized whether the user is giving JWT token from the first authentication method or from the second one. I can't supply an array of strings to this property like this for example:
"AuthenticationOptions": {
"AuthenticationProviderKey": ["firstauthenticationmethod", "secondauthenticationmethod"],
"AllowedScopes": []
}
nor provide an array of AuthenticationOptions like this for example:
"AuthenticationOptions": [{
"AuthenticationProviderKey": "firstauthenticationmethod",
"AllowedScopes": []
},
{
"AuthenticationProviderKey": "secondauthenticationmethod",
"AllowedScopes": []
}],
Both of these are not allowed in the Ocelot config file. Is there a way to make this microservice configurable in Ocelot to allow either of the authentication methods?

Adding Ocelot to web API breaks SignalR

I have a web API project where I use SignalR. Recently I added and configured Ocelot to be my gateway towards another web API. Ocelot routes the requests correctly but has messed up my SignalR configuration somehow.
Program.cs:
builder.Services.AddOcelot();
var app = builder.Build();
app.UseCors("AllowAllApps");
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
app.UseAuthentication();
app.UseAuthorization();
app.UseMvc();
app.UseOcelot().Wait();
app.MapHub<MyHub>("/myHub");
app.Run();
Client-side code:
// url = "http://localhost:5001/myHub"
connect(url: string, accessToken: string, debug: boolean): Promise<void> {
this.connection = new signalR.HubConnectionBuilder()
.withUrl(url, { accessTokenFactory: () => accessToken })
.configureLogging(debug ? signalR.LogLevel.Information : signalR.LogLevel.Error)
.withAutomaticReconnect()
.build();
return this.connection.start();
}
Ocelot.json
{
"Routes": [
{
"DownstreamPathTemplate": "/{route}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "myotherapi",
"Port": 80
}
],
"UpstreamPathTemplate": "/myotherapi/{route}",
"UpstreamHttpMethod": [ "Post" ],
"AuthenticationOptions": {
"AuthenticationProviderKey": "Bearer",
"AllowedScopes": []
},
"AddHeadersToRequest": {
"UserId": "Claims[sub] > value"
}
}
],
"GlobalConfiguration": {
"BaseUrl": "http://localhost:5001"
}
}
I need Ocelot only for HTTP requests. It shouldn't affect websocket connections with this configuration as far as I understand.
If I comment out the Ocelot lines in my Program.cs SignalR works. If I leave it there my POST request to http://localhost:5001/myHub/negotiate?negotiateVersion=1 fails with 404.
Is it something to do with the order of the middleware that is causing the issue? I have tried multiple different orderings but to no avail.
This is a .NET 6 project with Ocelot version 18.0. Both projects are containerized with Docker.
try adding this
{
"DownstreamPathTemplate": "/myHub/negotiate",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "myotherapi",
"Port": "80"
}
],
"UpstreamPathTemplate": "/myHub/negotiate",
"UpstreamHttpMethod": [ "POST" ]
}

How define ocelot configuration for POST method controllers net core?

Actually in my Api service i have a method controller like:
[Produces("application/json")]
[ApiController]
[Route("api/v1/[controller]")]
public class LoginController: Controller
{
public LoginController(IConfiguration config)
{
...
}
[Route("authentication"),HttpPost]
public async Task<IActionResult> Authentication(LogRequest request)
{
...
}
}
My configuration:
"ReRoutes": [
{
"DownstreamPathTemplate": "/api/{version}/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "tresfilos.users.service",
"Port": 7002
}
],
"UpstreamPathTemplate": "/api/{version}/user/{everything}",
"UpstreamHttpMethod": [ "POST", "PUT", "GET" ]
},
],
"GlobalConfiguration": {
"BaseUrl": "https://localhost:7001"
}
I consume in postman like:
http://localhost:7000/api/v1/user/Login/authentication
And i dont know if my definition on configuration file for ocelot is right for POST method.
I define now like:
"Routes": [
{
"DownstreamPathTemplate": "/api/{version}/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "tresfilos.users.service",
"Port": 7002
}
],
"UpstreamPathTemplate": "/api/{version}/User/{everything}"
},
],
"GlobalConfiguration": {
"BaseUrl": "https://localhost:7001"
}
Change ReRoutes to Routes because i use ocelot 16.0.1
And in postman i send the data in Body like json and not like paramaters.

Can I use Ocelot API Gateway to proxy to a Website

I am new to Ocelot API Gateway and trying to figure out how to perform a response host rewrite?
My ocelot api gateway is hosted on localhost:5000, the downstream server is on another host example.com. I am able to proxy from localhost:5000 to example.com, however, when example.com sends a response I get redirected to example.com. I need to stay within one domain (localhost:5000).
Any help is appreciated
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/example/{all}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "example.com",
"Port": 443
}
],
"UpstreamPathTemplate": "/example/{all}",
}
],
"GlobalConfiguration": {
"BaseUrl": "https://localhost:5000"
}
}
A bit late, but I think you need a "DownstreamHeaderTransform", which will change back example.com to localhost:9000. (not sure if the port will be mapped correctly). In our use case, we use the IP address of the downstream server, and then map that back to the host that the outside world sees. For you, try something along these lines:
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/example/{all}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "example.com",
"Port": 443
}
],
"DownstreamHeaderTransform": {
"Referrer": "https://example.com, https://localhost:5000",
"Host": "example.com, localhost:9000",
"Origin": "https://example.com, https://localhost:5000"
},
"UpstreamPathTemplate": "/example/{all}",
}
],
"GlobalConfiguration": {
"BaseUrl": "https://localhost:5000"
}
}
Personally, I found Ocelot to be rather finiky, and would try Kestrel instead.