HTTP 请求报文怎么看:从请求行到请求体
围绕HTTP 报文章节,拆解 HTTP 请求报文的请求行、请求头、空行和请求体,并说明请求排查时应该重点看哪些字段。
相关工具
HTTP 请求报文不是一整团文本
浏览器解析 URL、完成 DNS 查询、建立连接之后,真正发给服务器的是 HTTP 请求报文。文中把 HTTP 请求报文拆成三块:请求行、请求头、请求体。严格看,中间还有一个空行,用来分隔请求头和请求体。
这个结构很适合排查接口问题。很多人只看接口地址,发现请求失败就说“接口不通”。但服务器收到的不只是 URL,还有方法、路径、协议版本、头部字段和请求体。只要其中一块不符合预期,服务器处理结果就可能完全不同。
所以看 HTTP 请求报文时,不要从一长串文本里硬找。先看请求行,再看请求头,然后确认有没有空行和请求体。顺序清楚了,排查就不容易乱。

请求行说明要做什么,请求头补充上下文,请求体携带提交的数据。
请求行:先看方法、URI 和协议版本
请求行通常长这样:`GET /example/index.html HTTP/1.1`。它由请求方法、URI、协议版本组成。请求方法说明客户端想做什么,URI 说明要访问哪个资源,协议版本说明这次请求使用哪一版 HTTP。
文中列出的常见方法包括 GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE。日常开发里最常见的是 GET 和 POST。GET 多用于获取资源,POST 常用于提交数据。PUT、DELETE、PATCH 在 REST 风格接口里更常见。
排查时先看方法是否正确。接口文档写 POST,你实际发了 GET,服务器可能直接返回 405,也可能被网关拦掉。路径也要看清楚,`/user`、`/users`、`/api/user` 不是一回事。协议版本通常不需要每天手动处理,但在抓包或代理排查时也会出现。
请求头:用 key: value 补充请求信息
请求头由一行行 `key: value` 组成,用来告诉服务器更多细节。文中列了几个常见字段:Host、User-Agent、Accept、Content-Type、Authorization。这些字段看起来像附加信息,但很多接口问题就藏在这里。
`Host` 指定请求的目标主机和端口。虚拟主机、反向代理、网关转发都可能依赖 Host 判断请求属于哪个站点。`User-Agent` 标识客户端,比如浏览器、爬虫、脚本或某个工具。服务端有时会根据它做兼容处理或风控判断。
`Accept` 表示客户端能接收什么类型的响应。`Content-Type` 更容易出问题,它说明请求体是什么格式。你明明传了 JSON,却没有设置 `Content-Type: application/json`,后端就可能按表单或普通文本解析,结果自然不对。`Authorization` 常用于携带身份凭据,比如 Bearer Token,少了它就容易返回 401 或 403。

请求排查时,请求头经常比 URL 更能说明问题。
空行:一个很小但不能省的分隔符
HTTP 报文里,请求头和请求体之间有一个空行。它的作用是告诉接收方:请求头到这里结束,下面如果还有内容,就是请求体。文中也把空行单独列出来,因为它是解析报文时的边界。
平时用浏览器、Postman、curl 或代码库发请求,你很少手写这个空行,工具会帮你处理。但理解它有用。看原始报文、抓包数据、代理日志时,空行之前是头部,空行之后是主体。边界看错,就容易把请求体误认为请求头,或者反过来。
这也说明 HTTP 的早期文本报文为什么容易读:它不是二进制黑盒,而是一段按规则组织的文本。请求行、头部、空行、主体,每一块都有位置。
请求体:不是每个请求都有
请求体承载提交的数据,通常出现在 POST、PUT、PATCH 这类请求中。提交表单、上传文件、发送 JSON 参数,数据一般都在请求体里。GET 请求常见情况下没有请求体,参数更多放在 URL 查询字符串里。
请求体要和 `Content-Type` 一起看。`application/json` 通常表示 JSON;`application/x-www-form-urlencoded` 常见于普通表单;`multipart/form-data` 常见于文件上传。如果格式和头部不一致,后端解析会出问题。
排查时还要看请求体是否真的发出去了。有时前端代码里构造了参数,但拦截器、跨域预检、序列化或网关配置导致实际请求体为空。只看代码不够,最好看真实请求。
一个 GET 请求可以这样读
资料 给了一个 GET 请求示例:
GET /example/index.html HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 ... Chrome/88.0.4324.96 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8第一行说明它要用 GET 方法访问 `/example/index.html`,协议版本是 HTTP/1.1。`Host` 说明目标主机是 `example.com`。`User-Agent` 说明客户端是浏览器。`Accept` 说明客户端更希望接收 HTML、XML 等内容。
这个请求没有请求体,很符合页面访问场景。服务器收到后,会根据 Host、路径和其他头部判断该返回哪个资源。后续返回什么状态码、什么响应头、什么响应体,就属于 HTTP 响应报文的内容。
请求排查时按这个顺序看
第一,看方法和路径。文档写 POST,你发 GET;文档写 `/api/users`,你发 `/api/user`,后面的头部再正确也没用。第二,看认证字段。需要登录态、Cookie、Token 的接口,缺少凭据通常会失败。
第三,看 `Content-Type` 和请求体。JSON 接口要确认请求体确实是合法 JSON,表单接口要确认字段名和后端一致,上传接口要确认使用了正确的 `multipart/form-data`。第四,看 `Accept` 和服务端返回类型,尤其是同一个接口既可能返回 HTML 错误页,也可能返回 JSON 错误对象时。
最后再看代理、网关和跨域。很多请求不是直接打到业务服务,中间可能经过 Nginx、网关、负载均衡、鉴权服务。请求头在中间层被改掉或丢掉,也会导致业务服务拿到的内容和你以为的不一样。
把请求报文放回完整链路里理解
上一篇讲 DNS 时,浏览器还只是在找 IP。找到 IP、建立连接之后,请求报文才真正进入网络传输。它会被交给 TCP,继续封装成 TCP 段、IP 包、链路层帧,最后发到服务器。
也就是说,HTTP 请求报文属于应用层内容。它关心的是业务语义:访问哪个路径、用什么方法、带什么头、提交什么数据。TCP、IP、MAC 关心的是怎么可靠地把这段内容送过去。分清这两层,很多问题就不会混在一起。
学会看请求报文后,下一篇再看 HTTP 响应报文。请求报文回答“客户端发了什么”,响应报文回答“服务器怎么回”。这两块合起来,才是一完整的 HTTP 交互。
常见问题
GET 请求一定不能有请求体吗?
协议层面并不是绝对不能,但实际开发和服务端框架通常不建议依赖 GET 请求体。GET 参数一般放在 URL 查询字符串里。
Content-Type 和 Accept 有什么区别?
Content-Type 说明请求体是什么格式,Accept 说明客户端希望接收什么格式的响应。一个看发送内容,一个看接收偏好。
Authorization 和 Cookie 都能表示登录态吗?
可以。Authorization 常见于 Token 鉴权,Cookie 常见于浏览器会话。具体用哪种取决于系统设计。