文章目录
- 写在前面
- 问题描述
- 核心结论与建议
- 简要描述
- 详细阐述
- 1xx - 信息性响应 (Informational)
- 2xx - 成功 (Successful)
- 3xx - 重定向 (Redirection)
- 4xx - 客户端错误 (Client Error)
- 5xx - 服务器错误 (Server Error)
- HTTP 状态码速查表
- 参考以及更多更详细的状态码查询
写在前面
你是否见过这样的 API:无论操作成功、参数错误还是找不到资源,它都固执地返回 200 OK,然后把真正的状态信息藏在响应体的某个角落,比如 {“code”: 5001, “message”: “参数不能为空”}?
这种设计看似“统一”,实则严重违反了 RESTful 的核心原则,极大地增加了客户端的对接成本和出错概率。HTTP 状态码并非摆设,它们是服务器与客户端之间沟通的标准语言,是 API 自我描述能力的重要组成部分。
本文旨在建立一套清晰、统一的 HTTP 状态码使用规范,帮助你和你的团队构建出更健壮、更易于理解和使用的 API。
问题描述
在RESTful API设计中,仅仅返回200(成功)或500(服务器错误)是远远不够的。不规范的状态码会严重影响API的可用性和开发者的对接效率。
本次调研旨在建立一套清晰、统一的HTTP状态码使用规范,核心目标是:当API调用出现各类情况(如参数不合法、无权限、资源不存在等)时,能够返回最恰当的状态码和最清晰的错误信息,提升API的健壮性和开发者体验。
核心结论与建议
参数不合法应该返回什么?
首选答案:400 Bad Request
这是最通用、最符合HTTP规范的选择。当服务器因客户端发送的请求本身有错误(例如,数据格式错误、缺少必需参数、参数值超出业务范围等)而无法处理时,应返回此状态码。
更精确的选择:422 Unprocessable Entity
在特定场景下,422 是比 400 更精确的补充。它们的区别在于:
- 400 Bad Request: 请求语法有误。服务器无法理解请求,如JSON格式损坏。
- 422 Unprocessable Entity: 请求语义有误。服务器能理解请求,但因业务规则限制无法处理,如必填字段为空、年龄为负数。
对于绝大多数团队,统一使用 400 Bad Request 来表示所有类型的参数验证失败,是更简单且完全可接受的最佳实践。
简要描述
HTTP状态码是RESTful API设计中非常核心的一部分,是三位整数代码,它们是服务器与客户端之间沟通的“标准语言”。
HTTP 状态码是可扩展的。HTTP 客户端无需理解所有已注册状态码的含义,尽管理解这些含义显然是更好的。但是,客户端必须理解任何状态码的类别(由第一位数字指示),并将无法识别的状态码视为该类别的 x00 状态码,例如,如果客户端收到无法识别的状态码 471,则客户端可以假定其请求存在问题,并将该响应视为收到了 400(错误请求)状态码。响应消息通常包含一个解释状态的表示。
这些状态码被分为五大类,由第一位数字标识(第一位数字定义了响应的类别,最后两位数字不具有任何分类作用):
- 1xx (Informational): 信息性响应 - 表示请求已接收,继续处理。
- 2xx (Successful): 成功 - 表示请求已被成功接收、理解、并接受。
- 3xx (Redirection): 重定向 - 表示需要客户端采取进一步的操作才能完成请求。
- 4xx (Client Error): 客户端错误 - 表示请求包含语法错误或无法完成请求。
- 5xx (Server Error): 服务器错误 - 表示服务器在处理一个看似有效的请求时发生错误。
详细阐述
1xx - 信息性响应 (Informational)
这类状态码在日常API开发中非常少见,主要用于协议内部交互。
100 Continue (继续):客户端准备发送一个大的请求体(如POST一个大文件)时,可以先发送一个只包含头信息的请求,并携带Expect: 100-continue头。如果服务器愿意接收,就返回100,客户端再继续发送请求体。这可以避免因服务器拒绝而浪费带宽。
101 Switching Protocols (切换协议):客户端请求升级协议(例如,从HTTP/1.1升级到WebSocket),服务器同意切换时返回此码。
102 Processing (处理中):(WebDAV扩展) 一个请求可能包含多个子操作,需要较长时间完成。服务器返回102以防止客户端超时,表示请求已收到且正在处理中。
2xx - 成功 (Successful)
这是API设计中最常用的一类,表示操作成功。
200 OK (成功):最通用的成功状态码。表示请求已成功,响应体中通常包含请求的资源。适用于GET(获取数据)、PUT(更新整个资源)、PATCH(部分更新资源)以及不创建新资源的POST操作的成功响应。
201 Created (已创建):专门用于创建新资源。当客户端通过POST请求成功创建了一个新资源时返回。最佳实践是在响应头的Location字段中包含新资源的URL。
202 Accepted (已接受): 用于异步任务。服务器已接收请求,但尚未处理完成。这并不保证最终任务会成功。适用于需要长时间处理的操作,如视频转码、生成报表等。客户端可以后续通过轮询或其他机制查询任务状态。
204 No Content (无内容): 服务器成功处理了请求,但响应体中没有任何内容返回。常用于DELETE请求成功后,或PUT更新操作成功但无需返回资源内容时。
206 Partial Content (部分内容):(不常用) 用于范围请求(Range Requests),表示服务器成功返回了资源的一部分,例如视频流或大文件分块下载。
3xx - 重定向 (Redirection)
表示客户端需要执行后续操作才能完成请求。
301 Moved Permanently (永久移动): 请求的资源已被永久移动到新的URL。搜索引擎会更新其索引。API客户端应该将本地书签也更新到新的URL。
302 Found (找到):请求的资源临时位于不同的URL。客户端应该使用这个临时的URL来发送本次请求,但下次还应该使用原始URL。常用于传统的Web页面重定向,API中较少使用。
303 See Other (查看其他):(与302类似但更明确) 建议客户端使用GET方法去请求另一个URL来获取结果。主要用于POST请求后,防止用户刷新页面导致重复提交。
304 Not Modified (未修改):用于缓存控制。当客户端发送一个带条件的GET请求(如使用If-None-Match或If-Modified-Since头),如果服务器发现资源自上次请求以来未发生变化,则返回此码,并且不包含响应体,从而节省带宽。
307 Temporary Redirect (临时重定向):(与302类似但更严格) 要求客户端在重定向到新URL时,保持原始请求方法不变。例如,如果原始请求是POST,那么对新URL的请求也必须是POST。
4xx - 客户端错误 (Client Error)
API设计中最需要关注和细化的一类,表示错误源于客户端。
400 Bad Request (错误请求):通用的客户端错误。表示服务器因客户端发送的请求语法错误而无法解析。最常见的用途是参数验证失败,如缺少必需字段、字段格式错误、数值超出范围等。
401 Unauthorized (未授权):用户未认证。客户端必须先进行身份验证(例如,提供有效的Token或API Key)才能访问该资源。它表达的是“你是谁?”的问题。
403 Forbidden (禁止访问):用户没权限。服务器已经知道客户端的身份,但该身份没有权限访问此资源。它表达的是“我知道你是谁,但你不能做这个操作”的问题。
404 Not Found (未找到):请求的资源不存在。例如,GET /api/users/9999,但ID为9999的用户不存在。
405 Method Not Allowed (方法不允许):客户端使用了当前资源不支持的HTTP方法。例如,对一个只读资源使用POST。服务器应在Allow头中返回支持的方法列表。
406 Not Acceptable (不可接受):(不常用) 服务器无法根据客户端请求头中的Accept字段(如Accept: application/xml)生成任何可接受的表示形式。
409 Conflict (冲突):请求的操作与服务器资源的当前状态发生冲突。最常见的例子是尝试创建一个已经存在的唯一资源(如注册一个已被占用的用户名或邮箱)。
410 Gone (已移除):(比404更明确) 请求的资源曾经存在,但现在已被永久删除,并且不会再可用。
413 Payload Too Large (负载过大):客户端发送的请求体大小超过了服务器的限制。
415 Unsupported Media Type (不支持的媒体类型):客户端发送的请求体使用了服务器不支持的媒体类型(由Content-Type头指定)。例如,API只接受application/json,但客户端发送了application/xml。
422 Unprocessable Entity (无法处理的实体):(WebDAV扩展,但被广泛用于API) 请求的语法正确,但语义错误,导致服务器无法处理。这是400的一个更具体的版本,专门用于业务逻辑层面的验证失败。
429 Too Many Requests (请求过多):API限流。客户端在单位时间内发送的请求数量超过了服务器设定的速率限制。
5xx - 服务器错误 (Server Error)
表示错误源于服务器端,客户端通常无法解决。
500 Internal Server Error (服务器内部错误):通用的服务器端错误。表示服务器遇到了一个未知的、无法处理的意外情况,例如代码中出现未捕获的异常、数据库连接问题等。绝不能在响应中暴露敏感的错误细节。
501 Not Implemented (未实现):服务器不支持当前请求所需要的功能。例如,客户端使用了服务器无法识别的请求方法。
502 Bad Gateway (错误网关):作为网关或代理的服务器,从其上游服务器(如应用服务器)处收到了无效的响应。
503 Service Unavailable (服务不可用):服务器当前无法处理请求,通常是临时性的。原因可能是服务器过载、正在进行维护或部署。服务器可以在Retry-After头中告知客户端何时可以重试。
504 Gateway Timeout (网关超时):作为网关或代理的服务器,未能及时从其上游服务器获得响应。
HTTP 状态码速查表
类别 | 状态码 | 名称 | 核心适用场景 |
---|---|---|---|
信息性响应(1xx) | 100 Continue | 继续 | 交互是否继续发送 |
101 Switching Protocols | 切换协议 | 切换协议 | |
102 Processing | 处理中 | 防止客户端超时。请求包含多个子操作,需要较长时间 | |
成功 (2xx) | 200 OK | 成功 | 通用成功。GET, PUT, PATCH, POST(不创建新资源), DELETE 成功 |
201 Created | 已创建 | 资源创建成功 (专用于POST) | |
202 Accepted | 已接受 | 异步任务,请求已接收,正在后台处理 | |
204 No Content | 无内容 | 成功处理,但无返回内容 (如DELETE成功) | |
206 Partial Content | 部分内容 | 服务器成功返回了资源的一部分,例如视频流或大文件分块下载 | |
重定向 (3xx) | 301 Moved Permanently | 永久移动 | 资源 URL 永久变更 |
302 Found | 找到 | 请求的资源临时位于不同的URL | |
303 See Other | 查看其他 | 建议客户端使用GET方法去请求另一个URL来获取结果 | |
304 Not Modified | 未修改 | 缓存命中,资源无变化 | |
307 Temporary Redirect | 临时重定向 | 要求客户端在重定向到新URL时,保持原始请求方法不变 | |
客户端错误 (4xx) | 400 Bad Request | 错误请求 | 参数验证失败 (通用客户端错误) |
401 Unauthorized | 未授权 | 需要认证 (未登录或Token无效) | |
403 Forbidden | 禁止访问 | 权限不足 (已登录但无权操作) | |
404 Not Found | 未找到 | 请求的资源不存在 | |
405 Method Not Allowed | 方法不允许 | HTTP 请求方法错误 (如对只读资源用POST) | |
406 Not Acceptable | 不可接受 | 服务器无法根据客户端请求头中的Accept字段生成任何可接受的表示形式 | |
409 Conflict | 冲突 | 资源状态冲突 (如创建已存在的用户) | |
410 Gone | 已移除 | 请求的资源曾经存在,但现在已被永久删除,并且不会再可用 | |
413 Payload Too Large | 负载过大 | 客户端发送的请求体大小超过了服务器的限制 | |
415 Unsupported Media Type | 不支持的媒体类型 | 客户端发送的请求体使用了服务器不支持的媒体类型(由Content-Type头指定) | |
422 Unprocessable Entity | 无法处理的实体 | 请求的语法正确,但业务语义错误 (400的更具体版本),专用于业务逻辑层面的验证失败 | |
429 Too Many Requests | 请求过多 | API 限流 | |
服务器错误 (5xx) | 500 Internal Server Error | 服务器内部错误 | 通用服务器端代码/环境异常 |
501 Not Implemented | 未实现 | 服务器不支持当前请求所需要的功能 | |
502 Bad Gateway | 错误网关 | 网关/代理从上游收到无效响应 | |
503 Service Unavailable | 服务不可用 | 服务器临时过载、维护或部署 | |
504 Gateway Timeout | 网关超时 | 网关/代理从上游请求超时 |
参考以及更多更详细的状态码查询
权威标准-IETF RFCs
RFC 7231: Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content: 6. Response Status Codes
RFC 6585: Additional HTTP Status Codes
RFC 4918: HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV)
开发者圣经-MDN Web Docs
HTTP 响应状态码 - HTTP | MDN
快速查询
HTTP Status Codes Glossary - WebFX
趣味记忆
HTTP Cats