HTTP 状态码:真正需要记住的那些

状态码有 60 多个,但日常真会影响客户端行为的不到二十个。判断一个状态码值不值得记,就问一句:它会不会让浏览器、SDK 或网关改变行为?不会的(比如 418)知道名字就行。

五类的语义边界

类别 含义 谁的问题
1xx 信息,继续 协议内部,很少手写
2xx 成功 —
3xx 需要进一步动作(重定向) 客户端要重新发请求
4xx 客户端错误 请求本身有问题,重试同样的请求没用
5xx 服务端错误 服务端暂时处理不了,换个时间重试可能有用

必须掌握的 2xx 和 4xx

码 名称 关键点
200 OK 有响应体
201 Created 资源已创建,应在 Location 头给出新资源 URL
202 Accepted 已接收但还没处理完,异步任务的正确返回
204 No Content 成功但没有响应体,DELETE 常用
400 Bad Request 请求格式错,比如 JSON 解析失败
401 Unauthorized 未认证:缺少凭证或凭证无效,应带 WWW-Authenticate
403 Forbidden 已认证但没权限,重试没用
404 Not Found 不存在;如果不想暴露资源是否存在,也可用 403
405 Method Not Allowed 方法不支持,必须在 Allow 头列出可用方法
409 Conflict 与当前资源状态冲突,比如唯一约束冲突
422 Unprocessable Entity 语法没问题但语义处理不了,常用于表单校验失败
429 Too Many Requests 限流,应带 Retry-After

401 和 403 是最常搞混的一对。一句话区分:401 是"你是谁",403 是"你不配"。没登录或 token 过期返回 401;登录了但没权限访问这个资源返回 403。

400 和 422 的区别在于"请求能不能被解析":JSON 语法错误是 400,JSON 合法但 age 字段是 -5 是 422。

3xx 的四兄弟

这是最容易写错的一组。核心变量有两个:是不是永久、以及重定向时能不能改请求方法。

码 永久? 会不会改方法 用在哪
301 永久 历史上客户端常把 POST 改成 GET 域名迁移、URL 结构变更
302 临时 历史上客户端常把 POST 改成 GET 临时跳转
303 临时 明确要求改用 GET POST 提交后跳到结果页(PRG 模式)
307 临时 不允许改方法,原样重发 临时跳转但要保住 POST 体
308 永久 不允许改方法 永久跳转但要保住 POST 体

301 和 302 的"改方法"是历史实现的惯性行为,规范并没有这么要求,所以才补了 307 和 308 两个语义确定的版本。需要保住 POST 请求体时,用 307 或 308,不要用 301 或 302。

304 Not Modified 单独说:它不是重定向,而是告诉客户端"你缓存的版本还新鲜,直接用",响应体必须为空,配合 ETag 或 Last-Modified 使用。

5xx 里分得清的三个

码 含义 典型原因
500 Internal Server Error 未捕获异常,兜底码
502 Bad Gateway 网关/反向代理收到了上游的无效响应
503 Service Unavailable 服务暂时不可用(发版、过载),可带 Retry-After
504 Gateway Timeout 网关等上游等到超时,上游可能只是慢

502 和 504 的差别是"上游回了话但话不对"对"上游压根没回话"。排查方向完全不同:502 去看上游是不是崩了或者返回了畸形响应;504 去看上游是不是慢查询卡住,以及网关的超时阈值是不是设短了。

重试语义:不是所有错误都能重试

情况 该不该重试
5xx(除 501) 可以,但要退避(指数退避 + 抖动)
429 / 503 可以,且必须遵守 Retry-After 指定的时间
408 / 504 请求未生效时可重试
4xx(400/401/403/404/422) 不要重试,同样的请求再发一万次还是错
POST 类的 5xx 谨慎。POST 不幂等,重试可能产生重复订单

POST 如果需要安全重试,让客户端带 Idempotency-Key 头,服务端据此去重。

两个常见的错误用法

一、所有响应都返回 200。 把业务错误塞进 body 的 {"code": 50001} 里,HTTP 状态一律 200。后果很具体:CDN 不看 body,会把错误响应缓存起来;监控系统的错误率指标永远是 0;HTTP 客户端库的重试逻辑完全失效。

二、把业务校验失败返回 500。 参数不合法是客户端的问题,应该给 400 或 422。返回 500 会让监控告警把"用户输入错误"当成"线上故障"。

顺带两个彩蛋码:451 表示因法律原因不可用(RFC 7725),是正经状态码;418 I'm a teapot 来自 RFC 2324 的愚人节玩笑,不要用在真实业务里。

自己动手试试

相关工具