Reputation: 1424
I am trying to get a bunch of individual servers on the same domain behind the gateway. Currently, each of these servers can be reached from outside world via multiple names. Our sales team wanted to provide customers with a unique url, so if a server serves 10 customers, we have 10 CNAME records pointing to it.
As you can see, with 5 or 6 servers, the number of apiEndpoints
is pretty large. On top of that, new CNAMEs can be created at any given time making hardcoded apiEndpoints
a pain to manage.
Is it possible to have a dynamic serviceEndpoint
url. What I'm thinking is something like this:
apiEndpoints:
legacy:
host: '*.mydomain.com'
paths: '/v1/*'
serviceEndpoints:
legacyEndPoint:
url: '${someVarWithValueofStar}.internal.com'
pipelines:
default:
apiEndpoints:
- legacy:
policies:
- proxy:
- action:
serviceEndpoint: legacyEndPoint
Basically, what I want to achieve is to redirect the all the x.mydomain.com
to x.internal.com
where x
can be anything.
Can I use variables in the url strings? Is there a way to get the string that matched the wild card in the host? Are there other options to deal with this problem?
Upvotes: 2
Views: 1480
Reputation: 1424
I ended up hacking a proxy plugin together for my needs. Very basic and requires more work and testing, but this what I started with:
The proxy plugin (my-proxy)
const httpProxy = require("http-proxy");
/**
* This is a very rudimentary proxy plugin for the express gateway framework.
* Basically it will redirect requests xxx.external.com to xxx.internal.com
* Where xxx can be any name and the destination comes from providing a
* service endpoint with a http://*.destination.com url
* @param {*} params
* @param {*} config
*/
module.exports = function (params, config) {
const serviceEndpointKey = params.serviceEndpoint;
const changeOrigin = params.changeOrigin;
const endpoint = config.gatewayConfig.serviceEndpoints[serviceEndpointKey];
const url = endpoint.url;
const reg = /(\/\/\*\.)(\S+)/;
const match = reg.exec(url);
const domain = match[2];
const proxy = httpProxy.createProxyServer({changeOrigin : changeOrigin});
proxy.on("error", (err, req, res) => {
console.error(err);
if (!res.headersSent) {
res.status(502).send('Bad gateway.');
} else {
res.end();
}
});
return (req, res, next) => {
const hostname = req.hostname;
const regex = /^(.*?)\./
const tokens = regex.exec(hostname)
const serverName = tokens[1];
const destination = req.protocol + "://" + serverName + "." + domain;
proxy.web(req, res, {target : destination});
};
};
gateway.config.xml
http:
port: 8080
apiEndpoints:
legacy:
host: '*.external.com'
paths: '/v1/*'
serviceEndpoints:
legacy_end_point:
url: 'https://*.internal.com'
policies:
- my-proxy
pipelines:
default:
apiEndpoints:
- legacy
policies:
- my-proxy:
- action:
serviceEndpoint: legacy_end_point
changeOrigin: true
It all boils down to regex parsing the wild cards in the apiEndpoints
and serviceEndpoints
host and urls, nothing fancy so far. I looked at the source code of the built in proxy plugin and I don't think my naive approach will fit in very well, but it works for what I need it.
Upvotes: 2
Reputation: 1559
thanks for the question, I think this is going to be asked a lot over the following months.
Express Gateway has support for environment variables; unfortunately right now the apiEndpoint
can only be a single and well defined endpoint without any replacement capabilities.
This is something we'll probably change in the near term future — with a Proxy Table API that will let you insert some more difficult templates.
In case this is pressing for you, I'd invite you to open an issue so that everybody in the team is aware of such feature and we can prioritize it effectively.
In meantime, unfortunately, you'll have to deal with numerous numbers of ApiEndpoints
V.
Upvotes: 0