HTTP 状态码
所有 HTTP 状态码,依类别分组,并说明真正容易搞混的那几组:301 与 308、401 与 403、502 与 504。
在你的浏览器中运行
点一下代码即可复制。
请求已收到,处理仍在继续。人工很少会看到这一类。
| 代码 | 意义 |
|---|---|
| Continue | 可以继续发送请求主体。这是对 `Expect: 100-continue` 标头的回应,让客户端在发送大型上传之前,先确认服务器愿意接收。 |
| Switching Protocols | 连接正在切换协议,最常见的是切换到 WebSocket。 |
| Early Hints | 先发送的初步标头,让浏览器能在真正的响应之前先开始抓取资源。 |
请求已收到、已理解,也被接受了。
| 代码 | 意义 |
|---|---|
| OK | 成功了。 |
| Created | 成功了,而且产生了新的资源,地址在 `Location` 标头里。 |
| No Content | 成功了,而且刻意没有任何内容要回传。204 不能带有主体。硬要发送主体是协议错误,有些客户端会处理得很糟。 |
| Partial Content | 响应 `Range` 请求所发送的部分内容。视频拖动进度与断点续传就是靠它运作的。 |
你要的东西在别的地方,或是根本没有变过。
| 代码 | 意义 |
|---|---|
| Moved Permanently | 已经永久搬走了,请更新你的链接。301 和 302 允许客户端在重定向时把 POST 换成 GET,而浏览器确实会这么做。如果方法必须保留,请改用 308 或 307。 |
| Found | 暂时在别的地方,请继续使用原本这个网址。 |
| See Other | 请改用 GET 去取另一个网址——表单提交完成后最常见的响应。 |
| Not Modified | 你缓存的版本仍然有效,不会回传主体。 |
| Temporary Redirect | 暂时在别的地方,而且请求方法不能改变。 |
| Permanent Redirect | 永久搬到别的地方,而且请求方法不能改变。 |
请求本身有问题,或是不被允许。改变请求内容可能会有帮助。
| 代码 | 意义 |
|---|---|
| Bad Request | 服务器根本看不懂这个请求。 |
| Unauthorized | 你尚未通过身份验证,服务器不知道你是谁。名字取错了:401 的意思是「未验证身份」,「没有权限」是 403。401 必须带上 `WWW-Authenticate` 标头。 |
| Forbidden | 服务器知道你是谁,但你就是不能拿到这个东西。重新登录没有用。如果连「这个资源存在」本身都算机密,回 404 才是比较安全的做法。 |
| Not Found | 这个地址上没有任何东西。它完全没有说这东西曾经存不存在。如果你确定它永远消失了,请用 410。 |
| Method Not Allowed | 这个地址存在,但不接受这个方法。响应必须列出可用的方法。 |
| Conflict | 请求与目前的状态冲突,例如你正在修改的其实是旧版本。 |
| Gone | 它曾经存在,而且是刻意被移除的,不会再回来。 |
| I'm a teapot | 1998 年愚人节的玩笑,然后就再也没消失过。 |
| Unprocessable Content | 格式没问题,但语义上是错的——例如合法的 JSON 里有不合法的字段。 |
| Too Many Requests | 你被限流了,`Retry-After` 会告诉你什么时候可以再来。 |
请求本身没有问题,是服务器没能处理好。
| 代码 | 意义 |
|---|---|
| Internal Server Error | 出了问题,而服务器说不出更具体的原因。 |
| Not Implemented | 服务器根本不支持这个要求。 |
| Bad Gateway | 代理服务器向上游询问,却拿到一个无法使用的响应。上游有响应,只是回得不对。504 是上游没有在时限内响应,503 则是这台服务器自己决定不处理。 |
| Service Unavailable | 暂时不提供服务,可能是超载或正在维护。 |
| Gateway Timeout | 代理服务器等待上游响应,最后放弃了。 |
没有符合的状态码。
先看第一个数字
类别会告诉你「问题出在谁身上」,以及「重试有没有意义」:
- 1xx——已收到,还在处理中。人工几乎不会遇到。
- 2xx——成功了。
- 3xx——东西在别的地方,或是根本没变。
- 4xx——你的请求有问题或不被允许。再送一次一模一样的东西没有用。
- 5xx——服务器没能处理好。同样的请求过一阵子很可能就会成功。
最后那个区别,在出事时最有用。4xx 表示先停下来检查你送了什么;5xx 表示请求本身没问题, 重试是合理的。
最常被搞混的几组
**401 的名字取错了。**它的意思是尚未验证身分——服务器不知道你是谁——而且必须带上
WWW-Authenticate 头部。「没有权限」是 403。重新登入能解决 401,对 403 完全没用。
**机密资源该回 403 还是 404?**如果「这个资源存在」这件事本身就是机密,回 404 比较安全: 403 等于承认那里确实有东西。
**404 没有说任何关于过去的事。**如果你确定那个东西是被刻意、永久移除的,请用 410——它会 让爬虫停止再来询问。
**502、503、504 是三种不同的失败。**上游回了但回得不对、这台服务器自己决定不处理、上游 没有在时限内回应。
重新导向会换掉你的方法,这一点常让人意外
301 和 302 允许客户端在跟随重新导向时把 POST 换成 GET,而每一个浏览器都确实这么做。 所以如果你用 302 去重新导向一个表单送出,主体在抵达时就已经不见了。
307 和 308 的存在正是为了禁止这件事。它们分别等同于 302 和 301,只是多了一项保证:方法 与主体必须原封不动地保留。只要重新导向可能载着 POST,就用 307 或 308。
303 则是刻意反过来:它告诉客户端改用 GET 去取另一个地址,这正是表单完成后应该给的回应, 让浏览器停在一个可以安全重新整理、而不会重复送出的结果页。
418 是真的存在,某种意义上
418 I'm a teapot 来自 1998 年的愚人节 RFC,然后就再也没消失。它不是真正的状态码,而且
曾经有人提案把它从注册表中移除,却因为实作它的人太多而被否决。服务器偶尔真的会拿它来表示
「我就是不做这件事」。