报文分帧的方式
Transfer-Encoding 描述报文自身的传输编码,是逐跳字段而不是内容属性。HTTP/1.1 中唯一的标准取值是 chunked:把正文切成若干块,每块前面带十六进制长度,最后以长度 0 的块结束。它的价值在于长度未知时也能流式发送——服务端边生成边推送,不必先缓冲整个响应。
基本信息
| 方向 | 请求与响应都可出现,属于逐跳字段 |
|---|---|
| 规范 | RFC 9110 §6.1,报文分帧见 RFC 9112 §6.1 |
| 标准取值 | chunked(分块),历史值 gzip 与 compress 已废弃 |
| HTTP/2 及以上 | 不再使用 chunked,帧自带长度,仅保留 trailers 能力 |
| 与 Content-Length | 同一报文里两者不能同时出现 |
分块报文结构
| 片段 | 内容 | 说明 |
|---|---|---|
| 起始行 | HTTP/1.1 200 OK | 之后跟 Transfer-Encoding: chunked |
| 块头 | 十六进制长度加换行 | 如 1a 表示后续 26 字节数据 |
| 块数据 | 原始数据加换行 | 长度必须与块头声明一致 |
| 结束块 | 长度为 0 的块 | 其后的空行结束报文,可在其间放 trailer 字段 |
分块响应示例
分块响应示例
HTTP/1.1 200 OK
Transfer-Encoding: chunked
1a
(26 字节数据)
15
(21 字节数据)
0
# 每个块:十六进制长度 + 换行 + 数据 + 换行;0 长度块表示结束
# 流式接口(SSE、日志推送)依赖这种边生成边发送的能力
curl -sN https://example.com/stream # -N 关闭 curl 自身的输出缓冲典型使用场景
- 服务端流式输出:SSE、大文件边读边发、日志实时推送
- 不知道响应总长度时的默认做法,避免先算长度再发送
- 排查「响应卡住不结束」:看分块流是否缺少 0 长度结束块
- 网关升级协议时确认 chunked 是否被正确解包再重编码
报文中同时出现 Transfer-Encoding 与 Content-Length 是请求走私的经典素材:不同实现选取哪一个来解释边界,会出现两个解析器看到的报文长度不一致;网关应直接拒绝这种歧义消息。
chunked 是编码不是压缩:它只负责切块与定界,压缩仍由 Content-Encoding 承担,两者可以并存且顺序有讲究——先压缩再分块发送。