Nginx sub_filter 无法按路径条件判断,但可通过精确/前缀匹配 location 定位 HTML 页面,配合 sub_filter、sub_filter_once off 和 sub_filter_types 实现特定页面内部链接替换;支持 map + set 模拟轻量动态行为,需关闭 gzip 与 chunked 并明确 charset。

Nginx 的 sub_filter 指令本身不支持按页面路径做条件判断,它只能在启用它的 location 块中全局生效。但你可以通过合理配置 location 块 + sub_filter + sub_filter_once off 等组合,实现“对特定页面动态修改内部链接”的效果。
精准匹配目标页面路径
用精确或前缀匹配定位需要处理的 HTML 页面,避免影响 API 或静态资源:
-
location = /article/123 { ... }—— 只处理该单页 -
location ^~ /blog/ { ... }—— 匹配所有 blog 下的路径(优先级高于正则) -
location ~ \.html$ { ... }—— 匹配所有 .html 文件(需配合 MIME 类型检查)
注意:确保后端返回的 Content-Type 是 text/html,否则 sub_filter 默认不生效(可通过 sub_filter_types text/html 显式开启)。
用 sub_filter 替换相对/绝对内部链接
替换常见内部跳转链接,例如将 /product/ 改为 /v2/product/,或把 href="/about" 改成 href="/about-us":
sub_filter '/product/' '/v2/product/';-
sub_filter 'href="/about"' 'href="/about-us"';(注意引号和空格) -
sub_filter_once off;—— 必须开启,否则只替换第一个匹配项
注意:sub_filter 是字符串替换,不解析 HTML 结构。若链接出现在 JS 字符串或注释中,也会被误改,需谨慎设计 pattern。
结合变量实现轻量“动态”行为
虽然 sub_filter 本身不支持变量,但你可以用 map 预定义规则,再通过 set + sub_filter 组合模拟动态逻辑:
- 在 http 块中定义映射:
map $uri $link_prefix {<br> default "/";<br> ~/blog/ "/blog-v2/";<br> ~/docs/ "/docs-next/";<br>} - 在 location 中引用:
set $new_prefix $link_prefix;<br>sub_filter '/static/' "$new_prefix/static/";<br>sub_filter '/api/' "$new_prefix/api/";
这种方式适合有限几类路径的差异化替换,不适用于完全自由的 URL 生成逻辑。
规避缓存与编码干扰
sub_filter 对压缩或分块传输的内容无效,务必关闭 Gzip 并禁用 chunked:
-
gzip off;(或确保 sub_filter 在 gzip 后执行,需编译时启用--with-http_sub_module且版本 ≥ 1.19.6) chunked_transfer_encoding off;- 如使用 proxy_pass,确认后端未设置
Content-Encoding: gzip,否则需先解压(Nginx 原生不支持自动解压)
另外,确保响应字符集明确(如 charset utf-8;),避免中文或特殊符号替换错位。










