sub_filter需配合gzip off、sub_filter_types、sub_filter_once等配置才能生效,且安全替换HTTP脚本链接须限定上下文(如

nginx 的 sub_filter 指令可以在反向代理响应体中做字符串替换,但默认不处理 HTTPS 页面里硬编码的 http:// 第三方脚本链接(比如 <script src="http://cdn.example.com/js/lib.js"></script>),因为这类资源在浏览器中会因混合内容(Mixed Content)被直接阻止加载。要让页面正常运行,不能只靠替换 URL 协议,还需配合其他关键配置。
确保 sub_filter 能生效的基本前提
sub_filter 默认只对 text/html 类型响应起作用,且要求响应体未被压缩(gzip)。如果上游返回了 Content-Encoding: gzip,nginx 不会解压再替换,导致替换失效。
- 在 location 块中显式关闭 gzip 解压干扰:
gzip off;(或更稳妥地用gunzip on;启用解压,需编译时含 gunzip 模块) - 确认响应头为
Content-Type: text/html,必要时用sub_filter_types text/html application/xhtml+xml;扩展支持类型 -
sub_filter_once off;允许多次匹配(避免只替换第一个http://)
安全替换 HTTP 脚本链接的核心写法
单纯把 http:// 替成 https:// 风险高——可能误改非 URL 内容(如注释、JSON 字符串、CSS 中的 http:// 图片等)。应限定上下文,提高精准度:
- 匹配
<script> 标签内 <code>src</script>属性的 HTTP 地址:sub_filter '<script src="http://'%20'<script%20src=" https:></script> - 补充匹配单引号和自闭合写法:
sub_filter "<script src="http://%22%20%22<script%20src=" https:><br><code>sub_filter '<script src=http://' '<script src=https://';</script> - 若页面还引用了
或中的 HTTP 资源,按同样逻辑扩展(注意引号和空格边界)
必须同步处理的混合内容拦截问题
即使 HTML 中的脚本地址已改为 https://,若第三方 CDN 实际只支持 HTTP(即重定向到 HTTP 或证书不匹配),浏览器仍会拒绝加载。此时需验证目标域名是否真正支持 HTTPS:
- 用
curl -I https://cdn.example.com/js/lib.js检查能否返回200 OK和有效证书 - 若 CDN 不支持 HTTPS,替换协议无意义——应联系供应商升级,或改用支持 HTTPS 的备用 CDN
- 临时调试可用
Content-Security-Policy: upgrade-insecure-requests响应头,强制浏览器将所有 HTTP 请求升为 HTTPS(兼容性好,但仍是“尝试”,失败仍报错)
替代方案:用 proxy_redirect + rewrite 更可靠
对静态资源路径较规范的场景(如所有第三方脚本都来自固定域名),比 sub_filter 更健壮的做法是:在代理响应头中重写 Location 或用 proxy_redirect,或在 location 中用 rewrite 拦截请求并跳转:
- 例如,将发往
http://cdn.example.com/的请求,在 nginx 层rewrite ^/(.*)$ https://cdn.example.com/$1 break; - 或配合
map指令动态判断 Host,统一重写资源请求协议 - 优势:不依赖 HTML 解析,不担心正则误伤,性能更高,也规避了
sub_filter对 chunked 编码、流式响应的支持限制











