58
www.e7ai.com
当前还没有回复,欢迎成为第一个参与讨论的人。
Nginx不是爆发了漏洞吗,然后我就把服务器的Nginx升级到最新版本:V1.31。

主服务器和CDN反代服务器都升级了。结果这两天发现报错,反代的静态html文件无法正常访问,出现乱码。

因为我的规则是将文件拉取到反代服务器上保存,只有新增的页面出现问题,之前拉取的文件是正常的。那么可以确定是升级Nginx导致的。
你的 Nginx 反代配置中,HTML 页面乱码的根本原因是:
上游服务器返回了 gzip 压缩的响应体,proxy_store 将压缩后的二进制数据原样保存到磁盘。当 Nginx 从本地磁盘读取缓存文件返回给客户端时,没有携带正确的 Content-Encoding 头,浏览器把压缩后的二进制数据当作普通文本渲染,导致乱码。
流程如下:
ts上游(HTTPS) → 返回 gzip 压缩的 HTML
→ proxy_store 原样写入磁盘(压缩态)
客户端请求 → Nginx 读磁盘文件 → 直接返回压缩二进制 → 浏览器无法解码 → 乱码
然后我又和AI探讨了一下为什么升级Nginx会出现这个问题。
新版本 Nginx 对 HTTP/1.1 规范遵循更严格**,导致上游服务器默认返回了 gzip 压缩内容。
旧版 Nginx 的 proxy_pass 默认不会自动向上游发送 Accept-Encoding: gzip 头,或者上游服务器认为代理不需要压缩内容,因此返回的是未压缩的纯文本 HTML。
从 Nginx 1.7 及以后版本开始,proxy_pass 默认会透传客户端的 Accept-Encoding 请求头给上游服务器。现代浏览器都会发送:
textAccept-Encoding: gzip, deflate, br
上游服务器(如 Apache、Nginx、CDN 等)收到这个头后,会返回 gzip 压缩的响应体,并附带响应头:
textContent-Encoding: gzip
proxy_store 的机制是原样保存响应体到磁盘,但它不会保存响应头。所以:
text上游返回:gzip 压缩的 HTML + Content-Encoding: gzip proxy_store 保存:只存了压缩后的二进制数据(丢失了 Content-Encoding 头) 客户端再次请求: Nginx 从磁盘读取文件 → 直接返回压缩二进制 但响应头中没有 Content-Encoding: gzip 浏览器以为是普通文本 → 显示乱码
| 场景 | 结果 |
|---|---|
旧版 Nginx 未透传 Accept-Encoding |
上游返回纯文本,proxy_store 保存纯文本,正常显示 |
新版 Nginx 透传了 Accept-Encoding |
上游返回 gzip 压缩内容,proxy_store 保存压缩二进制但丢头,乱码 |
你可以通过以下方式验证:
bash# 1. 直接 curl 上游,看是否返回压缩内容
curl -I -H "Accept-Encoding: gzip" https://www.xxx.com/
# 如果看到 Content-Encoding: gzip,说明上游确实会压缩
# 2. 查看 proxy_store 保存的缓存文件
file /www/wwwroot/cdn.xxx.com/tmp/some.html
# 如果显示 "gzip compressed data",就确认了问题
在 location 块中添加:
nginxproxy_set_header Accept-Encoding "";
这会覆盖客户端传来的 Accept-Encoding 头,告诉上游服务器:不要返回压缩内容,从而确保 proxy_store 保存的是纯文本 HTML。
| 旧版本 Nginx | 新版本 Nginx | |
|---|---|---|
Accept-Encoding 透传 |
否/不完整 | 是(符合 HTTP/1.1 规范) |
| 上游返回 | 纯文本 HTML | gzip 压缩 HTML |
proxy_store 保存 |
纯文本 | 压缩二进制(丢失编码头) |
| 结果 | 正常显示 | 乱码 |
这是 Nginx 升级后的行为变更,不是你的配置写错了。添加 proxy_set_header Accept-Encoding ""; 即可解决。