# 1 HTTP 报文的组成部分

⚡ 30 秒速记

  • 请求报文:请求行(方法 + 路径 + 版本)→ 请求头空行请求体
  • 响应报文:状态行(版本 + 状态码 + 原因短语)→ 响应头空行响应体
  • 空行是关键分隔符 —— 头部变长,服务端靠它判断"头结束了";头里混入裸换行就能伪造分隔(HTTP 响应拆分攻击)
  • 头部过大会被网关拒绝(431),最常见的原因是 cookie 膨胀 —— 所以静态资源要放无 cookie 域名
  • Content-LengthTransfer-Encoding: chunked 二选一,流式响应用后者,所以下载进度条算不出百分比
  • ⚠️ HTTP/2 起头部被压成 HEADERS 帧、body 是 DATA 帧,不再是纯文本,但四部分的概念划分仍成立

HTTP/1.x 请求报文由请求行、请求头、空行和请求体组成,响应报文对应状态行、响应头、空行和响应体。 空行是头部与正文的关键分隔,因为头部长度不固定;字段中混入裸换行还可能造成 HTTP 响应拆分。工程上要留意头部过大可能触发 431,常见诱因是同域 cookie 膨胀,因此静态资源可使用无 cookie 域名。已知长度用 Content-Length,流式响应通常用 Transfer-Encoding: chunked;到了 HTTP/2,内容改由 HEADERSDATA 帧承载,但概念划分仍成立。

请求报文四部分:

POST /api/order HTTP/1.1              ← 请求行:方法 + 路径 + 协议版本
Host: api.example.com                 ← 请求头
Content-Type: application/json
Content-Length: 27
                                      ← 空行(关键分隔符)
{"id":123,"count":1}                  ← 请求体

响应报文四部分:

HTTP/1.1 200 OK                       ← 状态行:协议版本 + 状态码 + 原因短语
Content-Type: application/json        ← 响应头
Cache-Control: no-cache
                                      ← 空行
{"code":0,"data":{}}                  ← 响应体

那个空行为什么重要?

因为 HTTP 头部是变长的 —— 服务端读到一个空行才知道"头结束了,后面是 body"。这也是为什么头部字段不能包含裸的换行符,否则就能伪造出一个假的分隔,这类攻击叫 HTTP 响应拆分。

实际工作中会遇到的几个细节:

① 头部太大会被拒绝。 常见于 cookie 膨胀 —— 每个同域请求都会带上全域 cookie,塞多了轻松几 KB,超过网关限制就返回 431 或直接被断开。所以静态资源该放独立的无 cookie 域名。

② 自定义请求头有代价。 跨域时会触发 OPTIONS 预检,等于每个请求变两个往返;中间的 CDN/网关也可能不透传未知的头。能放 body 就别放头里。

webapp
公众号
开发者导航
切换夜间模式
点击侧边栏上一篇
点击侧边栏下一篇
折叠侧边栏
收起全部