Skip to main content
Version: Next

response-rewrite

Description#

The response-rewrite Plugin offers options to rewrite responses that APISIX and its Upstream services return to clients. With the Plugin, you can modify HTTP status codes, request headers, response body, and more.

For instance, you can use this Plugin to:

  • Support CORS by setting Access-Control-Allow-* headers.
  • Indicate redirection by setting HTTP status codes and Location header.
tip

You can also use the redirect Plugin to set up redirects.

Attributes#

NameTypeRequiredDefaultValid valuesDescription
status_codeintegerFalse[200, 598]New HTTP status code in the response. If unset, falls back to the original status code.
bodystringFalseNew response body. The Content-Length header would also be reset. Should not be configured with filters.
body_base64booleanFalsefalseIf true, decode the response body configured in body before sending to client, which is useful for image and protobuf decoding. Note that this configuration cannot be used to decode Upstream response.
headersobjectFalseActions to be executed in the order of add, remove, and set.
headers.addarray[string]FalseHeaders to append to requests. If a header already present in the request, the header value will be appended. Header value could be set to a constant, or one or more Nginx variables.
headers.setobjectFalseHeaders to set to requests. If a header already present in the request, the header value will be overwritten. Header value could be set to a constant, or one or moreNginx variables.
headers.removearray[string]FalseHeaders to remove from requests.
varsarray[array]FalseAn array of one or more matching conditions in the form of lua-resty-expr.
filtersarray[object]FalseList of filters that modify the response body by replacing one specified string with another. Should not be configured with body.
filters.regexstringTrueRegEx pattern to match on the response body.
filters.scopestringFalse"once"["once","global"]Scope of substitution. once substitutes the first matched instance and global substitutes globally.
filters.replacestringTrueContent to substitute with.
filters.optionsstringFalse"jo"RegEx options to control how the match operation should be performed. See Lua NGINX module for the available options.

Examples#

The examples below demonstrate how you can configure response-rewrite on a Route in different scenarios.

note

You can fetch the admin_key from config.yaml and save to an environment variable with the following command:

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

Rewrite Header and Body#

The following example demonstrates how to add response body and headers, only to responses with 200 HTTP status codes.

Create a Route with the response-rewrite Plugin:

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
}
}
}'

Send a request to verify:

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

You should receive a HTTP/1.1 200 OK response similar to the following:

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

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

Rewrite Header With RegEx Filter#

The following example demonstrates how to use RegEx filter matching to replace X-Amzn-Trace-Id for responses.

Create a Route with the response-rewrite Plugin:

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
}
}
}'

Send a request to verify:

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

You should see a response similar to the following:

{
"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"
}
}

Decode Body from Base64#

The following example demonstrates how to Decode Body from Base64 format.

Create a Route with the response-rewrite Plugin:

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
}
}
}'

Send a request to verify:

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

You should see a response of the following:

Hello World

Rewrite Response and Its Connection with Execution Phases#

The following example demonstrates the connection between the response-rewrite Plugin and execution phases by configuring the Plugin with the key-auth Plugin, and see how the response is still rewritten to 200 OK in the case of an unauthenticated request.

Create a Consumer jack:

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

Create key-auth credential for the Consumer:

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"
}
}
}'

Create a Route with key-auth and configure response-rewrite to rewrite the response status code and body:

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
}
}
}'

Send a request to the Route with the valid key:

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

You should receive an HTTP/1.1 200 OK response of the following:

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

Send a request to the Route without any key:

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

You should still receive an HTTP/1.1 200 OK response of the same, instead of HTTP/1.1 401 Unauthorized from the key-auth Plugin. This shows that the response-rewrite Plugin still rewrites the response.

This is because header_filter and body_filter phase logics of the response-rewrite Plugin will continue to run after ngx.exit in the access or rewrite phases from other plugins.

The following table summarizes the impact of ngx.exit on execution phases.

Phaserewriteaccessheader_filterbody_filter
rewritengx.exit
access×ngx.exit
header_filterngx.exit
body_filter×ngx.exit

For example, if ngx.exit takes places in the rewrite phase, it will interrupt the execution of access phase but not interfere with header_filter and body_filter phases.