Skip to main content
Version: Next

response-rewrite

描述#

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

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

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

如果你仅需要重定向功能,建议使用 redirect 插件。

属性#

名称类型必选项默认值有效值描述
status_codeinteger[200, 598]修改上游返回状态码,默认保留原始响应代码。
bodystring修改上游返回的 body 内容,如果设置了新内容,header 里面的 Content-Length 字段也会被去掉。
body_base64booleanfalse如果为 true,则在发送到客户端之前解码body 中配置的响应主体,这对于图像和 protobuf 解码很有用。请注意,此配置不能用于解码上游响应。
headersobject按照 addremoveset 的顺序执行的操作。
headers.addarray[string]要附加到请求的标头。如果请求中已经存在标头,则会附加标头值。标头值可以设置为常量,也可以设置为一个或多个 Nginx 变量
headers.setobject要设置到请求的标头。如果请求中已经存在标头,则会覆盖标头值。标头值可以设置为常量,也可以设置为一个或多个Nginx 变量
headers.removearray[string]要从请求中删除的标头。
varsarray[array]lua-resty-expr 的形式包含一个或多个匹配条件的数组。
filtersarray[object]通过将一个指定字符串替换为另一个指定字符串来修改响应主体的过滤器列表。不应与 body 一起配置。
filters.regexstringTrue用于匹配响应主体的 RegEx 模式。
filters.scopestring"once"["once","global"]替换范围。once 替换第一个匹配的实例,global 全局替换。
filters.replacestringTrue要替换的内容。
filters.optionsstring"jo"用于控制如何执行匹配操作的 RegEx 选项。请参阅Lua NGINX 模块以了解可用选项。

示例#

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

note

您可以这样从 config.yaml 中获取 admin_key 并存入环境变量:

admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')

重写标头和正文#

以下示例演示了如何添加响应正文和标头,仅适用于具有 200 HTTP 状态代码的响应。

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

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_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"}

使用 RegEx 过滤器重写标头#

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

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

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_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_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

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

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

创建消费者 jack

curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${admin_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_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_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 阶段逻辑将在 ngx.exit 之后在其他插件的 accessrewrite 阶段继续运行。

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

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

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