Express-Gateway,服务相同 API path/route,但在不同的 ServiceEndpoints 下

Express-Gateway, serve same API path/route, but under different ServiceEndpoints

我在 Node.js + Express 中有一个服务器,它向 public 和管理员公开了一些 API。实际上我有 2 个克隆实例 运行,一个用于测试,一个用于生产。它们是双胞胎,公开相同的路由(/admin/public),但连接到两个不同的数据库,并部署在两个不同的地址上。

我想使用 Express-Gateway 为 3d 方提供 API,所以我会先让他们访问测试服务器。全部完成后,我还会授予他们生产访问权限。

为此,我的想法是只创建 1 个 eg user,多个 eg application。每个 eg application 将有 eg credentials 访问服务器或生产。

                                             http://server_test.com
            |-------------|                    |-------------|
            |   App Prod  |                    | Server Test |
    +----►  |    scopes:  |------+     +-----► |    /public  |
    |       | [api_prod]  |      |     |       |    /admin   |
    |       |-------------|      ▼     |       |-------------|
    |                       http://gateway.com
|------|                     |------------|         
| User |                     |   Express  |  
|------|                     |   Gateway  |    
    |       |-------------|  |------------|                     
    |       |   App Test  |      ▲     |    http://server_prod.com
    +----►  |    scopes:  |      |     |       |-------------|             
            | [api_test]  |------+     +-----► | Server Prod |     
            |-------------|                    |    /public  |                 
                                               |    /admin   |                   
                                               |-------------|

根据提供的凭据,网关应将请求重定向到 server_test.comserver_prod.com。我的想法是使用 eg scopes 将请求发送到正确的端点。因此服务器测试策略将需要范围 api_test,而服务器生产将需要 api_prod 范围。

无论如何这个解决方案都行不通,因为如果 apiEndpoints 中的第一个匹配失败,它只会导致 "Not Found".

示例:我使用 App Prod 凭据向 http://gateway.com/public 发出请求,范围为 api_prod。它应该传递给 http://server_prod.com/public,但它匹配 testEndpoint 的第一个 paths: '/*',并且不符合范围条件。所以它只是失败了,而正确的 apiEndpoint 应该是 prodEndpoint.

我该如何解决这个问题?

这是我的gateway.config.yml

apiEndpoints:
   testEndpoint
      host:*
      paths: '/*'            # <--- match this
      scopes: ["api_test"]   # <--- but fails this
   prodEndpoint
      host:*
      paths: '/*'
      scopes: ["api_prod"]   # <---- this is right
serviceEndpoints
    testService      
      url: "http://server_test.com"
    prodService      
      url: "http://server_prod.com"
policies
    - proxy
pipelines
    testEndpoint:              # Test
       apiEndpoints:
         - testEndpoint
       policies:
         - proxy
           - action
             serviceEndpoint: testService
    prodEndpoint:              # Prod
       apiEndpoints:
         - prodEndpoint
       policies:
         - proxy
           - action
             serviceEndpoint: prodService

我是这样解决的:使用-rewrite策略。

  • 我在客户的请求前加上 /test/prod
  • 使用前缀匹配path正确的apiEndpoint
  • 重写请求,删除前缀
  • 选择服务端点并继续...
                                        http://server_test.com
|-------------|                              |-------------|
|   App Prod  | /prod/admin          /admin  | Server Test |
|    scopes:  |-------------+     +--------► |    /public  |
| [api_prod]  |             |     |          |    /admin   |
|-------------|             ▼     |          |-------------|
                        http://gateway.com
                         |------------|         
                         |   Express  |  
                         |   Gateway  |    
|-------------|          |------------|                     
|   App Test  |             ▲     |        http://server_prod.com
|    scopes:  |             |     |           |-------------|             
| [api_test]  |-------------+     +---------► | Server Prod |     
|-------------| /test/admin          /admin   |    /public  |                 
                                              |    /admin   |                   
                                              |-------------|

这是我的配置文件:

apiEndpoints:
   testEndpoint
      host:*
      paths: '/test/*'        
      scopes: ["api_test"]   
   prodEndpoint
      host:*
      paths: '/prod/*'
      scopes: ["api_prod"]  
serviceEndpoints
    testService      
      url: "http://server_test.com"
    prodService      
      url: "http://server_prod.com"
policies
    - proxy
pipelines
    testEndpoint:              # Test
       apiEndpoints:
         - testEndpoint
       policies:
         - rewrite:            # rewrite - delete '/test'
           -
             condition:
                name: regexpmatch
                match: ^/test/?(.*)$
             action:
               rewrite: /   
         - proxy
           - action
             serviceEndpoint: testService
    prodEndpoint:              # Prod
       apiEndpoints:
         - prodEndpoint
       policies:
         - rewrite:           # rewrite - delete '/prod'
           -
             condition:
                name: regexpmatch
                match: ^/prod/?(.*)$
             action:
               rewrite: /  
         - proxy
           - action
             serviceEndpoint: prodService