3. HTTP协议与状态码归纳总结
HTTP协议,说白了就是API世界里的通用语言。
我刚开始接手后端项目时,总觉得状态码就是随便填个200完事,直到赶上一次线上故障——前端死活拿不到数据,日志里全是500,才逼着自己把这块啃透了。
3.1 请求-响应模型
每个HTTP请求都是一个完整的来回:客户端发请求,服务端回响应。中间没有僵尸连接,也没有默认开着的长通道。这是一种 无状态 协议,每次请求都独立,服务端不记得上一次谁来过。那怎么维持登录态?靠或Session,这是后面章节要聊的。
核心要点:HTTP是请求-应答模式,不持久,不记忆。
3.2 HTTP方法——你该用哪个?
我记得刚做API规范时,团队里有人用POST做一切,包括查询。我建议你尽量按照下面这张表来选,后期解耦会省很多力气。
| 方法 | 语义 | 幂等? | 典型场景 |
|---|---|---|---|
| GET | 读取资源 | 是 | 查询列表、获取单条 |
| POST | 创建资源 | 否 | 新增订单、注册用户 |
| PUT | 整体更新 | 是 | 替换用户全量信息 |
| PATCH | 部分更新 | 不一定 | 修改用户头像 |
| DELETE | 删除资源 | 是 | 取消订单 |
幂等,就是个保护伞。你发送10次DELETE和发送1次,结果一样。客户端重试时不需要担惊受怕。
3.3 状态码分类——一眼看懂服务端的“脸色”
状态码分成五类,每类代表一种语气。我习惯把它们想象成服务端说的话:
- 1xx(情报):还在处理中,别急。实际API中很少用到。
- 2xx(成功):事办成了,数据在这。
- 3xx(重定向):资源挪地方了,你跟着箭头走。
- 4xx(客户端错误):你发的东西有问题。
- 5xx(服务端错误):服务器自己崩了,跟你没关系。
你看,分类逻辑其实很简洁。下面这张图能把关系串起来:
3.4 常用状态码详解——把数字变成含义
下面是我在项目中经常打交道的几个,每个都有血有肉的故事。
| 状态码 | 含义 | 什么时候用? |
|---|---|---|
| 200 OK | 请求成功,响应体带数据 | GET/PATCH/PUT 返回资源 |
| 201 Created | 资源创建成功 | POST 后返回新资源 URI |
| 204 No Content | 处理成功,但没响应体 | DELETE 成功,或不需要回传数据的更新 |
| 301 Moved Permanently | 资源永久迁移 | API 版本迁移,旧 URL 跳转新 URL |
| 302 Found | 临时跳转 | 登录后重定向到首页 |
| 400 Bad Request | 客户端请求语法错误 | 参数缺失、JSON 格式不对 |
| 401 Unauthorized | 身份凭证无效 | 过期或未传 |
| 403 Forbidden | 有身份但没权限 | 普通用户试图删除管理员资源 |
| 404 Not Found | 资源不存在 | URL 错了,或者 ID 无效 |
| 500 Internal Server Error | 服务器内部错误 | 代码抛异常没捕获 |
| 502 Bad Gateway | 上游服务不响应 | Nginx 代理后端挂掉 |
| 503 Service Unavailable | 服务过载或维护 | 限流、熔断、停机更新 |
我建议你在API文档里明确标注每个接口可能返回的状态码。我在项目中吃过亏:前端误以为404就是“没数据”,结果有个接口的404其实是“没权限”。后来改成403,沟通成本立即下降。
3.5 RESTful API中的状态码实践
说实话,很多团队会把所有成功情况全回200,然后通过业务码区分。我个人不太推荐这种做法,因为HTTP状态码本身就是协议层的有力语义。举个例子:
不推荐:
// 删除成功也返回200,
// 但 body 里写 {"code": 0, "msg": "ok"}
推荐:
DELETE /api/users/123
→ 204 No Content
(无响应体)
你想想看,204 既干净又明确,客户端拿到后直接清除本地缓存就行,根本不用解析JSON。类似的经验我在重构一个遗留系统时验证过,改完后前端代码量减少了将近15%。
避坑指南:我曾经把一个重要的POST接口返回成200而非201,导致前端认定资源已存在直接复用旧数据,引发了一周的数据不一致故障。从那以后我定了个规矩:创建资源必返201,并且在响应头的Location字段带上新资源URL。
3.6 状态码选择速查表
下面这张表帮你快速决策,直接用就行:
| 操作 | 成功状态码 | 可能失败的状态码 |
|---|---|---|
| 查询单条 | 200 | 404, 401, 403 |
| 查询列表 | 200 | 401, 403 |
| 创建 | 201 | 400, 401, 403, 409(冲突) |
| 全量更新 | 200 或 204 | 400, 404, 401, 403 |
| 部分更新 | 200 或 204 | 400, 404, 401, 403 |
| 删除 | 204 | 404, 401, 403 |
关键点:状态码是协议的承诺。你用对了,客户端、网关、监控工具都能理解你,整个系统会更整齐。我见过最乱的项目,一个接口在不同情况下分别返回200、201、204、302、400、500……嗯,你能想象接入方有多崩溃。
好了,状态码就说到这。下一步你可以对照自己的API设计,看看有没有能优化的地方。我个人经验是:先把状态码用对,再谈其他设计——这是投入产出比最高的步骤。