状态码选型的一张表
设计接口时最常见的争论是「这种情况该回哪个码」。判断顺序建议是:先分成功与失败,成功再分同步返回还是异步受理、有没有创建新资源;失败再分是调用方的问题、身份的问题、资源的问题还是服务端的问题。把结果固定成团队约定并写进接口文档,比每次争论都临时决定更省事,也让客户端能写出稳定的重试与提示逻辑。
场景与推荐码
| 场景 | 推荐码 | 备注 |
|---|---|---|
| 读取成功 | 200 | 带响应体表示 |
| 创建成功 | 201 加 Location | 也可用 200 直接返回创建结果体 |
| 删除成功 | 204 | 无响应体,注意客户端不能期待 JSON |
| 异步受理 | 202 | 配任务状态查询 URL |
| 请求语法错误 | 400 | JSON 畸形、参数缺失 |
| 参数语义校验失败 | 422 | 返回字段级错误明细 |
| 未认证或凭证过期 | 401 加 WWW-Authenticate | 客户端据此刷新令牌 |
| 已认证但无权限 | 403 | 不要引导重新登录 |
| 资源不存在 | 404 | 聚合接口可整体 200 并在明细里标注 |
| 并发版本冲突 | 409 或 412 | 配合 If-Match 使用 |
| 被限流 | 429 加 Retry-After | 客户端退避重试 |
| 未处理异常 | 500 | 记录堆栈,不向外暴露细节 |
选型原则
- 先判断责任侧:4xx 表示调用方需要改,5xx 表示服务端需要改,别用 200 包裹错误
- 创建成功优先 201 并给 Location;客户端只做展示时用 200 也说得通
- 删除与更新成功且无返回内容时用 204,避免返回空对象引起解析歧义
- 参数语法错误用 400,语法正确但语义不合法用 422,两者区分后前端提示更准确
- 异步任务用 202 并给出查询地址,不要用 200 假装已经完成
自测清单
自测清单
# 每个核心接口至少覆盖六类用例:正常、未认证、无权限、资源不存在、参数错误、限流
curl -si https://api.example.com/users/1 # 期望 200
curl -si https://api.example.com/users/99999 | head -1 # 期望 404
curl -si -X POST https://api.example.com/users -d '{}' # 期望 400 或 422,看校验层级
for i in $(seq 1 50); do curl -s -o /dev/null -w '%{http_code} ' https://api.example.com/users/1; done # 观察是否出现 429常见误用
| 误用 | 后果 | 正确做法 |
|---|---|---|
| 业务失败也返回 200 | 监控与网关无法识别错误,告警失效 | 按语义返回 4xx 或 5xx |
| 所有失败都返回 500 | 调用方无法区分自己该不该改 | 按责任侧区分 4xx 与 5xx |
| 权限不足返回 401 | 客户端反复刷新令牌形成死循环 | 返回 403 |
| 创建成功返回 204 | 客户端拿不到新资源地址 | 用 201 加 Location |
状态码之外还有一层:用 RFC 9457 定义的 problem 结构统一错误响应体,把类型、标题、明细一起给出,客户端处理错误时不必再解析各种自定义格式。