HTTP 报文结构与状态码
大约 6 分钟
HTTP 报文结构与状态码
引言 在上一篇《万维网基石之HTTP》中,我们了解了 HTTP 是客户端与服务器之间的“沟通语言”。 那么,这门语言到底长什么样?当我们调用
fetch或axios发送一个请求时,网络底层到底传输了什么样的数据格式?如果出错了,那些神奇的数字(404, 502)到底在暗示什么? 今天,我们就来做一次“网络外科手术”,彻底解剖 HTTP 报文结构,并盘点那些前端每天都要打交道的状态码。
一、 HTTP 报文:网络世界里的“信封与信件”
HTTP 协议的通信过程,本质上就是客户端和服务端在互相传递“报文(Message)”。
为了方便理解,我们可以把 HTTP 报文想象成一封我们在现实生活中寄出的快递信件:
- 起始行(信封正面第一行):写着这封信是寄给谁的、寄加急还是平邮。
- 首部字段 Headers(信封上的其他信息):写着寄件人是谁、信件有多重、用什么语言写的。
- 空行(信封的封口):一个没有任何内容的空行,用来告诉对方“信封上的信息写完了,下面是信件正文”。
- 报文主体 Body(信封里的信纸/物品):你真正要传递的内容,比如一段 JSON 数据、一张图片。
HTTP 报文分为两类:请求报文(Request) 和 响应报文(Response)。它们的结构非常相似,但细节略有不同。
1. 客户端发出的:请求报文 (Request Message)
当你在浏览器地址栏输入网址按回车,或者用 AJAX 发起 POST 请求时,浏览器会帮你拼装出这样一个纯文本格式的数据包:
POST /api/login HTTP/1.1 <-- [起始行]
Host: www.example.com <-- [首部 Headers 开始]
User-Agent: Mozilla/5.0 ...
Content-Type: application/json
Content-Length: 36 <-- [首部 Headers 结束]
<-- [空行 (CRLF)]
{"username":"admin","pwd":"123"} <-- [报文主体 Body]
手术刀解剖:
- 起始行(Request Line):由三部分组成,空格隔开。
- 方法 (Method):动词。比如这里的
POST,或者GET,PUT,DELETE。告诉服务器你想做什么动作。 - 请求目标 (URI/URL):名词。比如这里的
/api/login,告诉服务器你要操作哪个资源。 - HTTP 版本号:比如这里的
HTTP/1.1,告诉服务器我懂哪门语言。
- 方法 (Method):动词。比如这里的
- 首部字段(Headers):由
Key: Value的键值对组成。它是 HTTP 协议最灵活、最核心的部分(我们在下一篇会专门讲缓存和鉴权相关的 Headers)。 - 空行:极其重要!它是解析 HTTP 报文的界限,标志着 Headers 的结束和 Body 的开始。
- 报文主体(Body):你要传给后端的数据。注意:GET 请求通常没有 Body,只有 POST/PUT 等请求才有。
2. 服务器返回的:响应报文 (Response Message)
后端处理完你的请求后,会按同样的格式给你回一封信:
HTTP/1.1 200 OK <-- [起始行]
Date: Tue, 24 Oct 2023 10:00:00 <-- [首部 Headers 开始]
Server: Nginx/1.22
Content-Type: application/json
Set-Cookie: token=abcde; HttpOnly <-- [首部 Headers 结束]
<-- [空行]
{"code":0, "msg":"登录成功"} <-- [报文主体 Body]
手术刀解剖: 响应报文的区别主要在第一行(状态行 Status Line):
- HTTP 版本号:
HTTP/1.1。 - 状态码 (Status Code):数字。比如这里的
200,它是核心!告诉前端这次请求的结果是成功还是失败。 - 状态原因短语 (Reason Phrase):文本。比如这里的
OK,只是给人看的,机器只认前面的数字。
二、 前端背锅/甩锅指南:HTTP 状态码全解析
在日常开发中,当我们点开 Chrome DevTools 的 Network 面板看到满屏的红色报错时,第一时间就要看状态码。
状态码由 3 位数字组成,分为 5 大类。记住它们的分类,你能瞬间判断出这个 Bug 到底是前端的锅,还是后端的锅。
1. 【1xx】信息性状态码:看戏就好
- 含义:服务器正在处理请求,请客户端稍安勿躁。
- 前端感知:日常开发极少直接接触。
- 代表作:
101 Switching Protocols:前端发起 WebSocket 连接时,服务器同意把 HTTP 协议升级为 WebSocket 协议,就会返回 101。
2. 【2xx】成功状态码:皆大欢喜
- 含义:请求已被服务器成功接收、理解并接受。
- 代表作:
200 OK:最常见的成功状态码,GET 拿到了数据,POST 提交成功。201 Created:通常用于 POST/PUT,表示服务器成功创建了新的资源(比如新建了一个用户)。204 No Content:请求成功了,但服务器没有什么数据要返回给你(Body 为空)。前端注意:CORS 跨域的预检请求(OPTIONS)成功时,通常返回的就是 204。
3. 【3xx】重定向状态码:查缓存与跳转
- 含义:前端你需要进一步操作(通常是去另一个地址找,或者直接读本地缓存)才能完成请求。
- 代表作:
301 Moved Permanently(永久重定向):网站换域名了。前端大坑:浏览器会死死记住 301 缓存,下次你访问旧地址,浏览器连网都不上,直接内部跳转。302 Found(临时重定向):没登录想进后台,被临时踢到了/login登录页。- 🔥
304 Not Modified(未修改):前端性能优化核心! 协商缓存命中。服务器告诉你:“文件没改过,别下载了,直接用你本地硬盘里的旧文件吧”。(它的 Body 也是空的,极大地节省了带宽)。
4. 【4xx】客户端错误状态码:前端赶紧查代码!
- 含义:前端的锅! 你发送的请求有问题(参数拼错、没带 Token、格式不对),服务器拒绝处理。
- 代表作:
400 Bad Request:参数校验失败。比如后端要数字,你传了字符串。401 Unauthorized:身份验证失败。你没登录,或者 Token 过期了。前端通常要在 axios 拦截器里捕获 401,然后清除本地 Token 并跳回登录页。403 Forbidden:权限不足。你登录了,但我知道你是谁,你只是普通用户,不准调管理员接口。404 Not Found:找不到资源。你要么 URL 拼写错误,要么后端老哥还没把接口发上线。405 Method Not Allowed:方法用错了。后端写的是app.post('/hello'),你前端偏用axios.get('/hello')请求,直接报错。
5. 【5xx】服务器错误状态码:立刻截图找后端!
- 含义:后端的锅! 前端的请求完全合法完美,但后端代码写崩了,或者服务器挂了。
- 代表作:
500 Internal Server Error:最典型的后端报错。比如后端代码抛了“空指针异常”,或者 SQL 语句写错了。直接把截图扔给后端排查日志。502 Bad Gateway(网关错误):你请求打到了 Nginx(网关),但背后的真实服务器(如 Node.js 或 Java 进程)挂掉了没启动。Nginx 拿不到数据,只能给你退回 502。503 Service Unavailable:服务器超载了(双十一被挤爆了),或者正在停机维护。504 Gateway Timeout:后端处理得太慢了(比如查数据库卡了 60 秒),Nginx 等得不耐烦了,直接切断连接告诉你超时。
三、http 请求与响应图示


结语 HTTP 报文看似复杂,其实只是一封格式严格的“纯文本信件”。当我们弄懂了这封信的结构,并熟记了 4xx 和 5xx 状态码的区别,以后在面对控制台里红彤彤的报错时,我们就能做到胸有成竹、精准定位。
