4、HTTP协议抓包分析:HTTP请求与响应结构、状态码详解、Header字段分析

说到网络故障排查,HTTP协议绝对是咱们打交道最多的协议。你想想看,网页打不开、接口报错、上传下载慢……十有八九都跟HTTP脱不了干系。今天我就带你从抓包的角度,把HTTP的请求响应结构、状态码和Header字段彻底吃透。

我个人习惯,遇到HTTP相关的问题,第一件事就是打开Wireshark或者Charles抓个包看看。别急着猜,数据不会骗人。

4.1 HTTP请求与响应结构

HTTP的交互模型其实很简单:客户端发一个请求,服务端回一个响应。但就是这个简单的模型,里面藏着不少门道。

4.1.1 请求报文结构

一个标准的HTTP请求报文,由三部分组成:请求行、请求头、请求体。我截一个真实的抓包数据给你看:

GET /api/users HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Accept: application/json
Connection: keep-alive

(空行)
(请求体,GET请求通常没有)

注意看,请求行里包含了三个关键信息:方法(GET)、URI(/api/users)、协议版本(HTTP/1.1)。这三样缺一不可。

我的经验:抓包时如果看到请求行格式不对,比如缺少协议版本,那八成是客户端代码写错了。我曾经排查过一个案例,某App在低版本Android上发请求时,请求行末尾少了\r\n,导致服务端一直返回400。

4.1.2 响应报文结构

响应报文的结构跟请求类似,但第一行变成了状态行:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 128
Date: Mon, 15 Jan 2024 08:30:00 GMT

{"status":"success","data":[]}

状态行里包含了协议版本、状态码和原因短语。这里有个坑——原因短语其实不是必须的,但大多数服务器都会带上。我见过有些自定义服务器返回了"200 SUCCESS"而不是标准的"200 OK",结果某些严格的HTTP解析库直接报错。

4.2 状态码详解

状态码是服务端给客户端的「暗号」。搞懂了这些暗号,排查问题能快一倍。

分类 范围 含义 常见场景
1xx 100-199 信息性响应 100 Continue(继续发送请求体)
2xx 200-299 成功 200 OK、201 Created、204 No Content
3xx 300-399 重定向 301 Moved Permanently、302 Found、304 Not Modified
4xx 400-499 客户端错误 400 Bad Request、401 Unauthorized、403 Forbidden、404 Not Found
5xx 500-599 服务端错误 500 Internal Server Error、502 Bad Gateway、503 Service Unavailable

这里我重点说几个容易踩坑的状态码:

  • 301 vs 302:301是永久重定向,浏览器会缓存;302是临时重定向。我遇到过一个问题:某网站把HTTP到HTTPS的重定向配成了302,结果每次请求都要多一次跳转,页面加载慢了不少。
  • 304 Not Modified:这个状态码表示资源没变,可以直接用缓存。抓包时如果看到大量304,说明缓存策略生效了,不是故障。
  • 403 Forbidden:服务器知道你是谁,但不让你访问。跟401不同,401是「你没登录」,403是「你没权限」。
  • 502 Bad Gateway:这个在反向代理场景下很常见。说白了就是网关去后端拿数据时,后端没理它或者返回了非法数据。
避坑指南:我曾经排查过一个线上故障,客户端一直报500,但服务端日志里没有任何错误。抓包一看,原来是Nginx在转发请求时把Host头改掉了,后端根据错误的Host找不到对应的虚拟主机配置,直接返回了500。所以看到500别急着找后端,先看看中间件有没有搞鬼。

4.3 Header字段分析

Header字段是HTTP协议里信息量最大的部分。很多网络故障,光看Header就能定位问题。

4.3.1 通用Header

这些Header在请求和响应里都可能出现:

  • Date:报文生成的时间。我习惯用这个字段来排查时间同步问题。
  • Connection:控制连接管理。HTTP/1.1默认是keep-alive,如果看到Connection: close,说明这次请求结束后连接会断开。
  • Cache-Control:缓存策略。no-cache表示每次都要验证,no-store表示完全不缓存。

4.3.2 请求Header

