应关闭Nginx自动生成ETag并透传上游强ETag,配置etag off;确保后端用内容哈希生成无W/前缀的强ETag;透传Range/If-Range头,禁用gzip压缩,验证完整响应与分片响应ETag一致且返回206。
当Nginx作为静态资源服务器或反向代理时,若后端(如Node.js、Python应用或CDN源站)生成了ETag,而Nginx默认启用
并基于文件元数据(mtime + size)重写ETag,会导致客户端发起Range请求(如视频分片下载、断点续传)时,因ETag不一致被服务端拒绝(返回416或500),核心原因是ETag与实际响应内容不匹配。
关闭Nginx自动生成ETag
Nginx默认在
、
或
块中启用ETag,它会覆盖上游响应头中的ETag。对于需透传原始ETag的场景(尤其是支持Range的资源),应显式禁用:
这样Nginx将不再修改或添加ETag头,上游服务返回的ETag(含W/前缀、内容哈希等)会被原样透传,确保Range请求校验逻辑一致。
确保上游服务正确生成强ETag
分片下载依赖强ETag(非弱ETag,即不以
开头)。若后端使用弱ETag(如基于文件修改时间生成),Range请求可能被拒绝。建议后端按以下方式生成ETag:
对完整资源内容计算SHA-256或MD5,格式为
(无W/)
避免仅用
组合,该方式无法保证内容一致性
若使用Express,可用
显式处理Range请求头透传
即使ETag正确,Nginx默认可能缓存或截断Range请求。需确保:
禁用对Range请求的缓存:
(反向代理场景)
透传Range和If-Range头:
(默认开启,但建议显式声明)
若启用了gzip压缩,需关闭对Range响应的压缩:
或更稳妥地,对静态资源禁用gzip(Range响应不支持gzip分段)
验证ETag与响应一致性
部署后用curl验证关键行为:
三者返回的ETag值必须完全一致,且分片响应状态码为206 Partial Content。
etag onhttpserverlocationlocation /static/ {
etag off; # 关键:禁止Nginx生成/覆盖ETag
# 其他配置...
}W/""" mtime + sizeres.set('ETag', `"${crypto.createHash('sha256').update(content).digest('hex')}"`)proxy_cache_bypass $http_range;proxy_pass_request_headers on;gzip_disable "MSIE [1-6]\.(?!.*SV1)";# 1. 检查完整响应ETag
curl -I https://www.php.cn/link/89f569993f4af498b320aaaf4eb610c3
2. 检查分片响应是否携带相同ETag且状态为206
curl -I -H "Range: bytes=0-1023" https://www.php.cn/link/89f569993f4af498b320aaaf4eb610c3
3. 确认If-Range请求成功(应返回206而非200)
curl -I -H "Range: bytes=1024-2047" -H "If-Range: \"abc123...\"" https://www.php.cn/link/89f569993f4af498b320aaaf4eb610c3
