Nginx的sub_filter指令可在反向代理响应返回前动态替换响应体文本,用于修正硬编码绝对路径;需禁用gzip、设置sub_filter_types和sub_filter_once,并配合map变量实现动态路径重写。

使用 Nginx 的 sub_filter 指令可以在反向代理响应返回客户端前,对响应体(body)中的文本内容做动态替换,从而修正 HTML、CSS、JS 中硬编码的绝对路径(如 http://old-domain.com/static/ → /static/ 或 https://new-domain.com/static/)。这在不修改后端源码、实现前端资源路径“透明迁移”或“多环境统一路由”时非常实用。
启用 sub_filter 前提与基础配置
该指令默认不生效,需显式开启响应体过滤:
-
sub_filter_once off;:允许多次替换(默认为on,只替换第一个匹配项) -
sub_filter_types *或指定 MIME 类型(如text/html text/css application/javascript),否则仅对text/html生效 - 必须搭配
proxy_set_header Accept-Encoding "";禁用后端 gzip 压缩——因为sub_filter无法处理压缩后的响应体 - 推荐在
location块中配置,避免全局影响;若需正则替换,应改用sub_filter的增强版模块(如ngx_http_substitutions_filter_module)
修正绝对 URL 为相对路径或新域名
常见场景是把后端返回的完整域名地址替换成当前请求的上下文路径。例如将:
`` → ``
对应配置如下:
location / {
proxy_pass https://backend.example.com/;
proxy_set_header Host backend.example.com;
proxy_set_header Accept-Encoding "";
sub_filter 'http://backend.example.com/' '/';
sub_filter 'https://backend.example.com/' '/';
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
}
注意:替换字符串需严格匹配原始响应中的字面量(含协议、斜杠、大小写);若后端返回的是双引号或单引号包裹的路径,需分别处理或统一用正则模块。
结合变量实现动态路径重写
纯静态替换无法适配不同子路径(如部署在 /v2/ 下),此时可借助 map 和 sub_filter 变量组合:
map $request_uri $base_prefix {
~^/v2/(.*) "/v2/";
default "/";
}
server {
location / {
proxy_pass https://backend.example.com/;
proxy_set_header Accept-Encoding "";
sub_filter 'http://backend.example.com/' $base_prefix;
sub_filter 'https://backend.example.com/' $base_prefix;
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
}
}
这样当访问 /v2/index.html 时,所有 https://backend... 都被替换为 /v2/,保持路径层级一致。
注意事项与典型问题
-
sub_filter不处理响应头(如Location、Content-Security-Policy),这些需用proxy_redirect或add_header单独处理 - 响应体过大(>1M)可能被截断,可通过
proxy_buffering on;+ 调整proxy_buffers缓冲区缓解 - 若页面含内联 JS/CSS 且路径拼接逻辑复杂(如字符串模板),纯文本替换易出错,建议优先推动后端支持相对路径或通过环境变量注入
- HTTPS 后端返回的混合内容(HTTP 资源)在浏览器中会被拦截,替换时务必统一协议(如全转
https://或全用//协议相对链接)

















