HTTP 响应状态码赏析
Category(分类): NET Protocol Status: 优
本文保留原文按状态码分类、逐个收集整理的方式,并结合 RFC 9110、RFC 9112、WebDAV 相关 RFC 和 IANA 注册表修正过时或错误的描述。
概要
按道理来说,HTTP 常见的响应状态码都见过不少了,但遇到某些状态码时,还是很难一眼判断问题出在哪里。本文对常见状态码进行整理,帮助理解客户端、服务器、代理和缓存之间的关系。
HTTP 响应状态码是一个三位数字,用来表达服务器对请求的处理结果。第一位数字表示响应类别:
- 1xx(100–199):信息响应,表示请求处理仍在继续;
- 2xx(200–299):成功响应,表示请求已被理解并处理;
- 3xx(300–399):重定向或缓存相关响应,需要客户端采取进一步动作或使用已有缓存;
- 4xx(400–499):请求无法被当前服务器满足,通常与请求格式、权限、认证或资源状态有关;
- 5xx(500–599):服务器或网关无法完成看起来有效的请求。
第一位只能用于粗略分类,不能绝对理解为“4xx 一定是客户端代码错了”或“5xx 一定是源服务器错了”。反向代理、CDN、网关和认证系统也可能生成状态码。
状态码本身只描述 HTTP 层语义,具体业务含义还要结合响应首部、响应体、请求方法、服务端日志和链路监控判断。
一、信息响应
1xx 响应是临时响应,通常不能作为最终请求结果。客户端应继续等待后续最终响应,除非协议规定了其他行为。
| 状态 | 描述 |
|---|---|
| 100 Continue | 服务端暂未因请求首部拒绝请求,客户端可以继续发送请求体。它常与 Expect: 100-continue 配合使用,并不代表整个请求已经成功。 |
| 101 Switching Protocols | 服务端同意客户端在 HTTP/1.1 中通过 Upgrade 请求首部切换到其他协议,例如 WebSocket。HTTP/2 和 HTTP/3 不使用传统的 Connection: Upgrade 流程。 |
| 102 Processing | WebDAV 状态码,表示服务器已经收到并正在处理请求,但还没有最终响应,常用于避免客户端因长时间等待而超时。 |
| 103 Early Hints | 在最终响应之前发送的提示响应,通常通过 Link 首部让客户端提前进行预连接、预加载等优化。它只是提示,不保证客户端一定执行,也不代表最终响应已经确定。 |
二、成功响应
| 状态 | 描述 |
|---|---|
| 200 OK | 请求成功。具体响应内容取决于请求方法:GET 通常返回资源表示;HEAD 只返回类似 GET 的首部元数据、不能包含响应体;POST、PUT 等方法的响应内容由具体资源语义决定;TRACE 的响应体通常包含服务器收到的请求消息。 |
| 201 Created | 请求成功并创建了一个或多个资源。服务端通常可以通过 Location 首部指出新资源的位置,也可以在响应体中返回资源表示。常见于 POST 或 PUT。 |
| 202 Accepted | 请求已被接受处理,但处理尚未完成,也不保证最终一定成功。当前响应已经返回;如果是异步任务,响应体通常应说明任务状态或提供查询状态的方式。HTTP 不会自动在以后再发送一个对应的异步响应。 |
| 203 Non-Authoritative Information | 请求成功,但响应内容或元数据已经被转换代理修改,不再是源服务器直接提供的权威表示。它不是简单表示“响应来自缓存”。 |
| 204 No Content | 请求成功,但响应不包含内容。响应首部仍然可能提供有用的元数据,例如更新后的 ETag。204 响应不能包含响应体。 |
| 205 Reset Content | 请求成功,并要求用户代理重置发起请求的文档视图或表单。该响应不能包含响应体。 |
| 206 Partial Content | 服务端成功满足了 Range 请求,返回资源的一部分或多个范围。通常需要配合 Content-Range、Content-Length 和 Accept-Ranges 等首部。 |
| 207 Multi-Status | WebDAV 状态码,用于在一个响应中报告多个资源或多个独立操作的结果,通常使用 WebDAV 的 XML multistatus 响应。 |
| 208 Already Reported | WebDAV 状态码,通常出现在 DAV:propstat 响应中,用于避免在多个绑定指向同一资源时重复枚举内部成员。 |
| 226 IM Used | RFC 3229 定义的实例操作状态码,表示服务端完成了 GET,并返回了对当前表示应用一个或多个实例操作后的结果。实际使用非常少见。 |
关于 204、205 和 HEAD
这几个场景经常被混淆:
HEAD可以有Content-Length等首部,但不能发送响应体;204表示请求成功但没有响应内容;205除了没有响应内容,还要求客户端重置相关文档视图。
三、重定向和缓存响应
| 状态 | 描述 |
|---|---|
| 300 Multiple Choices | 请求有多个可能的表示或处理结果,服务端没有替客户端选择其中一个。响应可以提供可选地址或表示列表,由用户代理或用户选择。 |
| 301 Moved Permanently | 目标资源已永久移动到 Location 首部指定的 URI。客户端可以更新书签或后续引用。历史客户端可能把 POST 改成 GET,因此需要保留请求方法时应考虑 308。 |
| 302 Found | 目标资源暂时位于另一个 URI。客户端未来仍应使用原始 URI。历史客户端经常把 POST 改成 GET;如果必须保留方法和请求体,应使用 307。 |
| 303 See Other | 服务端要求客户端通过 GET 请求访问 Location 指定的另一个 URI,常用于 POST/提交操作完成后的“查看结果”跳转。 |
| 304 Not Modified | 用于条件 GET 或 HEAD。服务端表示资源相对于客户端缓存中的版本没有变化,客户端可以继续使用缓存内容。304 不应包含响应体。 |
| 305 Use Proxy | 历史上用于要求客户端通过代理访问资源。由于带内配置代理存在安全问题,已废弃,不应在新系统中使用。 |
| 306 Unused | 保留状态码,目前未使用。 |
| 307 Temporary Redirect | 临时重定向,并要求客户端保留原请求方法和请求体。例如原请求是 POST,重定向后仍应使用 POST。 |
| 308 Permanent Redirect | 永久重定向,并要求客户端保留原请求方法和请求体。它与 301 类似,但不会因为历史兼容行为把 POST 改成 GET。 |
301/302 与 307/308 的区别
最容易记忆的方式是:
301、302:历史客户端可能把 POST 改为 GET;307、308:规范要求保留原方法和请求体;301、308:永久重定向;302、307:临时重定向。
四、客户端错误响应
4xx 不一定意味着“客户端程序有 bug”,也可能表示认证失败、权限不足、资源冲突、请求过大或请求被策略拒绝。
| 状态 | 描述 |
|---|---|
| 400 Bad Request | 服务器无法或不愿处理请求,例如请求语法错误、消息 framing 无效、首部格式错误或请求路由具有欺骗性。 |
| 401 Unauthorized | 请求缺少有效的身份认证凭据,或凭据无效。响应必须包含 WWW-Authenticate,提示客户端应使用何种认证方案。名称虽然包含 Unauthorized,但语义更接近“未认证”。 |
| 402 Payment Required | 保留状态码,最初与数字支付有关,但目前没有通用的标准支付语义。 |
| 403 Forbidden | 服务器理解请求,但拒绝提供服务。原因可能是权限不足、策略禁止、来源受限等;不一定表示服务器已经确认了客户端身份。服务器也可以用 403 隐藏资源是否存在。 |
| 404 Not Found | 服务器没有找到目标资源,或者不愿透露该资源是否存在。API 中也可能表示路径有效但具体资源不存在。 |
| 405 Method Not Allowed | 目标资源不支持当前 HTTP 方法。响应必须通过 Allow 首部列出该资源支持的方法。 |
| 406 Not Acceptable | 服务端根据请求中的主动内容协商条件,找不到用户代理可以接受的表示。 |
| 407 Proxy Authentication Required | 类似 401,但认证需要向代理完成。响应通常包含 Proxy-Authenticate。 |
| 408 Request Timeout | 服务器在准备等待的时间内没有收到完整请求。服务器可能关闭连接;某些服务器也会用它清理空闲连接。它不是专门表示业务处理超时。 |
| 409 Conflict | 请求与目标资源的当前状态冲突,例如版本冲突、重复创建或状态机不允许当前操作。响应体通常应说明如何解决冲突。 |
| 410 Gone | 目标资源在源服务器上已经不存在,并且这种情况很可能是永久性的。它比 404 更明确地表示资源已被移除,但不意味着客户端必须机械地删除所有缓存和链接。 |
| 411 Length Required | 服务端拒绝处理缺少 Content-Length 的请求,因为服务端要求该首部。是否接受 chunked 请求由具体实现决定。 |
| 412 Precondition Failed | 请求中的条件首部未满足,例如 If-Match、If-Unmodified-Since 等条件失败。 |
| 413 Content Too Large | 请求内容超过服务器愿意或能够处理的大小。旧资料常写作 Payload Too Large。服务端可以关闭连接,也可以通过 Retry-After 提供重试建议,但该首部不是必需的。 |
| 414 URI Too Long | 请求目标 URI 长度超过服务器愿意解析的范围。实际长度限制通常来自浏览器、代理、CDN 或服务器配置,而不是一个统一的 HTTP 常量。 |
| 415 Unsupported Media Type | 请求内容的媒体类型不被目标资源或当前方法支持,例如接口只接受 JSON 却收到 XML。 |
| 416 Range Not Satisfiable | 请求中的 Range 无法满足,例如范围超出了资源长度。服务端通常可以通过 Content-Range: bytes */完整长度 告知当前资源大小。 |
| 417 Expectation Failed | 服务端无法满足 Expect 请求首部表达的期望,例如无法接受 100-continue。 |
| 418 Unused | 当前注册表将其标记为未使用。它源自“用茶壶煮咖啡”的历史玩笑,不应当作为正式业务语义依赖。 |
| 421 Misdirected Request | 请求到达了无法为目标 URI 生成权威响应的服务器,例如连接复用时请求被发送到错误的主机。HTTP/2 或 HTTP/3 客户端可能需要改用其他连接重试。 |
| 422 Unprocessable Content | 请求的媒体类型和语法都能理解,但其中的指令存在语义错误,无法执行。旧资料和 WebDAV 中常称为 Unprocessable Entity。 |
| 423 Locked | WebDAV 状态码,表示目标资源处于锁定状态,当前操作不能执行。 |
| 424 Failed Dependency | WebDAV 状态码,表示当前操作依赖的其他操作失败,因此当前操作也失败。 |
| 425 Too Early | 服务端不愿处理可能来自 TLS 早期数据(0-RTT)且可能被重放的请求。客户端重试时不应再次使用早期数据。 |
| 426 Upgrade Required | 服务端拒绝当前协议,但客户端升级到其他协议后可能接受请求。响应应通过 Upgrade 首部指出所需协议。 |
| 428 Precondition Required | 源服务器要求请求必须带条件,例如 If-Match,用于降低“丢失更新”风险。 |
| 429 Too Many Requests | 客户端在给定时间内发送了过多请求,通常表示触发限流。响应可以通过 Retry-After 告知建议等待时间。这里的“客户端”不一定是某个用户,也可能是 IP、API Key、租户或应用。 |
| 431 Request Header Fields Too Large | 一个或多个请求首部字段,或全部请求首部的总大小超过服务器愿意处理的范围。 |
| 451 Unavailable For Legal Reasons | 由于法律要求、法院命令或其他法律原因,服务端无法提供目标资源。不只限于政府审查场景,响应通常应说明相关法律依据或阻断方。 |
401 与 403
可以这样理解,但不能绝对化:
401:服务端需要有效认证凭据,或当前凭据无效;403:服务端理解请求,但即使请求格式正确,也拒绝提供服务。
实际系统为了避免泄露资源是否存在,也可能把部分未授权访问统一返回 404 或 403。
五、服务端错误响应
5xx 表示服务器、代理或网关无法完成一个看起来有效的请求。具体根因往往需要查看服务端和上游日志。
| 状态 | 描述 |
|---|---|
| 500 Internal Server Error | 服务器遇到未预期的内部错误,无法完成请求。真实原因通常需要查看服务端日志和链路追踪。 |
| 501 Not Implemented | 服务器不支持完成请求所需的功能,例如不支持某个方法或扩展。它不是“只支持 GET 和 HEAD”,也不等同于 405。 |
| 502 Bad Gateway | 网关或代理作为中间服务器时,从上游服务器收到了无效响应。 |
| 503 Service Unavailable | 服务器暂时无法处理请求,常见原因是过载、维护、连接池耗尽或依赖服务不可用。条件允许时可以通过 Retry-After 提示重试时间。 |
| 504 Gateway Timeout | 网关或代理在等待上游服务器响应时超时。它和 408 的区别是:504 关注的是等待上游响应,408 关注的是服务端等待客户端发送完整请求。 |
| 505 HTTP Version Not Supported | 服务器不支持或拒绝使用请求中的 HTTP 版本。 |
| 506 Variant Also Negotiates | 服务器存在透明内容协商配置错误,选中的变体资源又参与了协商,导致它不能作为合适的协商终点。 |
| 507 Insufficient Storage | WebDAV 状态码,服务器无法存储完成请求所需的表示。 |
| 508 Loop Detected | 通常用于 WebDAV 深度遍历,服务器在处理请求时检测到了无限循环。 |
| 510 Not Extended | 历史上属于 HTTP Extension Framework 的状态码,但该扩展框架已经废弃,IANA 将其标记为 OBSOLETED,新系统不应依赖它。 |
| 511 Network Authentication Required | 表示客户端需要完成网络接入认证才能获得网络访问,例如 captive portal(强制门户)。它不是普通网站用户登录失败的通用状态码。 |
常见 5xx 的区别
500:当前服务器内部发生未预期错误;502:网关从上游拿到了无效响应;503:服务暂时不可用;504:网关等待上游响应超时;505:HTTP 版本不支持。
六、排查状态码的思路
遇到状态码时,可以按照以下顺序排查:
- 查看请求方法、请求 URL、请求体和关键请求首部;
- 查看响应首部,例如
Location、Allow、WWW-Authenticate、Retry-After、Content-Range; - 判断响应是源服务器、反向代理、CDN 还是网关生成的;
- 对照认证、权限、缓存、限流、路由和上游依赖日志;
- 不要只根据浏览器页面上的一句错误提示判断根因;
- 对重试进行区分:GET 等幂等请求通常更适合自动重试,POST 是否可以重试要结合幂等键和业务语义。