应显式配置 sub_filter_types 限定 MIME 类型,仅放行 text/css、application/javascript、application/json 等必需类型,禁用 *;确保后端返回正确 Content-Type,配合 proxy_pass 时需关闭 gzip、启用缓冲并调大缓冲区。

要让 sub_filter 只处理真正需要改写的响应类型,核心是用 sub_filter_types 显式声明 MIME 类型,而不是依赖默认行为或盲目放开匹配范围。默认只处理 text/html,其他类型(如 CSS、JS、JSON)必须手动加入,否则替换根本不会触发。
只放行必需的 MIME 类型
明确列出你要处理的类型,例如:
sub_filter_types text/css application/javascript application/json;- 避免使用
sub_filter_types *;—— 它会让 Nginx 尝试对所有响应(包括二进制、SVG、压缩流甚至错误页)做字符串扫描,徒增 CPU 开销且易出错 - 注意拼写规范:
application/javascript是标准写法,text/javascript已过时,部分浏览器或工具可能不识别
确保后端返回正确的 Content-Type
即使你写了 text/css,如果后端返回的是 text/plain 或压根没设头,sub_filter 就会跳过该响应:
- 用
curl -I http://your-site/style.css检查实际响应头 - 静态文件可加
add_header Content-Type text/css;强制修正(仅限可控路径) - 动态接口建议在后端统一设置,比在 Nginx 层补救更可靠
配合 proxy_pass 使用时的关键约束
反向代理场景下,性能影响常来自隐性条件:
- 关闭响应压缩:
gzip off;或至少gzip_vary off;,因为压缩后的内容无法被sub_filter解析 - 启用缓冲:
proxy_buffering on;,并适当调大proxy_buffer_size和sub_filter_buffer_size(默认约 1MB),避免大响应被截断导致替换不全 - 若后端用 chunked 编码且无
Content-Length,需确认proxy_buffering已生效,否则流式响应可能漏处理
避免常见低效配置
这些写法看似方便,实则损害性能或稳定性:
- 把
sub_filter_types放在http块全局生效 → 导致所有 location 都额外扫描非目标类型,应尽量收窄到具体location - 多个
sub_filter规则叠加但未关sub_filter_once off→ 实际只替换首次匹配,后续内容无效,还白耗一次扫描 - 对含空格、特殊字符的路径做替换却未统一编码格式 → 可能因大小写或 URL 编码差异导致漏匹配,建议先规范后端输出










