sub_filter需配合proxy_set_header accept-encoding ""禁用压缩、显式声明sub_filter_types、关闭sub_filter_once才能生效;须避免与gzip冲突,精准匹配html片段,合理设置缓冲。

直接在 location 块里写 sub_filter 指令就能生效,但必须配齐几个关键指令,否则大概率不工作或拖慢响应。
确保后端返回的是未压缩明文sub_filter 只能处理解压后的文本流。如果上游返回了 Content-Encoding: gzip,Nginx 默认无法扫描替换:
- 在
location中加proxy_set_header Accept-Encoding "";,告诉后端“别压缩” - 用
curl -I https://your-domain/path确认响应头没有Content-Encoding: gzip - 不要同时开启
gzip on;和sub_filter,二者冲突
精准写匹配字符串,避免全页扫描sub_filter 是逐块扫描的,越宽泛越耗 CPU:
- 写带引号和属性名的完整片段,比如
sub_filter 'src="https://cdn.a.com/' 'src="/cdn/'; - 别只写
https://cdn.a.com/—— 容易误匹配、多扫描 - 不要跨行写 URL(后端模板里别把
href=拆成两行) - 不支持通配符或正则,越像真实 HTML 片段,命中越快越稳
只对真正需要的类型启用替换
默认只处理 text/html,其他类型必须显式声明:
-
sub_filter_types text/html text/css application/javascript; - 别写
*或留空,否则 Nginx 会对图片、字体、JSON 也尝试扫描,白耗资源 - 纯静态资源路径(如
/static/、/images/)建议跳过sub_filter,用root或alias直接返回
控制替换范围和次数
-
sub_filter_once off;才能替换页面中所有匹配项(默认只换第一个) - 每条
sub_filter按书写顺序执行,不支持循环或条件判断 - 多条替换时注意顺序,避免前一条替换结果被后一条再次匹配(比如先替
a.com再替b.a.com就可能出错)
缓冲设置要合理,别为了“保险”盲目调大
- 保持
proxy_buffering on;默认即可 -
proxy_buffers 4 8k;已足够应付多数 HTML(一般不到 200KB) - 避免设
proxy_buffer_size 128k;这类过大值,首字节延迟会明显上升 - 如果后端返回极小响应(如 JSON API),可考虑
proxy_buffering off;改为流式处理,但此时首处匹配后就不再扫描后续块











