sub_filter是nginx用于响应体字符串替换的模块,需编译启用,支持多级字面替换、大小写敏感控制及mime类型限定,但不支持正则、变量插值和二进制内容。

sub_filter 是 Nginx 的一个模块指令,用于在响应体(response body)中查找并替换指定字符串。它常被用在反向代理场景中,解决后端服务返回的 HTML 页面里含有**硬编码的绝对链接**(如 http://backend.example.com/static/)导致前端无法直接访问的问题。
启用 sub_filter 模块的前提
Nginx 默认不编译 ngx_http_sub_module,需确认已启用:
- 执行
nginx -V 2>&1 | grep -o with-http-sub-module,有输出说明已支持; - 若无,需重新编译 Nginx 并添加
--with-http_sub_module参数; - OpenResty 默认包含该模块,可直接使用。
基础用法:单次替换与大小写敏感控制
最简配置示例如下:
location / {
proxy_pass https://origin.example.com/;
sub_filter 'https://origin.example.com/' 'https://cdn.example.com/';
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
}
关键点说明:
-
sub_filter_once off:允许全局多次替换(默认为on,只替换第一个匹配项); -
sub_filter_types:明确指定哪些 MIME 类型的内容参与替换,默认仅text/html; - 替换是**严格字面匹配**,不支持正则,也不区分协议/端口以外的上下文(比如不能只换域名不换路径)。
处理多级替换与嵌套链接问题
一个页面可能含多种硬编码前缀(如 API 地址、资源路径、跳转 URL),需链式配置多个 sub_filter:
sub_filter 'https://api.origin.com/v1/' 'https://api.example.com/v1/'; sub_filter 'https://static.origin.com/' 'https://assets.example.com/'; sub_filter 'http://origin.com/' 'https://example.com/'; sub_filter_once off;
注意顺序:
- 长匹配优先,避免短前缀误替长链接(如先替换
origin.com/api,再替换origin.com); - 所有
sub_filter指令必须在同一作用域(如同一个location块内),否则后定义的不会生效; - 不支持变量插值(如
$host),所有替换内容必须写死。
配合 sub_filter_last_modified 修复缓存失效问题
替换响应体后,原始 Last-Modified 或 ETag 头仍指向未修改内容,可能导致浏览器缓存旧版 HTML。可手动清除或重写:
- 加
proxy_set_header Accept-Encoding "";关闭后端 gzip(因 sub_filter 不处理压缩响应); - 用
add_header Last-Modified "";清空原头,或设为当前时间:add_header Last-Modified $date_gmt;; - 禁用 ETag:
proxy_hide_header ETag;,并添加add_header ETag "";(部分客户端会忽略空值,更稳妥是用etag off;在 http 块中全局关闭)。
sub_filter 是轻量、低侵入的链接重写方案,适合静态资源路径、CDN 回源、灰度发布等场景。它不改变请求逻辑,只在响应流出前做文本手术,性能开销小但能力有限——不支持正则、不处理二进制内容、不兼容 chunked transfer encoding(需确保后端关闭流式响应或 Nginx 缓存完整 body)。











