unexplored
unexplored

Reputation: 1424

Express-Gateway, How to pick a service end point based on URL pattern?

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

Answers (2)

unexplored
unexplored

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

Vincenzo
Vincenzo

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

Related Questions