最轻量方案是在nginx代理层用sub_filter批量替换http://为https://,需关闭gzip/brotli压缩、扩展sub_filter_types、精准匹配src/href边界、关闭sub_filter_once,并配合csp upgrade-insecure-requests头覆盖js动态拼接场景。

直接在 Nginx 代理层用 sub_filter 把响应体里的 http:// 脚本链接批量替换成 https://,是最轻量、零改后端代码的解决方式。关键不是“能不能换”,而是“换得全不全、稳不稳”。
必须关闭响应压缩
gzip 或 brotli 压缩后的响应是二进制流,sub_filter 只处理明文文本。只要后端返回了 Content-Encoding: gzip,替换就完全失效。
- 在对应
location块中加gzip off;(最稳妥) - 或全局禁用压缩(如仅用于此代理场景)
- 不推荐依赖
gunzip on,它有兼容性风险且增加开销
显式声明可处理的 MIME 类型
sub_filter 默认只作用于 text/html,但脚本引用常出现在 text/javascript、application/json(如配置接口)、甚至内联 text/css 中。
- 加上
sub_filter_types text/html text/javascript application/json text/css; - 若不确定类型,可用
sub_filter_types *;强制覆盖所有响应(对图片、PDF 等二进制内容无影响,但会多一次无效扫描)
精准替换 HTTP 脚本地址
只替换 http:// 开头的脚本引用,避免误伤其他字段(比如 JSON 里的 "http_status": 200)。重点匹配 <script src="http://%20%E5%92%8C%20src=" http:> 这类上下文更安全,但 <code>sub_filter</script> 不支持正则捕获,所以退而求其次——用带边界的静态字符串:
sub_filter 'src="http://' 'src="https://';sub_filter "src='http://" "src='https://";-
sub_filter 'href="http://' 'href="https://';(兼顾 CSS/Link 引用) - 务必加
sub_filter_once off;,否则只改第一个匹配项
处理动态拼接路径的边界情况
有些前端会用 JS 拼接 URL,例如 document.write('<script src="'%20+%20protocol%20+%20'//cdn.com/a.js</script>')%E3%80%82%E8%BF%99%E7%B1%BB%E6%97%A0%E6%B3%95%E8%A2%AB%20sub_filter%20%E8%A7%A6%E5%8F%8A%E3%80%82
- %0A%20%20
- %E9%9C%80%E9%85%8D%E5%90%88%20
Content-Security-Policy:%20upgrade-insecure-requests%20%E5%93%8D%E5%BA%94%E5%A4%B4 %0A%20%20 - %E6%B5%8F%E8%A7%88%E5%99%A8%E8%87%AA%E5%8A%A8%E5%B0%86%E9%A1%B5%E9%9D%A2%E5%86%85%E6%89%80%E6%9C%89%20
http://%20%E8%AF%B7%E6%B1%82%E5%8D%87%E4%B8%BA%20https://%0A%20%20 - %E8%BF%99%E6%98%AF%20W3C%20%E6%A0%87%E5%87%86%E6%96%B9%E6%A1%88%EF%BC%8C%E4%B8%8E%20
sub_filter%20%E5%BD%A2%E6%88%90%E4%BA%92%E8%A1%A5%EF%BC%8C%E8%A6%86%E7%9B%96%E9%9D%99%E6%80%81%E6%9B%BF%E6%8D%A2%E7%9B%B2%E5%8C%BA %0A











