Hypertext Transfer Protocol (HTTP/1.1): Range Requests
1. Introduction
HTTP 客户端经常会遇到数据传输中断的情况,例如请求被取消或连接断开。当客户端已保存部分表示时,可以在后续请求中请求剩余部分,而不是重新传输整个表示。此外,存储空间有限的设备也可以只请求较大表示的一部分,如大型文档的一页或嵌入图片的尺寸。
本文件定义了 HTTP/1.1 的范围请求、部分响应以及 multipart/byteranges
媒体类型。范围请求是 HTTP 的一个可选功能,设计为即使接收方不支持该功能,也可以像处理普通 GET 请求一样回应,而不影响互操作性。部分响应通过一个独特的状态码指示,以避免缓存将其误认为是完整响应。
虽然范围请求机制设计为允许扩展范围类型,但本规范仅定义了字节范围请求。
2. Range Units
表示可以根据其媒体类型的结构划分为子范围。这种“范围单位”用于 Accept-Ranges
响应头字段以显示对范围请求的支持, Range
请求头字段以划定请求的表示部分,以及 Content-Range
负载头字段以描述传输的表示部分。
2.1 Byte Ranges
由于表示数据在负载中作为八位字节序列传输,字节范围对任何可通过 HTTP 传输的表示都是有意义的。“字节”范围单位用于表示数据的八位字节序列的子范围。
字节范围请求可以指定单个字节范围或单个表示中的多个范围。
2.2 Other Range Units
范围单位是可扩展的。新的范围单位应在 IANA 注册。
2.3 Accept-Ranges
Accept-Ranges
头字段允许服务器指示它支持目标资源的范围请求。
3. Range Requests
3.1 Range
在 GET 请求中的 Range
头字段修改方法语义,以请求传输所选表示数据的一个或多个子范围,而不是整个表示数据。
服务器可以忽略 Range
头字段,但起源服务器和中间缓存应尽可能支持字节范围,因为范围支持从部分失败的传输中高效恢复以及部分检索大型表示。服务器必须忽略在 GET 以外的请求方法中接收到的 Range
头字段。
如果所有前置条件都成立,服务器支持目标资源的 Range
头字段,并且指定的范围有效且可满足,服务器应发送 206(部分内容)响应,并包含一个或多个与请求的可满足范围对应的部分表示。
3.2 If-Range
If-Range
头字段允许客户端在表示未更改时发送请求的部分,否则发送整个表示。
4. Responses to a Range Request
4.1 206 Partial Content
206(部分内容)状态码表示服务器成功满足目标资源的范围请求,通过传输与请求的 Range
头字段中可满足的范围对应的一个或多个部分表示。
如果正在传输一个部分,服务器必须生成 Content-Range
头字段,描述所选表示的范围,并包含该范围的负载。如果正在传输多个部分,服务器必须生成一个 multipart/byteranges
负载,并在每个部分的头部区域生成 Content-Range
头字段。
4.2 Content-Range
Content-Range
头字段在单部分 206(部分内容)响应中发送,以指示所选表示的部分范围,在多部分 206 响应的每个部分中发送,以指示每个部分的范围,并在 416(范围不满足)响应中发送,以提供所选表示的信息。
4.3 Combining Ranges
如果连接提前关闭或请求使用了一个或多个范围规格,响应可能只传输表示的一个子范围。客户端可以将这些响应合并为一个更大的连续范围,但前提是它们都具有相同的强验证器。
4.4 416 Range Not Satisfiable
416(范围不满足)状态码表示请求的 Range
头字段中的所有范围都不重叠当前目标资源的范围,或请求的范围集合因无效范围或过多的小范围请求而被拒绝。
ABNF
Accept-Ranges = acceptable-ranges
Content-Range = byte-content-range / other-content-range
HTTP-date = <HTTP-date, see [RFC7231], Section 7.1.1.1>
If-Range = entity-tag / HTTP-date
OWS = <OWS, see [RFC7230], Section 3.2.3>
Range = byte-ranges-specifier / other-ranges-specifier
acceptable-ranges = ( *( "," OWS ) range-unit *( OWS "," [ OWS range-unit ] ) ) / "none"
byte-content-range = bytes-unit SP ( byte-range-resp / unsatisfied-range )
byte-range = first-byte-pos "-" last-byte-pos
byte-range-resp = byte-range "/" ( complete-length / "*" )
byte-range-set = *( "," OWS ) ( byte-range-spec / suffix-byte-range-spec ) *( OWS "," [ OWS ( byte-range-spec / suffix-byte-range-spec ) ] )
byte-range-spec = first-byte-pos "-" [ last-byte-pos ]
byte-ranges-specifier = bytes-unit "=" byte-range-set
bytes-unit = "bytes"
complete-length = 1*DIGIT
entity-tag = <entity-tag, see [RFC7232], Section 2.3>
first-byte-pos = 1*DIGIT
last-byte-pos = 1*DIGIT
other-content-range = other-range-unit SP other-range-resp
other-range-resp = *CHAR
other-range-set = 1*VCHAR
other-range-unit = token
other-ranges-specifier = other-range-unit "=" other-range-set
range-unit = bytes-unit / other-range-unit
suffix-byte-range-spec = "-" suffix-length
suffix-length = 1*DIGIT
token = <token, see [RFC7230], Section 3.2.6>
unsatisfied-range = "*/" complete-length