exit-transformer
exit-transformer 插件 支持根据 API7 插件返回的状态码、请求头和请求体自定义网关响应。当配置为全局插件时,它还支持自定义请求不存在的路由时的响应。
转换逻辑在插件中使用 Lua 函数定义,遵循以下语法:
return (function(code, body, header) if {{ condition }} then return {{ modified_resp }} end return code, body, header end)(...)
示例
以下示例演示了如何在不同场景下使用 exit-transformer。
启用 exit-transformer 插件
在 API7 网关中,exit-transformer 默认可通过 Dashboard 和 Admin API 使用。对于 APISIX 部署,在配置使用该插件的全局规则或路由前,请先在网关静态配置中加载该插件。
- 宿主机或 Docker
- Kubernetes (Helm)
对于 APISIX 宿主机或 Docker 部署,请保留 config.yaml 中现有插件列表,并加入 exit-transformer:
plugins:
# 保留现有插件列表。
- exit-transformer
重新加载网关以使更改生效。
对于 APISIX Helm Chart,apisix.plugins 会替换已加载插件列表。请从当前网关使用的完整插件列表开始,加入 exit-transformer,并保留列表中的其他插件:
apisix:
plugins:
# 保留网关使用的完整插件列表。
- exit-transformer
使用 APISIX Helm Chart 应用 values 文件:
helm upgrade <release-name> <chart-name> -n <namespace> -f values.yaml
修改 404 路由未找到响应
以下示例演示了当路由不存在时,如何使用该插件更新 404 Not Found 响应代码和头。在这种情况下,插件需要配置为全局规则插件。
创建一个启用 exit-transformer 插件的全局规则,其中函数将响应状态码更新为 405,如果原始状态码为 404,则添加自定义 X-Custom-Header 头:
- Admin API
- ADC
- Ingress Controller
curl -i "http://127.0.0.1:9180/apisix/admin/global_rules" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "transform-404-not-found",
"plugins": {
"exit-transformer": {
"functions": ["return (function(code, body, header) header = header or {} if code == 404 then header[\"X-Custom-Header\"] = \"Modified\" return 405, body, header end return code, body, header end)(...)"]
}
}
}'
global_rules:
- id: transform-404-not-found
plugins:
exit-transformer:
functions:
- "return (function(code, body, header) header = header or {} if code == 404 then header[\"X-Custom-Header\"] = \"Modified\" return 405, body, header end return code, body, header end)(...)"
将配置同步到网关:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: GatewayProxy
metadata:
namespace: aic
name: apisix-config
spec:
provider:
type: ControlPlane
controlPlane:
# 在此添加控制面连接配置
# ....
plugins:
- name: exit-transformer
enabled: true
config:
functions:
- "return (function(code, body, header) header = header or {} if code == 404 then header[\"X-Custom-Header\"] = \"Modified\" return 405, body, header end return code, body, header end)(...)"
应用配置:
kubectl apply -f gatewayproxy.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixGlobalRule
metadata:
namespace: aic
name: transform-404-not-found
spec:
ingressClassName: apisix
plugins:
- name: exit-transformer
enable: true
config:
functions:
- "return (function(code, body, header) header = header or {} if code == 404 then header[\"X-Custom-Header\"] = \"Modified\" return 405, body, header end return code, body, header end)(...)"
应用配置:
kubectl apply -f exit-transformer-ic.yaml
发送请求到一个不存在的路由:
curl -i "http://127.0.0.1:9080/non-existent"
你应该收到 HTTP/1.1 405 Not Allowed 响应,并看到 X-Custom-Header: Modified 头。
修改认证失败的 401 未授权响应
以下示例演示了当认证失败时,如何使用该插件更新 401 Unauthorized 响应。
- Admin API
- ADC
- Ingress Controller
创建一个启用 exit-transformer 插件的路由,其中函数如果原始状态码为 401,则将响应状态码更新为 402;并启用 key-auth:
curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "transform-auth-route",
"uri": "/get",
"plugins": {
"exit-transformer": {
"functions": ["return (function(code, body, header) if code == 401 then return 402, body, header end return code, body, header end)(...)"]
},
"key-auth":{}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
创建消费者 john:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "john"
}'
为消费者配置 key-auth 凭证:
curl "http://127.0.0.1:9180/apisix/admin/consumers/john/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-john-key-auth",
"plugins": {
"key-auth": {
"key": "john-key"
}
}
}'
创建一个配置了 key-auth 凭证的消费者,以及一个配置了 exit-transformer 和 key-auth 插件的路由:
consumers:
- username: john
credentials:
- name: key-auth
type: key-auth
config:
key: john-key
services:
- name: httpbin
routes:
- name: transform-auth-route
uris:
- /get
plugins:
exit-transformer:
functions:
- "return (function(code, body, header) if code == 401 then return 402, body, header end return code, body, header end)(...)"
key-auth: {}
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
将配置同步到网关:
adc sync -f adc.yaml
创建一个配置了 key-auth 凭证的消费者,以及一个配置了 exit-transformer 和 key-auth 插件的路由:
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: john
spec:
gatewayRef:
name: apisix
credentials:
- type: key-auth
name: primary-cred
config:
key: john-key
---
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: exit-transformer-plugin-config
spec:
plugins:
- name: exit-transformer
config:
functions:
- "return (function(code, body, header) if code == 401 then return 402, body, header end return code, body, header end)(...)"
- name: key-auth
config:
_meta:
disable: false
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: transform-auth-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /get
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: exit-transformer-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
namespace: aic
name: john
spec:
ingressClassName: apisix
authParameter:
keyAuth:
value:
key: john-key
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: transform-auth-route
spec:
ingressClassName: apisix
http:
- name: transform-auth-route
match:
paths:
- /get
methods:
- GET
upstreams:
- name: httpbin-external-domain
plugins:
- name: exit-transformer
enable: true
config:
functions:
- "return (function(code, body, header) if code == 401 then return 402, body, header end return code, body, header end)(...)"
- name: key-auth
enable: true
应用配置:
kubectl apply -f exit-transformer-ic.yaml
在没有凭证的情况下发送请求到路由:
curl -i "http://127.0.0.1:9080/get"
对于未授权访问,你应该收到 HTTP/1.1 402 Payment Required 响应,其中响应状态码已被修改。
根据请求头有条件地修改响应
以下示例演示了如何使用该插件根据请求头有条件地修改响应。
创建一个启用 exit-transformer 插件的路由,其中函数根据 Content-Type 头更新响应状态码。如果头值为 application/json 且原始状态码为 404,则将响应状态码更新为 405。为了演示目的,在条件评估内外打印警告消息。
- Admin API
- ADC
- Ingress Controller
curl -i "http://127.0.0.1:9180/apisix/admin/global_rules" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "transform-by-header-condition",
"plugins": {
"exit-transformer": {
"functions": [
"return
(function(code, body, header, ctx)
local core = require(\"apisix.core\")
local ct = core.request.headers(ctx)[\"Content-Type\"]
core.log.warn(\"exit transformer logics running outside the condition\")
if ct == \"application/json\" and code == 404 then
core.log.warn(\"exit transformer logics running inside the condition\")
return 405
end
return code, body, header
end)
(...)"
]
}
}
}'
global_rules:
- id: transform-by-header-condition
plugins:
exit-transformer:
functions:
- "return (function(code, body, header, ctx) local core = require(\"apisix.core\") local ct = core.request.headers(ctx)[\"Content-Type\"] core.log.warn(\"exit transformer logics running outside the condition\") if ct == \"application/json\" and code == 404 then core.log.warn(\"exit transformer logics running inside the condition\") return 405 end return code, body, header end)(...)"
将配置同步到网关:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: GatewayProxy
metadata:
namespace: aic
name: apisix-config
spec:
provider:
type: ControlPlane
controlPlane:
# 在此添加控制面连接配置
# ....
plugins:
- name: exit-transformer
config:
functions:
- "return (function(code, body, header, ctx) local core = require(\"apisix.core\") local ct = core.request.headers(ctx)[\"Content-Type\"] core.log.warn(\"exit transformer logics running outside the condition\") if ct == \"application/json\" and code == 404 then core.log.warn(\"exit transformer logics running inside the condition\") return 405 end return code, body, header end)(...)"
应用配置:
kubectl apply -f gatewayproxy.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixGlobalRule
metadata:
namespace: aic
name: transform-by-header-condition
spec:
ingressClassName: apisix
plugins:
- name: exit-transformer
enable: true
config:
functions:
- "return (function(code, body, header, ctx) local core = require(\"apisix.core\") local ct = core.request.headers(ctx)[\"Content-Type\"] core.log.warn(\"exit transformer logics running outside the condition\") if ct == \"application/json\" and code == 404 then core.log.warn(\"exit transformer logics running inside the condition\") return 405 end return code, body, header end)(...)"
应用配置:
kubectl apply -f exit-transformer-ic.yaml
发送请求到一个不存在的路由,不带任何头:
curl -i "http://127.0.0.1:9080/non-existent"
你应该收到 HTTP/1.1 404 Not Found 响应,并在日志中看到以下消息:
exit transformer logics running outside the condition
发送带有 JSON Content-Type 头的请求到不存在的路由:
curl -i "http://127.0.0.1:9080/non-existent" -H "Content-Type: application/json"
你应该收到 HTTP/1.1 405 Not Allowed 响应,其中响应状态码已被修改,并在日志中看到以下消息:
exit transformer logics running outside the condition
exit transformer logics running inside the condition