Sub_filter 是 Nginx 轻量级响应体字符串替换模块,适用于反向代理层简单路径修正或注入,但不支持正则、HTML深度重写及压缩/分块编码下可靠工作。

Sub_filter 是 Nginx 提供的一个轻量级、低开销的响应体内容替换模块,适合在反向代理网关层做简单字符串注入或路径修正(比如将后端返回的绝对路径改写为网关统一域名),但不适用于复杂 HTML 重写或 JS/CSS 内容深度处理。
启用 sub_filter 的前提条件
该功能默认编译进大多数主流 Nginx 发行版(包括官方预编译包),但需确认以下两点:
- Nginx 版本 ≥ 0.7.32(推荐 ≥ 1.11.6,支持 sub_filter_once off 多次匹配)
- 模块未被显式禁用:运行 nginx -V 2>&1 | grep -o with-http_sub_module,有输出即表示已启用
- 注意:sub_filter 仅作用于 text/plain、text/html、application/json 等明确声明 Content-Type 的响应;若后端未设类型或设为 application/octet-stream,则不会触发替换
基础替换语法与常见配置模式
sub_filter 指令必须放在 location 块中,且仅对 proxied 响应生效。典型用法如下:
-
单次替换(默认行为):
sub_filter 'http://api.old.com' 'https://api.example.com'; -
全局替换(同一响应内所有匹配项):
sub_filter_once off; -
区分大小写控制:
sub_filter_ignore_case on;(默认关闭,区分大小写) -
配合 proxy_pass 使用示例:
location /app/ {
proxy_pass https://backend-server/;
sub_filter '"/static/' '"/app/static/';
sub_filter_once off;
sub_filter_types text/html application/json;
}
绕过缓存与响应限制的关键细节
sub_filter 不会修改原始响应长度,因此容易与 gzip、chunked 编码或代理缓存产生冲突:
- 若启用了 gzip on,sub_filter 默认失效(因响应已被压缩)——需添加 gzip_vary off; 并确保 sub_filter_types 包含实际返回类型
- 当后端使用 Transfer-Encoding: chunked 且未发送 Content-Length 时,sub_filter 可能只处理首块数据;建议后端显式设置 Content-Length 或关闭分块编码(如通过 proxy_buffering on + proxy_buffer_size 调整)
- sub_filter 不支持正则表达式,无法实现动态值提取(例如把
src="/img/123.jpg"替成src="https://cdn.example.com/123.jpg"中的 123 需借助 Lua 或外部服务)
调试与验证方法
替换失败时优先检查响应头和原始内容流:
- 用 curl 查看原始响应:
curl -H "Accept: text/html" -I http://gateway/app/ 确认 Content-Type 和是否被 gzip - 禁用浏览器缓存并查看响应体:
curl -H "Cache-Control: no-cache" http://gateway/app/ | grep -o 'https://[^"]*' - 开启 Nginx 错误日志 debug 级别(临时):
error_log /var/log/nginx/debug.log debug;,搜索 "sub filter" 相关日志行 - 注意:sub_filter 对非 2xx 响应(如 404、502)同样生效,可利用这点注入自定义错误提示


















