Can I use Ocelot API Gateway to proxy to a Website - asp.net-core

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.

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?

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" ]
}

Ocelot API Gateway Optional Parameter

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}"

laravel echo server , redis

i have a problem with remote connections.
my vhost is : redis.test
i added this on blade file:
<script src="//redis.test:6001/socket.io/socket.io.js"></script>
.env file
BROADCAST_DRIVER=redis
REDIS_HOST=redis.test
REDIS_PASSWORD=null
REDIS_PORT=6379
echo configuration
import Echo from "laravel-echo"
window.Echo = new Echo({
broadcaster: 'socket.io',
host: 'http://redis.test:6001'
});
laravel-exho-server.json
{
"authHost": "http://redis.test",
"authEndpoint": "/broadcasting/auth",
"clients": [
{
"appId": "f27485125ac2627f",
"key": "6328e672f42cbf4cba1de3da215ec41a"
}
],
"database": "redis",
"databaseConfig": {
"redis": {
"port": "6379",
"host": "redis.test"
},
"sqlite": {
"databasePath": "/database/laravel-echo-server.sqlite"
}
},
"devMode": true,
"host": "redis.test",
"port": "6001",
"protocol": "http",
"socketio": {},
"sslCertPath": "",
"sslKeyPath": ""
}
it works when i try to broadcast with a local connection (2 browsers - same pc), but when i try to send a "message" from other pc on lan network (192.168.1.50) i have this error
GET: http://redis.test:6001/socket.io/socket.io.js net::err_connection_refused
[vue_warn] error in created hook
how ca i resolve this?
It may be a firewall issue as I can see, try to open redis port in the firewall

How to correctly deploy multi meteor instances WITH SSL on one digitalocean droplet using mup?

my mup.json config for first meteor instance:
{
"servers": [
{
"host": "111.222.333.444",
"username": "root",
"password": "mypass"
}
],
"setupMongo": true,
"setupNode": true,
"nodeVersion": "0.10.40",
"setupPhantom": false,
"enableUploadProgressBar": true,
"appName": "myapp1",
"app": "../myapp1",
"env": {
"PORT": 3001,
"ROOT_URL": "https://my.domain.com"
},
"ssl": {
"pem": "./ssl.pem"
},
"deployCheckWaitTime": 15
}
So after deployment I want to get access to this instance by https://my.domain.com:3001. Then with similar configuration I want to deploy second instance to same droplet and get access to it by https://my.domain.com:3002.
The problem is that after deployment accessing by https taking ERR_CONNECTION_CLOSED, but accessing by http is OK.
How can I make it working?
Finally, I did it.
Firstly, I used mupx. But there I had troubles too. Later I found that my fault was writing same ports for different apps or protocols. So, there is working configurations of first and second apps:
{
"servers": [{
"host": "111.222.333.444",
"username": "root",
"password": "mypass",
"env": {}
}],
"setupMongo": true,
"appName": "myapp1",
"app": "../myapp1",
"env": {
"PORT": 8000,
"ROOT_URL": "http://my.domain.com"
},
"deployCheckWaitTime": 15,
"enableUploadProgressBar": true,
"ssl": {
"certificate": "../ssl/bundle.crt",
"key": "../ssl/private.key",
"port": 8001
}
}
{
"servers": [{
"host": "111.222.333.444",
"username": "root",
"password": "mypass",
"env": {}
}],
"setupMongo": true,
"appName": "myapp2",
"app": "../myapp2",
"env": {
"PORT": 8100,
"ROOT_URL": "http://my.domain.com"
},
"deployCheckWaitTime": 15,
"enableUploadProgressBar": true,
"ssl": {
"certificate": "../ssl/bundle.crt",
"key": "../ssl/private.key",
"port": 8101
}
}
bundle.crt and private.key are common for all apps.
Don't forget to use mupx.
So after
mupx setup
mupx deploy
We can get access for first app by
http://my.domain.com:8000
https://my.domain.com:8001
And for second app by
http://my.domain.com:8100
https://my.domain.com:8101
EDIT: accessing by http is not working. I don't know why, maybe it just for my configuration. But this feature I don't need, I need only https. So if you know how to fix, please, write.
EDIT2: it's alright, http access works. The reason was Chrome browser, it always redirects my domain from http to https. After cleaning browser history it do all good.