Nginx sub_filter可修复混合内容,需关闭gzip或启用gunzip、显式设置sub_filter_types、精准匹配src/href属性中的http://、禁用ETag并关闭sub_filter_once。

使用 Nginx 的 sub_filter 指令可以在反向代理响应体中批量替换文本,从而将 HTTP 资源链接自动升级为 HTTPS,解决混合内容(Mixed Content)问题。但需注意:它仅适用于纯文本响应(如 text/html),且不处理内联脚本或动态生成的 URL。
确保 sub_filter 生效的基本前提
sub_filter 默认只对 text/html 类型响应生效,且要求响应未被压缩(gzip)。若后端返回了 Content-Encoding: gzip,Nginx 不会解压并修改响应体 —— 此时替换失效。
- 关闭后端的 gzip 压缩,或在 Nginx 中配置
gzip off;或gunzip on;(需编译时启用ngx_http_gunzip_module) - 显式设置
sub_filter_types text/html application/xhtml+xml;以支持常见 HTML 变体 - 确认响应头中
Content-Type确实包含text/html,可用curl -I验证
精准替换不安全的 script src 和 link href
直接全局替换 http:// 风险高(可能误改 JSON、注释、URL 参数等)。应聚焦于 HTML 标签属性中明确的资源引用:
- 替换
<script src="http://→<script src="https:// - 替换
<link rel="stylesheet" href="http://→<link rel="stylesheet" href="https:// - 用正则式需配合
sub_filter的扩展语法(Nginx ≥ 1.9.4 +--with-http_sub_module编译):sub_filter '<script src="http://' '<script src="https://';sub_filter '<link href="http://' '<link href="https://';
处理相对路径与协议相对 URL 的兼容性
现代页面多用 //example.com/js/app.js(协议相对 URL),这类地址在 HTTPS 页面中会自动继承协议,无需替换。重点应放在硬编码的 http:// 绝对地址上。
- 避免替换
http://出现在非属性值位置(如注释、JS 字符串、CSS 内容),可借助更严格的匹配模式,例如:sub_filter 'src="http://' 'src="https://';sub_filter 'href="http://' 'href="https://'; - 若页面含大量 JS 动态加载逻辑(如
document.write('<script src="http://...')),sub_filter无法覆盖,需前端修复
启用替换并防止缓存干扰
sub_filter 修改响应体后,原始 ETag 或 Last-Modified 头已失效,必须清除或重写这些头,否则浏览器可能加载旧缓存(含未替换的 HTTP 链接):
- 添加
sub_filter_once off;允许多次替换(默认只替换第一个匹配) - 禁用 ETag:
etag off; - 强制刷新缓存头(可选):
add_header Cache-Control "no-cache"; - 完整示例片段:
location / {
proxy_pass https://backend;
proxy_set_header Host $host;
sub_filter 'src="http://' 'src="https://';
sub_filter 'href="http://' 'href="https://';
sub_filter_once off;
sub_filter_types text/html application/xhtml+xml;
etag off;
add_header Cache-Control "no-cache";
}

















