Nginx的If-Range处理是断点续传稳定性的关键,它依据强ETag或Last-Modified校验决定返回206或200;常见问题包括弱ETag、Nginx覆盖ETag、gzip干扰及If-Range头丢失,需通过禁用自动ETag、透传If-Range、关闭Range响应gzip等协同配置修复。

Nginx 对 If-Range 头的处理是断点续传(Range 请求)能否稳定工作的关键一环。它不像 Range 那样直接触发分片响应,而是作为“条件开关”:只有当资源未变更时,才允许返回 206;否则退化为完整响应(200)。这个校验逻辑若与 ETag 或 Last-Modified 不匹配,就会导致拖拽卡顿、下载中断或静默降级为全量传输。
If-Range 的两种校验模式及触发条件
Nginx 支持两种 If-Range 校验方式,按优先级顺序自动选择:
-
强 ETag 优先:若响应头中含不带
W/前缀的 ETag(如ETag: "a1b2c3"),且请求中If-Range: "a1b2c3"匹配,则接受 Range 请求,返回 206 -
Last-Modified 回退:若无强 ETag,或 ETag 不匹配,Nginx 会检查
If-Range值是否为合法 HTTP 日期格式(如Wed, 21 Oct 2025 07:28:00 GMT),并比对资源最后修改时间(mtime)。匹配则返回 206;不匹配则返回完整 200 响应
常见冲突场景与根因
以下情况会导致 If-Range 校验失败,表现为明明发了 Range + If-Range,却收到 200 而非 206:
-
后端生成弱 ETag:如 Express 默认用
W/"mtime-size",Nginx 视其为不可靠,跳过 ETag 校验,直接走 mtime 比对——而集群节点文件系统时间可能微差,造成误判 -
Nginx 自动覆盖 ETag:默认开启
etag on;时,Nginx 会基于文件 mtime + size 重写 ETag,覆盖上游强 ETag,破坏一致性 - gzip 干扰 If-Range 处理:启用 gzip 后,Nginx 可能对 206 响应尝试压缩,但 RFC 明确禁止对分块响应做 gzip 编码,导致内部校验异常或响应截断
-
代理链中 If-Range 丢失:反向代理场景下,
$http_if_range默认不透传,后端收不到该头,无法配合校验
精准配置修复方案
要让 If-Range 稳定生效,需协同控制 ETag 来源、头部透传与压缩策略:
-
禁用 Nginx 自动 ETag 生成:在对应 location 中添加
etag off;,避免覆盖上游强 ETag -
强制透传 If-Range 头(代理场景):
proxy_set_header If-Range $http_if_range;必须显式配置,不能依赖默认 -
关闭 Range 响应的 gzip:对大文件或已知支持 Range 的路径,加
gzip_disable "Range";或更稳妥地,用gzip off;配合location ~ \.(mp4|zip|iso|pdf)$ { gzip off; } -
统一 mtime 校验基准(不得已时):若必须依赖 Last-Modified,确保所有节点文件系统时间同步(NTP),并在后端响应中显式设置
Last-Modified为 UTC 时间戳
验证是否真正生效
仅看配置不够,必须用真实请求验证行为一致性:
- 先获取资源完整响应:
curl -I https://site.com/video.mp4,确认含ETag: "xxx"和Accept-Ranges: bytes - 模拟有效 If-Range 请求:
curl -I -H "Range: bytes=0-1023" -H 'If-Range: "xxx"' https://site.com/video.mp4,应返回206 Partial Content且含Content-Range - 模拟失效 If-Range 请求:
curl -I -H "Range: bytes=0-1023" -H 'If-Range: "wrong"' https://site.com/video.mp4,应返回200 OK(非 412)


















