Nginx 的 sub_filter 指令可在响应返回前对文本类型内容实时替换,适用于修正后端硬编码的 CDN 域名等问题;需确保 Content-Type 为 text/html 等文本类型、禁用 gzip 压缩、设置 sub_filter_types 和 sub_filter_once off,并注意锚定上下文以防误替。

Nginx 的 sub_filter 指令可以在响应体返回给客户端前,对 HTML(或其他文本类型)内容做实时字符串替换,非常适合在反向代理层统一修正后端静态页中硬编码的 CDN 域名、路径或协议问题,无需修改源站代码。
启用 sub_filter 的基本前提
该指令仅对 text/html 和 text/css 等明确声明为文本类型的响应生效,默认不处理 gzip 压缩内容。需确保:
- 后端响应头包含
Content-Type: text/html; charset=utf-8(或类似文本类型) - 关闭或绕过响应压缩:
gzip off;或使用sub_filter_types显式扩展支持类型 - 启用
sub_filter_once off;才能替换页面中所有匹配项(默认只换第一个)
替换 CDN 域名(最常用场景)
假设后端 HTML 中写死:<img src="https://old-cdn.example.com/logo.png" alt="如何利用 sub_filter 指令实现在代理层动态修正后端静态页中的 CDN 链接" >,你想全局替换为 https://cdn.yourdomain.com:
location / {
proxy_pass https://backend;
sub_filter 'https://old-cdn.example.com' 'https://cdn.yourdomain.com';
sub_filter_types text/html text/css application/javascript;
sub_filter_once off;
proxy_set_header Accept-Encoding '';
}
注意:proxy_set_header Accept-Encoding '' 是关键,它告诉后端“我不接受压缩”,避免 Nginx 对已压缩响应跳过 sub_filter。
安全替换 + 防止误伤的技巧
直接替换字符串可能误改 URL 参数、注释或 JS 字符串。推荐组合策略:
- 用更精确的上下文锚定,例如替换
src="https://old-cdn.example.com/→src="https://cdn.yourdomain.com/,减少干扰 - 配合
sub_filter_last_modified on;(Nginx 1.13.5+)让替换后的响应保留原始 Last-Modified 头,利于缓存 - 若需大小写不敏感替换,Nginx 原生不支持,可改用
sub_filter+ Lua 模块(如ngx_http_lua_module)或升级到 OpenResty 使用ngx.re.gsub
调试与验证要点
替换失败常见原因:
- 响应被 gzip 压缩且未禁用:
curl -I查看是否有Content-Encoding: gzip - Content-Type 不在
sub_filter_types列表中,特别是 JSON API 返回 HTML 片段时容易忽略 - 后端设置了
Content-Security-Policy或X-Content-Type-Options: nosniff导致浏览器拒绝执行篡改后的内容(极少,但需留意) - 替换后链接路径出错,建议先用
sub_filter替换为带明显标识的测试域名(如https://test-cdn.local),确认位置准确再切正式域名
不复杂但容易忽略细节,关键是控制响应类型、压缩状态和替换粒度。用好 sub_filter,能让老旧静态站点快速接入新 CDN 架构,零代码改造落地。

















