sub_filter仅支持字符串级查找替换,不解析JSON;需配置sub_filter_types application/json、禁用压缩、用sub_filter_once off实现全局替换,且必须精确匹配含引号的完整字段值。

sub_filter 指令本身不支持解析或修改 JSON 结构,它只是对响应体做**字符串级别的查找替换**。若想在 Nginx 代理层“动态修正 JSON 内容”,必须满足一个前提:你要替换的内容是**固定格式、可被正则或字面量精确匹配的字段值**,且不能破坏 JSON 的语法结构(如引号、逗号、括号等)。
确保 sub_filter 生效的基本条件
sub_filter 默认只处理 text/html 类型响应,而 JSON 响应通常是 application/json。需显式启用:
- 使用 sub_filter_types application/json; 允许对 JSON 响应体生效
- 确保响应未被压缩(gzip/br),因为 sub_filter 不处理压缩后的内容;可在 upstream 中禁用压缩,或在 location 中加 proxy_set_header Accept-Encoding "";
- sub_filter 默认只替换第一个匹配项;如需全局替换,加 sub_filter_once off;
安全替换 JSON 字段值的典型写法
假设上游返回:
{"code":0,"msg":"ok","data":{"url":"https://api.example.com/v1/user"}}你想把所有 api.example.com 替换为 api.mydomain.com,且保证引号和结构不变:
- sub_filter '"https://api.example.com' '"https://api.mydomain.com';
- sub_filter_types application/json;
- sub_filter_once off;
注意:必须包含前后引号和协议,否则可能误替 URL 片段(如把 domain.com 替成 mydomain.com 后导致 "mydomain.com/v1" 错误)。这种写法依赖字段位置和格式稳定,适用于 host、path 等固定前缀场景。
无法胜任的场景及替代建议
sub_filter 无法处理以下情况:
- 根据请求头或变量动态计算新值(比如把 url 中的 user_id 替换为当前请求的 cookie 值)
- 修正嵌套过深、键名不固定或存在转义字符的 JSON(如 {"urls":["\/v1\/a","\/v1\/b"]})
- 增删字段、修改数值类型(如把 "code":0 改成 "code":200)、重排结构
这类需求应考虑:OpenResty(lua-resty-json + ngx.exec/ngx.redirect) 或在应用层统一做网关转换,而非强求 Nginx 原生命令。
调试与验证要点
开启 sub_filter 后易因空格、换行、编码问题导致替换失败:
- 用 curl -H "Accept-Encoding: identity" 查看原始响应体,确认要替换的字符串完全一致(含空格、引号、斜杠)
- 临时加上 add_header X-Subfilter-Status "enabled"; 辅助判断是否命中
- 避免在 JSON 中替换未加引号的 key(如 code:0 → code:200),因为 sub_filter 无法识别 JSON 语法边界,极易出错
不复杂但容易忽略:它不是 JSON 编辑器,而是带条件的文本缝合器。用对了省事,用错了会返回非法 JSON。


















