Skip to content

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

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