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.com
或 server_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
我在 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.com
或 server_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