跳到主要内容
版本:3.10.x

API7 网关 AI Agent Skill:plugin response rewrite

本页提供 plugin response rewrite 场景的 API7 企业版操作指南。请保留下方命令、字段、配置项和 API 路径的原样,并根据实际网关环境替换示例值。

Overview

The response-rewrite plugin rewrites response attributes before API7 EE returns the response to the client. You can change the HTTP status code, response headers, and response body — either unconditionally or based on matching conditions. It runs in the header_filter and body_filter phases, so it executes even if earlier plugins (like auth) call ngx.exit.

When to Use

  • Override the HTTP status code returned to clients
  • Add, set, or remove response headers (e.g., security headers, CORS)
  • Replace the entire response body (static content, error messages)
  • Use regex filters to modify parts of the response body
  • Apply response changes conditionally (e.g., only for certain status codes)
  • Serve base64-decoded binary content (images, protobuf)

Plugin Configuration Reference (Route/Service)

FieldTypeRequiredDefaultDescription
status_codeintegerNoNew HTTP status code (200–598). If unset, original status is used.
bodystringNoNew response body. Content-Length is automatically reset. Cannot be used with filters.
body_base64booleanNofalseDecode body from base64 before sending. Only decodes plugin-configured body, not upstream response.
headersobjectNoHeader manipulation with set, add, and remove fields.
headers.setobjectNoSet (overwrite) response headers. Key-value pairs. Supports Nginx variables.
headers.addarray[string]NoAppend response headers. Format: ["Name: value", ...]. Adds even if header exists.
headers.removearray[string]NoRemove response headers. List of header names to strip.
varsarray[array]NoConditional matching using lua-resty-expr syntax. Plugin only executes when conditions match.
filtersarray[object]NoRegex filters to modify response body. Cannot be used with body.
filters[].regexstringYesRegex pattern to match in response body.
filters[].replacestringYesReplacement content.
filters[].scopestringNo"once""once" = first match only. "global" = all matches.
filters[].optionsstringNo"jo"Regex options. See ngx.re.match.

Mutual exclusion: body and filters cannot be used together.

Step-by-Step: Enable response-rewrite on a Route

1. Add security response headers

Add security headers for gateway group default:

a7 route create --gateway-group default -f - <<'EOF'
{
"id": "security-headers",
"uri": "/api/*",
"plugins": {
"response-rewrite": {
"headers": {
"set": {
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains"
},
"remove": ["Server", "X-Powered-By"]
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": [{"host": "backend", "port": 8080, "weight": 1}]
}
}
EOF

2. Custom error response body

a7 route create --gateway-group prod -f - <<'EOF'
{
"id": "custom-error",
"uri": "/maintenance/*",
"plugins": {
"response-rewrite": {
"status_code": 503,
"body": "{\"error\": \"Service under maintenance\", \"retry_after\": 300}",
"headers": {
"set": {
"Content-Type": "application/json",
"Retry-After": "300"
}
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": [{"host": "backend", "port": 8080, "weight": 1}]
}
}
EOF

3. Conditional rewrite (only for 200 responses)

a7 route create --gateway-group stage -f - <<'EOF'
{
"id": "conditional-rewrite",
"uri": "/api/*",
"plugins": {
"response-rewrite": {
"headers": {
"set": {
"Cache-Control": "public, max-age=3600"
}
},
"vars": [["status", "==", 200]]
}
},
"upstream": {
"type": "roundrobin",
"nodes": [{"host": "backend", "port": 8080, "weight": 1}]
}
}
EOF

Common Patterns

Regex body filter (replace text globally)

Replace internal hostnames in response body with public URLs:

{
"plugins": {
"response-rewrite": {
"filters": [
{
"regex": "http://internal\\.service\\.local",
"scope": "global",
"replace": "https://api.example.com"
}
]
}
}
}

Multiple regex filters

{
"plugins": {
"response-rewrite": {
"filters": [
{
"regex": "X-Amzn-Trace-Id",
"scope": "global",
"replace": "X-Trace-Id"
},
{
"regex": "\"debug\":\\s*true",
"scope": "global",
"replace": "\"debug\": false"
}
]
}
}
}

Base64 body (serve binary content)

{
"plugins": {
"response-rewrite": {
"status_code": 200,
"body": "SGVsbG8gV29ybGQ=",
"body_base64": true,
"headers": {
"set": {
"Content-Type": "text/plain"
}
}
}
}
}

Returns decoded body: Hello World

Add dynamic server info headers

{
"plugins": {
"response-rewrite": {
"headers": {
"set": {
"X-Served-By": "$balancer_ip:$balancer_port",
"X-Request-Id": "$request_id"
}
}
}
}
}

Conditional: only rewrite 5xx errors

{
"plugins": {
"response-rewrite": {
"body": "{\"error\": \"internal server error\", \"code\": 500}",
"headers": {
"set": {
"Content-Type": "application/json"
}
},
"vars": [["status", ">=", 500]]
}
}
}

Important Notes

  • Execution phase: Runs in header_filter and body_filter phases, which means it executes even if earlier plugins (auth, rate-limiting) reject the request via ngx.exit.
  • Header manipulation order: addremoveset.
  • Body and filters are mutually exclusive: Cannot set both body and filters.
  • base64 decoding: Only applies to the plugin-configured body field, NOT to the upstream response body.

Troubleshooting

SymptomCauseFix
Body not changedbody and filters both setUse only one: body for full replacement, filters for partial
Status code unchangedstatus_code not in valid rangeMust be 200–598
Regex filter not matchingPattern syntax or escaping issueTest regex; use "jo" options for UTF-8 support
Headers still present after removeHeader name case mismatchHeader names are case-insensitive; check exact spelling
Vars condition not workingIncorrect operator or typeUse lua-resty-expr syntax: ["status", "==", 200] (integer, not string)
Rewrite runs on auth failuresExpected behaviorPlugin runs in filter phases regardless of earlier ngx.exit calls
Content-Length mismatchManual Content-Length headerDon't set Content-Length manually — plugin resets it automatically
Config not appliedWrong gateway group specifiedEnsure --gateway-group matches the desired cluster

Config Sync Example

version: "1"
gateway_group: default
routes:
- id: response-transform
uri: /api/*
plugins:
response-rewrite:
headers:
set:
X-Content-Type-Options: "nosniff"
X-Frame-Options: "DENY"
remove:
- Server
- X-Powered-By
vars:
- ["status", "==", 200]
upstream:
type: roundrobin
nodes:
- host: backend
port: 8080
weight: 1

This page is generated from a7-plugin-response-rewrite/SKILL.md in the api7/a7 repository. Browse all skills on the AI Agent Skills page.