【问题标题】:Express-Gateway, How to pick a service end point based on URL pattern?Express-Gateway,如何根据 URL 模式选择服务端点?
【发布时间】:2018-05-24 23:50:44
【问题描述】:

我正在尝试在网关后面的同一域上获取一堆单独的服务器。目前,可以通过多个名称从外部访问这些服务器中的每一个。我们的销售团队希望为客户提供一个唯一的 url,因此如果一个服务器为 10 个客户提供服务,我们有 10 条 CNAME 记录指向它。

如您所见,如果有 5 或 6 台服务器,apiEndpoints 的数量非常多。最重要的是,可以在任何给定时间创建新的 CNAME,从而使硬编码的 apiEndpoints 难以管理。

是否可以有一个动态的serviceEndpoint url。我的想法是这样的:

apiEndpoints:
  legacy:
    host: '*.mydomain.com'
    paths: '/v1/*'
serviceEndpoints:
  legacyEndPoint:
    url: '${someVarWithValueofStar}.internal.com'
pipelines:
  default:
    apiEndpoints:
      - legacy:
    policies:
      - proxy:
          - action:
              serviceEndpoint: legacyEndPoint

基本上,我想要实现的是将所有x.mydomain.com 重定向到x.internal.com,其中x 可以是任何东西。

我可以在 url 字符串中使用变量吗?有没有办法获取与主机中的通配符匹配的字符串?是否有其他方法可以解决此问题?

【问题讨论】:

    标签: express api-gateway express-gateway


    【解决方案1】:

    我最终为了我的需要一起破解了一个代理插件。非常基础,需要更多的工作和测试,但这是我开始的:

    代理插件(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
    

    这一切都归结为正则表达式解析apiEndpointsserviceEndpoints 主机和url 中的通配符,到目前为止没有什么特别的。我查看了内置代理插件的源代码,我认为我的幼稚方法不太适合,但它可以满足我的需要。

    【讨论】:

      【解决方案2】:

      感谢您的提问,我认为在接下来的几个月里会被很多人问到这个问题。

      Express Gateway 支持环境变量;不幸的是,现在apiEndpoint 只能是一个单一且定义明确的端点,没有任何替代功能。

      我们可能会在近期内改变这一点——使用代理表 API,它可以让您插入一些更难的模板。

      如果这对你来说很紧迫,我会邀请你到open an issue,以便团队中的每个人都知道这个功能,我们可以有效地优先考虑它。

      不幸的是,与此同时,您将不得不处理大量的 ApiEndpoints

      V.

      【讨论】:

      • 感谢您的反馈。我最初想打开一个问题,但不知道如何陈述它。我想我现在知道了。
      • 就我的问题而言,我已经通过创建自己的代理策略来解决它,该策略知道如何解析serviceEndPoint url 中的通配符,并将通配符替换为来自请求的主机名。它非常粗糙,只适用于我的用例,如果我有时间想出一个更优雅的解决方案,我会创建一个 PR。
      • 嘿,太好了。如果您能指出您更改/编写的代码,我很乐意查看一下,看看是否有机会在我们的主分支中获取它。谢谢!
      • 我添加了自己的答案来描述我的解决方案。顺便说一句,我在这里创建了一个功能请求feathub.com/ExpressGateway/express-gateway/+54
      • 太好了。我们会调查一下!
      猜你喜欢
      • 2015-09-08
      • 2019-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-16
      • 2016-10-05
      • 1970-01-01
      • 2021-05-22
      相关资源
      最近更新 更多