请求Header里,有几个字段我每次抓包都会重点看:

Header字段 作用 抓包排查要点
Host 指定目标主机和端口 检查是否与DNS解析结果一致
User-Agent 标识客户端类型和版本 某些服务会根据UA返回不同内容
Referer 来源页面URL 防盗链、CSRF检查常用
Cookie 携带会话状态 检查是否丢失或过期
Authorization 认证凭证 检查Token是否有效、格式是否正确
Content-Type 请求体的媒体类型 常见值:application/json、application/x-www-form-urlencoded

嗯,这里要注意Content-Type。我见过一个案例,前端明明传的是JSON数据,但Content-Type写成了text/plain,后端解析不了,一直返回400。抓包一看,问题一目了然。

4.3.3 响应Header

响应Header里,这几个字段值得你特别关注:

  • Content-Length:响应体的大小。如果这个值跟实际数据大小不符,传输过程中可能发生了截断。
  • Transfer-Encoding: chunked:分块传输。服务端不知道响应体大小时会用这个,比如动态生成的内容。
  • Set-Cookie:服务端要求客户端设置Cookie。我排查登录问题时,第一个看的就是这个字段有没有正确返回。
  • Location:重定向的目标URL。配合3xx状态码使用。
核心思路:抓包分析HTTP故障,其实就是「对答案」——把客户端发出去的内容和服务端期望的内容做对比,把服务端返回的内容和客户端期望的内容做对比。Header字段就是这份「答案」的详细说明。

4.4 HTTP协议抓包实战流程

说了这么多理论,咱们来走一遍实战流程。我个人习惯按这个步骤来:

  1. 确定抓包范围:只抓目标进程或目标端口的流量,避免数据太多看花眼。
  2. 设置过滤条件:用http或tcp.port == 80过滤出HTTP流量。
  3. 重现问题:操作一遍出问题的流程,同时抓包。
  4. 定位请求:找到对应的HTTP请求,先看状态码。
  5. 分析请求Header:检查Host、Cookie、Content-Type等关键字段。
  6. 分析响应Header:检查Content-Type、Content-Length、Set-Cookie等。
  7. 查看请求体和响应体:确认数据内容是否符合预期。

下面这张图,是我总结的HTTP抓包分析决策流程:

HTTP抓包分析决策流程 开始抓包 过滤HTTP流量 找到目标请求 判断状态码 分析Header字段 检查请求体/响应体 定位故障原因 抓包工具推荐 Wireshark(全流量) Charles(HTTPS解密) Fiddler(Windows平台) 常见过滤表达式 http tcp.port == 80 http.request.method == "POST"

这个流程我用了好多年,基本覆盖了90%以上的HTTP故障场景。你刚开始用的时候可能会觉得步骤多,但多练几次就变成肌肉记忆了。

4.5 常见HTTP故障抓包案例

最后,我分享几个真实案例,帮你把前面讲的知识串起来。

案例一:接口返回400 Bad Request

抓包发现请求行是POST /api/login HTTP/1.1,看起来没问题。但仔细看请求Header,Content-Type写的是text/plain,而服务端期望的是application/json。改过来就好了。

案例二:页面一直加载中,最后超时

抓包发现有一个CSS文件的请求状态码是301,浏览器跟着重定向到了新地址。但新地址的响应Header里Content-Length写的是0,实际上文件内容没返回。排查发现是CDN配置错误,源站返回了空内容。

案例三:登录后马上被踢下线

抓包看到登录请求的响应里Set-Cookie设置了sessionid=abc123; Domain=.example.com; Path=/。但后续请求的Cookie里却没有这个sessionid。检查发现是前端代码在发请求时,把withCredentials设成了false,导致跨域请求不带Cookie。

我的习惯:每次排查完一个HTTP故障,我都会把抓包文件保存下来,标注好问题原因和解决方式。时间长了,这就是一本活字典。下次遇到类似问题,直接翻出来对比,效率高很多。

好了,HTTP协议抓包分析的核心内容就这些。记住,抓包不是目的,分析才是。多动手、多总结,你也能成为HTTP故障排查的高手。