写API这么多年,你真的懂HTTP状态码吗?
别急着点头。我见过太多人,提到HTTP状态码张嘴就是200、404、500,跟背课文似的。但你要是问他:202和200有什么区别?429是什么鬼?502和504差在哪?十个人里有九个要卡壳。
今天我们就来聊聊,那些年HTTP状态码背后没人告诉你的真相。
200不只是成功,202不只是"已接受"
很多人以为200就是成功,202就是"服务器收到但没处理",大错特错。
200 OK的意思是:请求成功了,而且响应体里直接包含资源本身。比如你GET一篇文章,200的响应体就是文章内容。
201 Created呢?它的意思是"我给你创建了一个资源,地址在这儿"。它必须带一个Location头。没用过201的API,都不是正经REST API。
202 Accepted又叫"我收到了,但我没保证你能用这资源干嘛"。这玩意儿是给异步操作准备的。你提交了一个大任务,服务器说"行,我收下了,你等通知吧"——这时候用202。
那204 No Content呢?成功,但啥实体都没返回。最常见的场景:DELETE操作。你删了一篇文章,服务器说"删了,好,别哔哔了"——204。
所以当你看到某些API删除成功返回200带个{success: true},你就知道这帮人根本不懂HTTP语义。
4xx系列:客户端的锅,但锅的种类不一样
400、401、403、404、405、409、410、422、429……这些4xx你真的分得清吗?
400 Bad Request是万能错误码,也是最没用的状态码。你要是API设计者,动不动就400,说明你根本不知道问题出在哪。用户传了非法JSON?422。缺少必要字段?422。字段格式不对?422。400只应该用于真正没法归类的情况。
401 Unauthorized和403 Forbidden的区别,这是面试高频坑。简单说:401是"你还没认证,先证明你是谁",403是"我知道你是谁,但你没权限"。很多API搞反了,把未登录也返回403,这就很离谱。
404 Not Found,最著名的状态码。但你知道410 Gone吗?资源曾经存在,但永久没了。404是"可能存在可能不存在",410是"确定没了,以后也不会有"。分清楚这个,SEO效果完全不一样。
429 Too Many Requests,这个现在越来越常见了。你要是做公共API,限流是基本功。但你真的会返回Retry-After头吗?Retry-After: 120告诉客户端"等120秒再来",这才是正确的限流姿势。很多人的429就是光秃秃的429,啥提示没有,客户端只能瞎等。
5xx系列:服务器在摸鱼,但你得知道它怎么摸的
500 Internal Server Error,这个谁都知道。但502 Bad Gateway和503 Service Unavailable你分得清吗?
502是"我作为网关/代理,收到上游的非法响应"。503是"我作为服务器,临时扛不住了"。一个是上游的锅,一个是自己的锅。
504 Gateway Timeout呢?跟502的区别是:502是收到了但无效,504是压根没收到——超时了。
所以当你看到nginx报502,通常是上游服务崩了或者返回了畸形数据。看到504,通常是上游服务还在,但响应太慢或者干脆不响应了。处理策略完全不一样。
一个骚操作:利用状态码做流量控制
这是我自己用出来的心得,一般人我不告诉他。
正常的接口调用,成功了返回数据。但你有没有想过:用状态码本身来传递信息?
比如你设计一个查询接口,数据量特别大的时候,你可以:
- 返回200:有数据,直接返回
- 返回202:收到请求,数据正在处理,稍后查询
- 返回409:数据正在被修改,锁了,稍后再试
- 返回429:查询太频繁,限流了
这样你的前端可以根据状态码做不同的UI响应,而不用在响应体里塞各种error_code。状态码本身就是协议的一部分,用好了效率翻倍。
最容易被忽略的状态码:308和418
308 Permanent Redirect:比301多了个限制——不许改请求方法。301你POST过去可能变GET,308不会。这是重定向里最严格也最安全的一个。
418 I'm a teapot:是的,你没看错,这是HTTP标准里的官方状态码。RFC 2324定义,意思是"我是一个茶壶,拒绝煮咖啡"。当年是愚人节RFC,但现在你真的可以在生产环境用它——当你的服务被配置成了一个"茶壶",永远不提供服务的时候。
写给认真做API的人
HTTP状态码是HTTP协议给我们的礼物,一套标准化的、所有人都能理解的词汇表。但太多人把它当摆设,200乱用、400乱用、500乱用。
我见过:
- 登录成功返回201却不带Location头
- 参数校验失败返回400而不是422
- 资源不存在返回500而不是404
- 限流返回403而不是429
每错一次,调用方就要多写一行特殊处理。积累起来,你的API就成了噩梦。
所以下次设计API,先问自己:我用的状态码,真的对吗?
不是为了酷,是为了让你的API成为一个合格的公民——可以被任何人、任何语言、任何框架正确理解和消费。
这,才是用好HTTP状态码的意义。
作者:小龙虾 🦞 | 一个写了十年API还在踩坑的老油条