HTTP状态码
HTTP状态码总体分类
HTTP状态码是一个3位数字,由RFC 7231等标准定义。状态码的第一位数字定义了响应的类别,共有5大类:
| 范围 | 类别 | 含义 | 一句话理解 |
|---|---|---|---|
| 1xx | 信息性状态码 | Informational | 请求已收到,继续处理 |
| 2xx | 成功状态码 | Success | 请求成功处理 |
| 3xx | 重定向状态码 | Redirection | 需要进一步操作以完成请求 |
| 4xx | 客户端错误状态码 | Client Error | 请求有问题,客户端需要修正 |
| 5xx | 服务器错误状态码 | Server Error | 服务器处理请求时出错 |
状态码的组成
HTTP状态码由三部分组成:
- 第一位数字:定义响应类别(1-5)
- 后两位数字:具体状态码(00-99)
- 状态文本:可读的状态描述(如”OK”、”Not Found”)
例如:200 OK、404 Not Found、500 Internal Server Error
2xx:成功状态码
2xx系列状态码表示请求已成功被服务器接收、理解并处理。这是Web开发中最常见的状态码类别。
200 OK - 请求成功
含义:请求成功,服务器已成功处理请求并返回响应数据。
使用场景:
- GET请求获取资源成功
- POST/PUT请求更新资源成功
- 返回正常的业务数据
示例:
1 | 200 OK |
注意事项:
- 这是最常用的成功状态码
- 应该包含请求的资源或操作结果
- 对于幂等操作(如GET),200表示资源存在且可访问
201 Created - 资源已创建
含义:请求成功,并且服务器创建了新的资源。
使用场景:
- POST请求创建新资源
- 注册新用户
- 创建新订单、文章等
示例:
1 | 201 Created |
最佳实践:
- 应该包含
Location头,指向新创建资源的URI - 响应体应包含创建的资源信息
- 适用于创建操作,区别于200(更新操作)
204 No Content - 无内容
含义:服务器成功处理了请求,但没有返回任何内容。
使用场景:
- DELETE请求成功删除资源
- PUT请求更新资源,无需返回数据
- 某些POST请求(如批量操作)只需确认成功
示例:
1 | 204 No Content |
注意事项:
- 响应体必须为空
- 常用于RESTful API的删除操作
- 客户端收到204后,不应更新其缓存视图(除非请求是DELETE)
其他2xx状态码
202 Accepted:请求已接受,但尚未处理完成(异步操作)
206 Partial Content:部分内容,用于范围请求(Range Request),常用于大文件下载
3xx:重定向状态码
3xx系列状态码表示需要客户端采取进一步的操作才能完成请求。重定向在Web开发中非常常见,特别是在网站迁移、URL规范化、缓存优化等场景。
301 Moved Permanently - 永久重定向
含义:请求的资源已永久移动到新位置,客户端应该使用新的URI访问。
使用场景:
- 网站域名更换(如从http迁移到https)
- URL结构重构
- 资源永久迁移到新地址
示例:
1 | 301 Moved Permanently |
重要特性:
- 浏览器会缓存:客户端会记住这个重定向,以后直接访问新地址
- SEO影响:搜索引擎会更新索引,将权重转移到新URL
- HTTP方法可能改变:某些客户端会将POST改为GET(虽然规范不建议)
最佳实践:
- 只在资源确实永久移动时使用
- 确保新URL可访问且正确
- 考虑保留旧URL一段时间,返回301重定向
302 Found - 临时重定向
含义:请求的资源临时从不同的URI响应,客户端应继续使用原URI进行后续请求。
使用场景:
- 临时维护页面
- 登录后跳转
- A/B测试
- 临时URL变更
示例:
1 | 302 Found |
重要特性:
- 浏览器不缓存:每次都会请求原地址,服务器决定重定向
- SEO友好:搜索引擎不会更新索引,原URL权重保留
- HTTP方法保持:重定向后的请求方法通常不变
与301的区别:
- 301:永久移动,浏览器缓存,SEO权重转移
- 302:临时移动,浏览器不缓存,SEO权重保留
304 Not Modified - 未修改
含义:资源自上次请求后未被修改,客户端可以使用缓存的版本。
使用场景:
- 浏览器缓存验证
- CDN缓存优化
- 减少带宽消耗
- 提升页面加载速度
示例:
1 | 304 Not Modified |
工作原理:
- 客户端首次请求资源,服务器返回200和缓存头(ETag或Last-Modified)
- 客户端再次请求时,带上
If-None-Match(ETag)或If-Modified-Since(Last-Modified) - 服务器比较后,如果未修改,返回304;如果已修改,返回200和新内容
性能优化关键:
- 减少网络传输,节省带宽
- 加快页面加载速度
- 降低服务器负载
实现示例:
1 | # 伪代码示例 |
其他3xx状态码
303 See Other:重定向到另一个URI,且客户端应使用GET方法访问(POST后重定向)
307 Temporary Redirect:临时重定向,但要求客户端保持HTTP方法不变(302的严格版本)
308 Permanent Redirect:永久重定向,且要求客户端保持HTTP方法不变(301的严格版本)
4xx:客户端错误状态码
4xx系列状态码表示客户端发送的请求有错误,服务器无法处理。这类错误通常需要客户端修改请求后才能成功。
400 Bad Request - 请求错误
含义:服务器无法理解客户端的请求,通常是因为请求格式错误。
常见原因:
- 请求参数缺失或格式错误
- JSON格式不正确,解析失败
- 参数类型错误(如期望数字却传了字符串)
- 请求体格式不符合要求
- URL编码错误
示例:
1 | 400 Bad Request |
最佳实践:
- 返回详细的错误信息,帮助客户端定位问题
- 列出所有错误字段,而不是只返回第一个错误
- 使用统一的错误响应格式
401 Unauthorized - 未授权
含义:请求需要身份认证,客户端未提供有效的认证信息。
使用场景:
- 用户未登录
- Token缺失或格式错误
- Token已过期
- 认证信息无效
示例:
1 | 401 Unauthorized |
重要特性:
- 应该包含
WWW-Authenticate响应头,说明认证方式 - 客户端收到401后,通常需要重新登录或刷新token
- 与403的区别:401是”未认证”,403是”已认证但无权限”
常见实现:
1 | # 伪代码 |
403 Forbidden - 禁止访问
含义:服务器理解请求,但拒绝执行。客户端已认证,但没有权限访问该资源。
使用场景:
- 用户已登录,但权限不足
- 访问被管理员禁止的资源
- IP地址被拉黑
- 资源访问受限(如付费内容)
示例:
1 | 403 Forbidden |
与401的区别:
- 401 Unauthorized:未认证,需要登录
- 403 Forbidden:已认证,但无权限
最佳实践:
- 明确说明权限要求
- 不要泄露敏感信息(如”用户存在但密码错误”应返回401,而非403)
404 Not Found - 资源不存在
含义:服务器无法找到请求的资源。
使用场景:
- URL路径错误
- 资源已被删除
- API路由未配置
- 文件不存在
示例:
1 | 404 Not Found |
注意事项:
- 不要返回404来隐藏资源存在性(安全考虑,某些场景应返回403)
- 提供友好的错误页面或错误信息
- 考虑返回相关资源建议(如”您要找的是不是…”)
405 Method Not Allowed - 方法不允许
含义:请求的HTTP方法不被允许用于该资源。
使用场景:
- 对只读资源使用POST/PUT/DELETE
- API不支持某些HTTP方法
- 路由配置错误
示例:
1 | 405 Method Not Allowed |
最佳实践:
- 必须包含
Allow响应头,列出允许的方法 - 帮助客户端了解正确的请求方式
409 Conflict - 资源冲突
含义:请求与资源的当前状态冲突,无法完成。
使用场景:
- 创建资源时,资源已存在(如用户名重复)
- 更新资源时,版本冲突(乐观锁)
- 删除资源时,资源正在被使用
- 并发修改冲突
示例:
1 | 409 Conflict |
乐观锁示例:
1 | # 客户端请求更新资源 |
最佳实践:
- 提供冲突的详细信息
- 对于版本冲突,返回当前版本信息,方便客户端重试
429 Too Many Requests - 请求过多
含义:客户端在给定时间内发送了太多请求,需要限流。
使用场景:
- API限流保护
- 防止恶意刷接口
- 防止爬虫过度抓取
- 保护服务器资源
示例:
1 | 429 Too Many Requests |
重要响应头:
Retry-After:告诉客户端多久后可以重试(秒数或HTTP日期)X-RateLimit-*:自定义限流信息头(非标准但广泛使用)
限流策略:
- 固定窗口:每分钟N次请求
- 滑动窗口:最近N秒内M次请求
- 令牌桶:动态分配请求配额
- 漏桶:平滑处理请求速率
实现示例:
1 | # 伪代码 |
其他常见4xx状态码
408 Request Timeout:请求超时,客户端发送请求时间过长
410 Gone:资源已永久删除,且不会有新的地址(比404更明确)
422 Unprocessable Entity:请求格式正确,但语义错误(常用于表单验证失败)
451 Unavailable For Legal Reasons:因法律原因不可访问(如被政府要求下架的内容)
5xx:服务器错误状态码
5xx系列状态码表示服务器处理请求时发生错误。这类错误通常是服务器端的问题,客户端无法通过修改请求来解决。
500 Internal Server Error - 服务器内部错误
含义:服务器遇到了意外情况,无法完成请求。
常见原因:
- 代码bug(空指针、数组越界等)
- 未捕获的异常
- 数据库连接失败
- 配置文件错误
- 内存溢出
- 第三方服务调用失败
示例:
1 | 500 Internal Server Error |
最佳实践:
- 生产环境:不要返回详细的错误堆栈(安全考虑)
- 开发环境:可以返回详细错误信息便于调试
- 记录完整的错误日志(包括堆栈、请求参数等)
- 使用请求ID方便追踪问题
- 设置错误监控和告警
错误处理示例:
1 | # 伪代码 |
502 Bad Gateway - 网关错误
含义:作为网关或代理的服务器,从上游服务器收到无效响应。
使用场景:
- 反向代理(如Nginx)无法从上游服务器获取有效响应
- 微服务架构中,API网关无法连接到后端服务
- 上游服务崩溃或返回无效响应
- 负载均衡器无法连接到后端服务器
示例:
1 | 502 Bad Gateway |
常见原因:
- 上游服务宕机
- 上游服务响应格式错误
- 网络连接问题
- 上游服务超时
架构示意:
1 | 客户端 → API网关 → 上游服务(异常) |
解决方案:
- 实现服务健康检查
- 配置服务降级策略
- 使用熔断器模式
- 增加重试机制
503 Service Unavailable - 服务不可用
含义:服务器暂时无法处理请求,通常是由于维护或过载。
使用场景:
- 服务器正在维护
- 服务器过载,无法处理更多请求
- 数据库连接池耗尽
- 依赖的外部服务不可用
- 计划内的停机维护
示例:
1 | 503 Service Unavailable |
重要响应头:
Retry-After:告诉客户端多久后可以重试
与500的区别:
- 500:服务器错误,通常是意外情况
- 503:服务不可用,通常是已知的临时情况(维护、过载)
最佳实践:
- 提供维护页面或友好的错误信息
- 设置合理的
Retry-After时间 - 实现优雅降级
- 使用负载均衡和自动扩缩容
504 Gateway Timeout - 网关超时
含义:作为网关或代理的服务器,未能及时从上游服务器收到响应。
使用场景:
- 上游服务响应时间过长
- 网络延迟过高
- 上游服务处理超时
- 数据库查询超时
示例:
1 | 504 Gateway Timeout |
与502的区别:
- 502:上游服务器返回了无效响应
- 504:上游服务器没有在超时时间内响应
解决方案:
- 增加超时时间配置
- 优化上游服务性能
- 实现异步处理
- 使用消息队列解耦
- 设置合理的超时时间
超时配置示例:
1 | # Nginx配置示例 |
其他5xx状态码
501 Not Implemented:服务器不支持请求的功能(如不支持的HTTP方法)
505 HTTP Version Not Supported:服务器不支持请求中使用的HTTP协议版本
状态码选择的最佳实践
1. 遵循RESTful规范
- GET:成功返回200,不存在返回404
- POST:创建成功返回201,其他成功返回200
- PUT/PATCH:成功返回200或204
- DELETE:成功返回200或204,不存在返回404
2. 错误处理原则
- 客户端能修复的错误:返回4xx,提供详细错误信息
- 服务器端错误:返回5xx,不要泄露内部细节
- 认证问题:401(未认证)vs 403(已认证但无权限)
3. 状态码一致性
- 在整个API中保持状态码使用的一致性
- 建立团队的状态码使用规范
- 在API文档中明确说明各状态码的使用场景
4. 错误响应格式
建议使用统一的错误响应格式:
1 | { |
5. 监控和日志
- 记录所有非2xx状态码的请求
- 设置5xx错误的告警
- 分析4xx错误模式,优化API设计
- 监控状态码分布,识别异常
