跳到主要内容

response-rewrite

response-rewrite 插件提供了重写 APISIX 及其上游服务返回给客户端的响应的选项。使用该插件,你可以修改 HTTP 状态码、请求头、响应体等。

例如,你可以使用此插件来:

  • 通过设置 Access-Control-Allow-* 头来支持 CORS
  • 通过设置 HTTP 状态码和 Location 头来指示重定向。

示例

以下示例展示了如何在不同场景下的路由上配置 response-rewrite

重写响应头和响应体

以下示例演示了如何仅对具有 200 HTTP 状态码的响应添加响应体和响应头。

创建一个带有 response-rewrite 插件的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "response-rewrite-route",
"methods": ["GET"],
"uri": "/headers",
"plugins": {
"response-rewrite": {
"body": "{\"code\":\"ok\",\"message\":\"new json body\"}",
"headers": {
"set": {
"X-Server-id": 3,
"X-Server-status": "on",
"X-Server-balancer-addr": "$balancer_ip:$balancer_port"
}
},
"vars": [
[ "status","==",200 ]
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

发送请求以进行验证:

curl -i "http://127.0.0.1:9080/headers"

你应该收到类似于以下的 HTTP/1.1 200 OK 响应:

...
X-Server-id: 3
X-Server-status: on
X-Server-balancer-addr: 50.237.103.220:80

{"code":"ok","message":"new json body"}

使用正则过滤器重写响应头

以下示例演示了如何使用正则过滤器匹配来替换响应的 X-Amzn-Trace-Id

创建一个带有 response-rewrite 插件的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "response-rewrite-route",
"methods": ["GET"],
"uri": "/headers",
"plugins":{
"response-rewrite":{
"filters":[
{
"regex":"X-Amzn-Trace-Id",
"scope":"global",
"replace":"X-Amzn-Trace-Id-Replace"
}
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

发送请求以进行验证:

curl -i "http://127.0.0.1:9080/headers"

你应该看到类似于以下的响应:

{
"headers": {
"Accept": "*/*",
"Host": "127.0.0.1",
"User-Agent": "curl/8.2.1",
"X-Amzn-Trace-Id-Replace": "Root=1-6500095d-1041b05e2ba9c6b37232dbc7",
"X-Forwarded-Host": "127.0.0.1"
}
}

解码 Base64 格式的响应体

以下示例演示了如何解码 Base64 格式的响应体。

创建一个带有 response-rewrite 插件的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "response-rewrite-route",
"methods": ["GET"],
"uri": "/get",
"plugins":{
"response-rewrite": {
"body": "SGVsbG8gV29ybGQ=",
"body_base64": true
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

发送请求以进行验证:

curl "http://127.0.0.1:9080/get"

你应该看到以下响应:

Hello World

重写响应及其与执行阶段的联系

以下示例演示了 response-rewrite 插件与执行阶段之间的联系,通过配置带有 key-auth 插件的 response-rewrite 插件,观察在未经身份验证的请求情况下,响应如何仍然被重写为 200 OK

创建一个消费者 jack

curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "jack"
}'

为消费者创建 key-auth 凭证:

curl "http://127.0.0.1:9180/apisix/admin/consumers/jack/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-jack-key-auth",
"plugins": {
"key-auth": {
"key": "jack-key"
}
}
}'

创建一个带有 key-auth 的路由,并配置 response-rewrite 以重写响应状态码和响应体:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "response-rewrite-route",
"uri": "/get",
"plugins": {
"key-auth": {},
"response-rewrite": {
"status_code": 200,
"body": "{\"code\": 200, \"msg\": \"success\"}"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

使用有效密钥向路由发送请求:

curl -i "http://127.0.0.1:9080/get" -H 'apikey: jack-key'

你应该收到如下所示的 HTTP/1.1 200 OK 响应:

{"code": 200, "msg": "success"}

向路由发送不带任何密钥的请求:

curl -i "http://127.0.0.1:9080/get"

你仍然应该收到相同的 HTTP/1.1 200 OK 响应,而不是来自 key-auth 插件的 HTTP/1.1 401 Unauthorized。这表明 response-rewrite 插件仍然重写了响应。

这是因为 response-rewrite 插件的 header_filterbody_filter 阶段逻辑将在其他插件的 accessrewrite 阶段中的 ngx.exit 之后继续运行。

下表总结了 ngx.exit 对执行阶段的影响。

阶段rewriteaccessheader_filterbody_filter
rewritengx.exit
access×ngx.exit
header_filterngx.exit
body_filter×ngx.exit

例如,如果 ngx.exit 发生在 rewrite 阶段,它将中断 access 阶段的执行,但不会干扰 header_filterbody_filter 阶段。