416 Range Not Satisfiable
用法
收到 416 Range Not Satisfiable 错误消息时,说明客户端使用 Range 头请求了部分内容。对于字节范围,如果指定范围的第一个字节大于资源的长度,就会返回此错误。
请求部分范围的原因之一是大文件传输,客户端希望分块下载文件。通过在请求中使用 Range 头,文件实际上可以分片、以任意顺序下载。
当服务器满足请求并返回所请求范围中至少一个作为资源子集时,返回 206 表示成功。服务器也可以选择忽略范围请求,并以 200 状态返回完整资源。
作为响应的一部分,服务器会创建一个 Content-Range 头,指明数据的当前长度:
Content-Range: bytes */512
分隔符 / 之前的星号 * 表示一个无法满足的范围,其后是资源的总大小。
SEO 影响
像 Google 这样的搜索引擎不会索引响应状态为 416 的 URL。此前已被索引的 URL 会从搜索结果中移除。
示例
客户端请求某资源的第 1000 到 2000 字节。由于该文件只有 512 字节长,服务器返回 416 Range Not Satisfiable。客户端利用服务器返回的关于总大小的信息,用有效范围重新构造请求。
请求
GET /documents/main HTTP/1.1
Host: example.com
Range: bytes=1000-2000
响应
HTTP/1.1 416 Range Not Satisfiable
Content-Range: bytes */512
服务器忽略该范围时的替代响应
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 512
<entire 512 bytes in message body>
如何修复
Range 头指定了一个超出资源边界的字节范围。最常见的原因是请求了超出文件末尾的字节(例如,从一个只有 512 字节的文件中请求第 1000-2000 字节)。
先核实资源大小。在构造范围请求之前,发送 HEAD 请求以读取 Content-Length 头。这样可以避免请求超出文件边界的字节。
检查字节范围的计算。字节范围从零开始索引,且两端都包含在内。一个 512 字节的文件的有效字节位置为 0 到 511。范围 bytes=0-511 请求整个文件。范围计算中的差一错误是 416 响应的常见来源。
处理资源变化。恢复下载时,服务器上的文件可能自上次部分请求以来已被更改或删除。对旧版本有效的范围对于更短或不同的文件会变得无效。恢复前重新核实资源大小。
移除 Range 头。当不需要部分内容时,去掉 Range 头以请求完整资源。服务器会改为返回带完整消息体的 200。
清除浏览器缓存。浏览器有时会缓存部分响应,并在后续访问时构造无效的范围请求。清除缓存会强制发起一个全新的完整请求。
服务端考量。有些服务器配置会限制哪些资源类型支持范围请求。核实服务器在目标资源的响应中发送 Accept-Ranges: bytes。当存在 Accept-Ranges: none 时,说明服务器完全不支持对该资源的部分请求。
媒体加载失败
浏览器中的视频和音频播放器会发送范围请求以流式播放媒体文件。播放期间出现 416 错误意味着播放器请求了超出文件边界的字节范围。这发生在媒体文件被替换为更短的版本、而播放器仍持有陈旧的 Content-Length 值时。重新加载页面会强制播放器在请求范围之前获取当前的文件大小。
代码参考
.NET
HttpStatusCode.RequestedRangeNotSatisfiable
Rust
http::StatusCode::RANGE_NOT_SATISFIABLE
Rails
:range_not_satisfiable
:requested_range_not_satisfiable
Go
http.StatusRequestedRangeNotSatisfiable
Symfony
Response::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE
Python3.5+
http.HTTPStatus.REQUESTED_RANGE_NOT_SATISFIABLE
Java
HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE
Apache HttpComponents Core
org.apache.hc.core5.http.HttpStatus.SC_REQUESTED_RANGE_NOT_SATISFIABLE
Angular
@angular/common/http/HttpStatusCode.RangeNotSatisfiable