Skip to main content

7. Transfer Codings (传输编码)

传输编码名称 (transfer coding names) 用于指示已应用、可以应用或可能需要应用于消息内容的编码转换,以确保通过网络"安全传输"。这与内容编码不同,因为传输编码是消息的属性,而不是正在传输的表示的属性。

所有传输编码名称都不区分大小写,并且应该在 HTTP 传输编码注册表中注册,如第 7.3 节所定义。它们用于 Transfer-Encoding (第 6.1 节) 和 TE ([HTTP] 第 10.1.4 节) 头字段(后者也定义了 "transfer-coding" 语法)。

7.1. Chunked Transfer Coding (分块传输编码)

分块传输编码 (chunked transfer coding) 包装内容以便将其作为一系列块传输,每个块都有自己的大小指示符,后跟一个可选的尾部部分 (trailer section),其中包含尾部字段。分块使得能够将未知大小的内容流作为一系列长度界定的缓冲区传输,这使发送方能够保持连接持久性,并使接收方知道何时已接收到整个消息。

chunked-body   = *chunk
last-chunk
trailer-section
CRLF

chunk = chunk-size [ chunk-ext ] CRLF
chunk-data CRLF
chunk-size = 1*HEXDIG
last-chunk = 1*("0") [ chunk-ext ] CRLF

chunk-data = 1*OCTET ; a sequence of chunk-size octets

chunk-size 字段是一个十六进制数字字符串,指示 chunk-data 的大小(以八位字节为单位)。当收到 chunk-size 为零的块时,分块传输编码完成,后面可能跟着尾部部分,最后以空行终止。

接收方必须 (MUST) 能够解析和解码分块传输编码。

HTTP/1.1 没有定义任何限制分块响应大小的方法,以便中介可以确保缓冲整个响应。此外,如果在接收实现中不能准确表示非常大的块大小的值,可能会导致溢出或精度损失。因此,接收方必须 (MUST) 预期可能很大的十六进制数字,并防止由于整数转换溢出或由于整数表示导致的精度损失而导致的解析错误。

分块编码不定义任何参数。它们的存在应该 (SHOULD) 被视为错误。

7.1.1. Chunk Extensions (块扩展)

分块编码允许每个块紧跟在 chunk-size 之后包含零个或多个块扩展,以便提供每块元数据(例如签名或哈希)、中间消息控制信息或消息体大小的随机化。

chunk-ext      = *( BWS ";" BWS chunk-ext-name
[ BWS "=" BWS chunk-ext-val ] )

chunk-ext-name = token
chunk-ext-val = token / quoted-string

分块编码特定于每个连接,并且可能在任何更高级别的应用程序有机会检查扩展之前被每个接收方(包括中介)删除或重新编码。因此,块扩展的使用通常仅限于专门的 HTTP 服务,例如"长轮询" (long polling)(其中客户端和服务器可以对块扩展的使用有共同的期望)或用于端到端安全连接内的填充。

接收方必须 (MUST) 忽略无法识别的块扩展。服务器应该将请求中收到的块扩展的总长度限制为对所提供服务合理的数量,就像它对消息的其他部分应用长度限制和超时一样,如果超出该数量,则生成适当的 4xx (Client Error) 响应。

7.1.2. Chunked Trailer Section (分块尾部部分)

尾部部分允许发送方在分块消息末尾包含额外的字段,以便提供在发送内容时可能动态生成的元数据,例如消息完整性检查、数字签名或后处理状态。尾部字段的正确使用和限制在 [HTTP] 第 6.5 节中定义。

trailer-section   = *( field-line CRLF )

从消息中删除分块编码的接收方可以 (MAY) 选择性地保留或丢弃收到的尾部字段。保留收到的尾部字段的接收方必须 (MUST) 将尾部字段与收到的头字段分开存储/转发,或将收到的尾部字段合并到头部分。接收方禁止 (MUST NOT) 将收到的尾部字段合并到头部分,除非其相应的头字段定义明确允许并指示如何安全地合并尾部字段值。

