sub_filter仅支持纯文本查找替换,不能直接修改JSON结构;需确保响应为UTF-8明文JSON、禁用gzip、设置正确Content-Type、关闭chunked传输,并用完整键值对模式安全替换。

sub_filter 指令本身不支持直接修改 JSON 响应体中的结构化字段(如替换某个 key 的 value),它只是对响应体做**纯文本查找与替换**。但只要后端返回的是 UTF-8 编码的明文 JSON(非 gzip 压缩、非流式分块),配合合理配置,就能在 Nginx 代理层完成轻量、实时的内容修正。
确保 sub_filter 生效的前提条件
很多问题其实卡在基础配置上:
- Nginx 必须启用 sub_filter 模块(默认已编译,无需额外加载)
- 响应头中不能含 Content-Encoding: gzip(需在 proxy_pass 前用
proxy_set_header Accept-Encoding ""禁用后端 gzip) - 响应头中 Content-Type 应为
application/json或其他 text 类型(sub_filter 默认只处理 text/* 类型;若后端返回无类型或自定义类型,需加sub_filter_types *或显式列出) - 响应不能是 Transfer-Encoding: chunked 流式传输(sub_filter 需完整响应体才能工作;若后端强制分块,可加
proxy_buffering on和足够大的 buffer 缓存整包)
典型 JSON 字段值替换示例
比如后端返回:{"code":0,"msg":"ok","data":{"url":"http://old.example.com/file.jpg"}},你想把图片域名统一换成 CDN 地址:
location /api/ {
proxy_pass https://backend/;
proxy_set_header Accept-Encoding "";
sub_filter '"url":"http://old.example.com' '"url":"https://cdn.example.com';
sub_filter_once off;
sub_filter_types application/json;
}
注意两点:
- 双引号和斜杠需原样写入,因为这是字符串字面量匹配
-
sub_filter_once off允许多次替换(避免只改第一个链接)
安全替换:避免误伤 JSON 结构
直接替换容易破坏 JSON 格式,例如把 "status":"success" 中的 "s" 错替成其他字符。更稳妥的方式是:
- 用完整键值对模式匹配:
sub_filter '"status":"success"' '"status":"ok"'; - 利用前后固定字符锚定,如替换 URL 时带上前后引号和冒号:
"avatar":"http://a.com/1.jpg"→"avatar":"https://b.com/1.jpg" - 避免跨字段替换:不要匹配换行或空格(JSON 通常无换行),也不要用正则(sub_filter 不支持正则,仅字面量)
进阶:组合使用 add_header 与 sub_filter 实现动态注入
单纯替换不够?可以借助 Nginx 变量间接“注入”内容:
- 用
map定义变量映射(如根据请求头决定替换目标) - 用
add_header X-Proxy-Modified "true"标记已处理,方便前端识别 - 结合
sub_filter替换占位符,例如后端返回"cdn_host":"__CDN_PLACEHOLDER__",再用sub_filter '__CDN_PLACEHOLDER__' '$cdn_domain';
其中 $cdn_domain 可由 map 或 geo 指令动态设置,实现灰度或地域路由级替换。
不复杂但容易忽略——关键是让 JSON 以可编辑的原始文本形式抵达 sub_filter,其余就是精准的字符串手术。