7.1.3. Decoding Chunked (解码分块)

解码分块传输编码的过程可以用伪代码表示为:

length := 0
read chunk-size, chunk-ext (if any), and CRLF
while (chunk-size > 0) {
read chunk-data and CRLF
append chunk-data to content
length := length + chunk-size
read chunk-size, chunk-ext (if any), and CRLF
}
read trailer field
while (trailer field is not empty) {
if (trailer fields are stored/forwarded separately) {
append trailer field to existing trailer fields
}
else if (trailer field is understood and defined as mergeable) {
merge trailer field with existing header fields
}
else {
discard trailer field
}
read trailer field
}
Content-Length := length
Remove "chunked" from Transfer-Encoding

7.2. Transfer Codings for Compression (用于压缩的传输编码)

以下用于压缩的传输编码名称由与其相应内容编码相同的算法定义:

compress (和 x-compress) 参见 [HTTP] 第 8.4.1.1 节。

deflate 参见 [HTTP] 第 8.4.1.2 节。

gzip (和 x-gzip) 参见 [HTTP] 第 8.4.1.3 节。

压缩编码不定义任何参数。这些压缩编码中任何一个的参数存在应该 (SHOULD) 被视为错误。

7.3. Transfer Coding Registry (传输编码注册表)

"HTTP 传输编码注册表" (HTTP Transfer Coding Registry) 定义了传输编码名称的命名空间。它维护在 https://www.iana.org/assignments/http-parameters

注册必须 (MUST) 包括以下字段:

  • 名称 (Name)

  • 描述 (Description)

  • 规范文本指针 (Pointer to specification text)

传输编码的名称禁止 (MUST NOT) 与内容编码的名称 ([HTTP] 第 8.4.1 节) 重叠,除非编码转换相同,如第 7.2 节中定义的压缩编码的情况。

TE 头字段 ([HTTP] 第 10.1.4 节) 在多个传输编码可接受时使用名为 "q" 的伪参数作为排名值。未来的传输编码注册不应该 (SHOULD NOT) 定义名为 "q" 的参数(不区分大小写),以避免歧义。

要添加到此命名空间的值需要 IETF 审查 (IETF Review)(参见 [RFC8126] 第 4.8 节),并且必须 (MUST) 符合本规范中定义的传输编码的目的。

不鼓励使用程序名称来标识编码格式,未来的编码应避免这样做。

7.4. Negotiating Transfer Codings (协商传输编码)

TE 字段 ([HTTP] 第 10.1.4 节) 在 HTTP/1.1 中用于指示除分块之外,客户端愿意在响应中接受哪些传输编码,以及客户端是否愿意在分块传输编码中保留尾部字段。

客户端禁止 (MUST NOT) 在 TE 中发送分块传输编码名称; 分块对于 HTTP/1.1 接收方始终是可接受的。

以下是三个 TE 使用示例:

TE: deflate
TE:
TE: trailers, deflate;q=0.5

当多个传输编码可接受时,客户端可以 (MAY) 使用不区分大小写的 "q" 参数按偏好对编码进行排名(类似于内容协商字段中使用的 qvalues; 参见 [HTTP] 第 12.4.2 节)。排名值是 0 到 1 范围内的实数,其中 0.001 是最不偏好的,1 是最偏好的; 值为 0 表示"不可接受"。

如果 TE 字段值为空或不存在 TE 字段,则唯一可接受的传输编码是分块。没有传输编码的消息始终是可接受的。

关键字 "trailers" 表示发送方不会丢弃尾部字段,如 [HTTP] 第 6.5 节所述。

由于 TE 头字段仅适用于直接连接,TE 的发送方还必须 (MUST) 在 Connection 头字段 ([HTTP] 第 7.6.1 节) 中发送 "TE" 连接选项,以防止 TE 头字段被不支持其语义的中介转发。