✅ 健康检查功能: - 实现完整的健康检查接口(/api/health, /api/health/detailed) - 支持MySQL和Redis依赖状态检查 - 包含系统信息、性能指标监控 - 修复this上下文问题,确保服务方法正常调用 - 添加全面的健康检查测试用例 📝 Swagger文档优化: - 创建全局响应Schema定义和错误码说明 - 完善API文档,包含详细的错误码表格 - 添加JWT认证说明和响应格式示例 - 增加全局组件、响应模板和示例 - 创建Swagger文档功能测试 🎯 任务完成: - ✅ 5.0 健康检查接口 - 实现系统和依赖健康状态监控 - ✅ 7.0 Swagger文档完善 - 增加全局响应示例和错误码说明 📁 新增文件: - src/controllers/health.controller.ts - 健康检查控制器 - src/services/health.service.ts - 健康检查服务层 - src/type/health.type.ts - 健康检查类型定义 - src/validators/health.response.ts - 健康检查响应验证 - src/validators/global.response.ts - 全局响应Schema定义 - src/tests/health.test.ts - 健康检查功能测试 - src/tests/redis.test.ts - Redis连接测试 - src/tests/swagger.test.ts - Swagger文档功能测试
623 lines
15 KiB
Markdown
623 lines
15 KiB
Markdown
# HTTP 状态码完整指南
|
||
|
||
## 概述
|
||
|
||
HTTP 状态码是服务器响应客户端请求时返回的三位数字代码,用于表示请求的处理结果。本文档详细列举了所有常见的HTTP状态码,以及在API开发中的最佳实践。
|
||
|
||
## 状态码分类
|
||
|
||
- **1xx (信息性)**: 请求已接收,继续处理
|
||
- **2xx (成功)**: 请求已成功被服务器接收、理解、并接受
|
||
- **3xx (重定向)**: 需要后续操作才能完成这一请求
|
||
- **4xx (客户端错误)**: 请求包含错误语法或无法被执行
|
||
- **5xx (服务器错误)**: 服务器无法完成明显有效的请求
|
||
|
||
---
|
||
|
||
## 1xx 信息性状态码
|
||
|
||
### 100 Continue
|
||
|
||
- **说明**: 继续,客户端应继续其请求
|
||
- **使用场景**: 大文件上传时的初始确认
|
||
- **处理建议**: 通常由HTTP库自动处理,开发者无需特殊处理
|
||
|
||
### 101 Switching Protocols
|
||
|
||
- **说明**: 切换协议,服务器根据客户端的请求切换协议
|
||
- **使用场景**: WebSocket握手、HTTP升级到HTTPS
|
||
- **处理建议**: 确保客户端支持新协议
|
||
|
||
### 102 Processing
|
||
|
||
- **说明**: 处理中,服务器已接收并正在处理请求
|
||
- **使用场景**: 长时间运行的请求
|
||
- **处理建议**: 告知客户端请求正在处理,避免超时
|
||
|
||
---
|
||
|
||
## 2xx 成功状态码
|
||
|
||
### 200 OK
|
||
|
||
- **说明**: 请求成功
|
||
- **使用场景**: GET、PUT、PATCH请求成功
|
||
- **返回内容**: 请求的资源或操作结果
|
||
- **示例响应**:
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "操作成功",
|
||
"data": { "id": 1, "name": "用户" }
|
||
}
|
||
```
|
||
|
||
### 201 Created
|
||
|
||
- **说明**: 创建成功
|
||
- **使用场景**: POST请求成功创建资源
|
||
- **返回内容**: 新创建的资源信息
|
||
- **Header建议**: 添加`Location`头指向新资源
|
||
- **示例响应**:
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "创建成功",
|
||
"data": { "id": 123, "name": "新用户" }
|
||
}
|
||
```
|
||
|
||
### 202 Accepted
|
||
|
||
- **说明**: 已接受,请求已被接受,但尚未处理完成
|
||
- **使用场景**: 异步任务、批量操作
|
||
- **返回内容**: 任务状态或追踪信息
|
||
- **示例响应**:
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "任务已提交",
|
||
"data": { "taskId": "task-123", "status": "processing" }
|
||
}
|
||
```
|
||
|
||
### 204 No Content
|
||
|
||
- **说明**: 无内容,请求成功但无返回内容
|
||
- **使用场景**: DELETE请求成功、PUT更新成功
|
||
- **返回内容**: 空响应体
|
||
- **注意**: 不应返回JSON响应体
|
||
|
||
### 206 Partial Content
|
||
|
||
- **说明**: 部分内容
|
||
- **使用场景**: 文件断点续传、大文件分块下载
|
||
- **Header要求**: 必须包含`Content-Range`
|
||
- **处理建议**: 实现Range请求支持
|
||
|
||
---
|
||
|
||
## 3xx 重定向状态码
|
||
|
||
### 301 Moved Permanently
|
||
|
||
- **说明**: 永久重定向
|
||
- **使用场景**: URL结构永久性改变、API版本升级
|
||
- **Header要求**: 必须包含`Location`头
|
||
- **SEO影响**: 搜索引擎会更新索引
|
||
|
||
### 302 Found
|
||
|
||
- **说明**: 临时重定向
|
||
- **使用场景**: 临时维护、负载均衡
|
||
- **Header要求**: 必须包含`Location`头
|
||
- **注意**: 不会影响搜索引擎索引
|
||
|
||
### 304 Not Modified
|
||
|
||
- **说明**: 未修改,资源未发生变化
|
||
- **使用场景**: 缓存验证、条件请求
|
||
- **Header要求**: 配合`ETag`或`Last-Modified`
|
||
- **性能优化**: 减少带宽消耗
|
||
|
||
### 307 Temporary Redirect
|
||
|
||
- **说明**: 临时重定向(保持请求方法)
|
||
- **使用场景**: 确保POST/PUT等方法不被改变
|
||
- **与302区别**: 严格保持原始HTTP方法
|
||
|
||
### 308 Permanent Redirect
|
||
|
||
- **说明**: 永久重定向(保持请求方法)
|
||
- **使用场景**: API端点永久迁移,需保持HTTP方法
|
||
- **与301区别**: 严格保持原始HTTP方法
|
||
|
||
---
|
||
|
||
## 4xx 客户端错误状态码
|
||
|
||
### 400 Bad Request
|
||
|
||
- **说明**: 请求语法错误或参数无效
|
||
- **常见原因**:
|
||
- JSON格式错误
|
||
- 必需参数缺失
|
||
- 参数类型不正确
|
||
- 参数值超出范围
|
||
- **解决方法**:
|
||
- 验证请求格式
|
||
- 检查参数完整性
|
||
- 使用参数验证库
|
||
- **示例响应**:
|
||
|
||
```json
|
||
{
|
||
"code": 400,
|
||
"message": "参数校验失败",
|
||
"data": null,
|
||
"errors": [
|
||
{ "field": "email", "message": "邮箱格式不正确" },
|
||
{ "field": "age", "message": "年龄必须大于0" }
|
||
]
|
||
}
|
||
```
|
||
|
||
### 401 Unauthorized
|
||
|
||
- **说明**: 未认证,需要身份验证
|
||
- **常见原因**:
|
||
- 缺少认证信息
|
||
- Token已过期
|
||
- Token格式错误
|
||
- 认证信息无效
|
||
- **解决方法**:
|
||
- 提供有效的认证信息
|
||
- 刷新过期的Token
|
||
- 重新登录
|
||
- **Header建议**: 添加`WWW-Authenticate`头
|
||
- **示例响应**:
|
||
|
||
```json
|
||
{
|
||
"code": 401,
|
||
"message": "认证失败,请重新登录",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
### 403 Forbidden
|
||
|
||
- **说明**: 禁止访问,已认证但无权限
|
||
- **常见原因**:
|
||
- 权限不足
|
||
- 资源被禁止访问
|
||
- IP被封禁
|
||
- 账户被冻结
|
||
- **解决方法**:
|
||
- 联系管理员获取权限
|
||
- 检查用户角色设置
|
||
- 验证访问策略
|
||
- **示例响应**:
|
||
|
||
```json
|
||
{
|
||
"code": 403,
|
||
"message": "权限不足,无法访问该资源",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
### 404 Not Found
|
||
|
||
- **说明**: 资源不存在
|
||
- **常见原因**:
|
||
- URL路径错误
|
||
- 资源已被删除
|
||
- 资源ID不存在
|
||
- API端点不存在
|
||
- **解决方法**:
|
||
- 检查URL拼写
|
||
- 验证资源是否存在
|
||
- 确认API版本
|
||
- **示例响应**:
|
||
|
||
```json
|
||
{
|
||
"code": 404,
|
||
"message": "请求的资源不存在",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
### 405 Method Not Allowed
|
||
|
||
- **说明**: 请求方法不被允许
|
||
- **常见原因**:
|
||
- 使用了不支持的HTTP方法
|
||
- GET请求用于需要POST的接口
|
||
- **Header要求**: 必须包含`Allow`头列出支持的方法
|
||
- **示例响应**:
|
||
|
||
```json
|
||
{
|
||
"code": 405,
|
||
"message": "不支持的请求方法",
|
||
"data": null,
|
||
"allowedMethods": ["GET", "POST"]
|
||
}
|
||
```
|
||
|
||
### 406 Not Acceptable
|
||
|
||
- **说明**: 不可接受,服务器无法返回客户端可接受的内容格式
|
||
- **常见原因**:
|
||
- Accept头指定了不支持的格式
|
||
- 内容协商失败
|
||
- **解决方法**: 调整Accept头或支持更多格式
|
||
|
||
### 409 Conflict
|
||
|
||
- **说明**: 冲突,请求与当前资源状态冲突
|
||
- **常见原因**:
|
||
- 资源已存在
|
||
- 并发修改冲突
|
||
- 业务逻辑冲突
|
||
- **解决方法**:
|
||
- 重新获取最新状态
|
||
- 解决冲突后重试
|
||
- **示例响应**:
|
||
|
||
```json
|
||
{
|
||
"code": 409,
|
||
"message": "用户名已存在",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
### 410 Gone
|
||
|
||
- **说明**: 资源已永久删除
|
||
- **使用场景**: 资源被主动删除且不会恢复
|
||
- **与404区别**: 明确表示资源曾经存在但已删除
|
||
|
||
### 411 Length Required
|
||
|
||
- **说明**: 需要Content-Length头
|
||
- **常见原因**: POST/PUT请求缺少Content-Length
|
||
- **解决方法**: 添加Content-Length头
|
||
|
||
### 412 Precondition Failed
|
||
|
||
- **说明**: 前置条件失败
|
||
- **使用场景**: 条件请求(If-Match、If-None-Match等)失败
|
||
- **常见原因**: ETag不匹配、条件不满足
|
||
|
||
### 413 Payload Too Large
|
||
|
||
- **说明**: 请求体过大
|
||
- **常见原因**:
|
||
- 上传文件超出限制
|
||
- JSON数据过大
|
||
- **解决方法**:
|
||
- 减小文件大小
|
||
- 分块上传
|
||
- 调整服务器限制
|
||
- **示例响应**:
|
||
|
||
```json
|
||
{
|
||
"code": 413,
|
||
"message": "上传文件大小超出限制(最大10MB)",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
### 414 URI Too Long
|
||
|
||
- **说明**: URI过长
|
||
- **常见原因**: GET请求参数过多
|
||
- **解决方法**: 使用POST请求或减少参数
|
||
|
||
### 415 Unsupported Media Type
|
||
|
||
- **说明**: 不支持的媒体类型
|
||
- **常见原因**:
|
||
- Content-Type不正确
|
||
- 上传了不支持的文件格式
|
||
- **解决方法**: 检查Content-Type头
|
||
- **示例响应**:
|
||
|
||
```json
|
||
{
|
||
"code": 415,
|
||
"message": "不支持的文件格式,仅支持图片文件",
|
||
"data": null,
|
||
"supportedTypes": ["image/jpeg", "image/png", "image/gif"]
|
||
}
|
||
```
|
||
|
||
### 422 Unprocessable Entity
|
||
|
||
- **说明**: 无法处理的实体,语法正确但语义错误
|
||
- **常见原因**:
|
||
- 业务逻辑验证失败
|
||
- 数据关联性错误
|
||
- 状态不允许操作
|
||
- **与400区别**: 语法正确但业务逻辑错误
|
||
- **示例响应**:
|
||
|
||
```json
|
||
{
|
||
"code": 422,
|
||
"message": "业务逻辑验证失败",
|
||
"data": null,
|
||
"errors": [{ "field": "endDate", "message": "结束日期不能早于开始日期" }]
|
||
}
|
||
```
|
||
|
||
### 423 Locked
|
||
|
||
- **说明**: 资源被锁定
|
||
- **使用场景**: WebDAV、文件编辑锁定
|
||
- **解决方法**: 等待锁定释放或强制解锁
|
||
|
||
### 429 Too Many Requests
|
||
|
||
- **说明**: 请求过于频繁
|
||
- **常见原因**:
|
||
- 超出API调用频率限制
|
||
- 防暴力破解保护
|
||
- **Header建议**:
|
||
- `Retry-After`: 建议重试时间
|
||
- `X-RateLimit-*`: 频率限制信息
|
||
- **解决方法**:
|
||
- 降低请求频率
|
||
- 实现指数退避重试
|
||
- **示例响应**:
|
||
|
||
```json
|
||
{
|
||
"code": 429,
|
||
"message": "请求过于频繁,请稍后重试",
|
||
"data": null,
|
||
"retryAfter": 60
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 5xx 服务器错误状态码
|
||
|
||
### 500 Internal Server Error
|
||
|
||
- **说明**: 服务器内部错误
|
||
- **常见原因**:
|
||
- 代码异常未捕获
|
||
- 数据库连接失败
|
||
- 第三方服务异常
|
||
- 配置错误
|
||
- **解决方法**:
|
||
- 检查服务器日志
|
||
- 修复代码bug
|
||
- 验证配置正确性
|
||
- **开发环境响应**:
|
||
|
||
```json
|
||
{
|
||
"code": 500,
|
||
"message": "服务器内部错误",
|
||
"data": null,
|
||
"traceId": "req-123456",
|
||
"details": "NullPointerException at line 42",
|
||
"stack": "详细堆栈信息..."
|
||
}
|
||
```
|
||
|
||
- **生产环境响应**:
|
||
|
||
```json
|
||
{
|
||
"code": 500,
|
||
"message": "服务器内部错误,请稍后重试",
|
||
"data": null,
|
||
"traceId": "req-123456"
|
||
}
|
||
```
|
||
|
||
### 501 Not Implemented
|
||
|
||
- **说明**: 功能未实现
|
||
- **使用场景**: API端点规划但未开发
|
||
- **解决方法**: 等待功能开发完成
|
||
|
||
### 502 Bad Gateway
|
||
|
||
- **说明**: 网关错误
|
||
- **常见原因**:
|
||
- 上游服务器响应无效
|
||
- 代理服务器配置错误
|
||
- 负载均衡器问题
|
||
- **解决方法**:
|
||
- 检查上游服务状态
|
||
- 验证代理配置
|
||
- 重启相关服务
|
||
|
||
### 503 Service Unavailable
|
||
|
||
- **说明**: 服务不可用
|
||
- **常见原因**:
|
||
- 服务器维护
|
||
- 系统过载
|
||
- 依赖服务不可用
|
||
- **Header建议**: 添加`Retry-After`头
|
||
- **解决方法**:
|
||
- 等待维护完成
|
||
- 扩容服务器
|
||
- 修复依赖服务
|
||
- **示例响应**:
|
||
|
||
```json
|
||
{
|
||
"code": 503,
|
||
"message": "服务暂时不可用,系统维护中",
|
||
"data": null,
|
||
"retryAfter": 3600
|
||
}
|
||
```
|
||
|
||
### 504 Gateway Timeout
|
||
|
||
- **说明**: 网关超时
|
||
- **常见原因**:
|
||
- 上游服务响应超时
|
||
- 网络延迟过高
|
||
- 处理时间过长
|
||
- **解决方法**:
|
||
- 优化上游服务性能
|
||
- 增加超时时间
|
||
- 实现异步处理
|
||
|
||
### 505 HTTP Version Not Supported
|
||
|
||
- **说明**: HTTP版本不支持
|
||
- **解决方法**: 使用支持的HTTP版本
|
||
|
||
---
|
||
|
||
## API 错误处理最佳实践
|
||
|
||
### 1. 统一错误响应格式
|
||
|
||
```json
|
||
{
|
||
"code": 400,
|
||
"message": "用户友好的错误描述",
|
||
"data": null,
|
||
"traceId": "req-uuid-123",
|
||
"timestamp": "2024-01-01T12:00:00Z",
|
||
"errors": [
|
||
{
|
||
"field": "email",
|
||
"message": "邮箱格式不正确",
|
||
"code": "INVALID_EMAIL_FORMAT"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 2. 错误码设计原则
|
||
|
||
- **HTTP状态码**: 表示HTTP层面的处理结果
|
||
- **业务错误码**: 表示具体的业务错误类型
|
||
- **错误消息**: 提供用户友好的错误描述
|
||
- **错误详情**: 开发环境提供详细信息,生产环境保护敏感信息
|
||
|
||
### 3. 常见业务错误码映射
|
||
|
||
| 业务场景 | HTTP状态码 | 业务错误码 | 错误消息 |
|
||
| ---------------- | ---------- | ---------- | -------------------- |
|
||
| 参数校验失败 | 400 | 1001 | 参数校验失败 |
|
||
| 用户名或密码错误 | 400 | 1002 | 用户名或密码错误 |
|
||
| Token无效 | 401 | 1003 | 认证失败,请重新登录 |
|
||
| 权限不足 | 403 | 1004 | 权限不足 |
|
||
| 资源不存在 | 404 | 1005 | 请求的资源不存在 |
|
||
| 资源已存在 | 409 | 1006 | 资源已存在 |
|
||
| 请求频率限制 | 429 | 1007 | 请求过于频繁 |
|
||
| 系统错误 | 500 | 2001 | 系统内部错误 |
|
||
| 数据库错误 | 500 | 2002 | 数据存储错误 |
|
||
| 第三方服务错误 | 502 | 2003 | 外部服务错误 |
|
||
|
||
### 4. 错误日志记录
|
||
|
||
```typescript
|
||
// 错误日志应包含的信息
|
||
{
|
||
timestamp: "2024-01-01T12:00:00Z",
|
||
level: "ERROR",
|
||
message: "用户登录失败",
|
||
traceId: "req-uuid-123",
|
||
userId: "user-456",
|
||
ip: "192.168.1.100",
|
||
userAgent: "Mozilla/5.0...",
|
||
path: "/api/login",
|
||
method: "POST",
|
||
statusCode: 400,
|
||
errorCode: 1002,
|
||
errorType: "BUSINESS_ERROR",
|
||
stack: "错误堆栈信息...",
|
||
requestBody: { /* 脱敏后的请求数据 */ },
|
||
context: { /* 其他上下文信息 */ }
|
||
}
|
||
```
|
||
|
||
### 5. 客户端错误处理建议
|
||
|
||
```typescript
|
||
// 客户端错误处理示例
|
||
async function handleApiError(error: ApiError) {
|
||
const { status, data } = error.response;
|
||
|
||
switch (status) {
|
||
case 400:
|
||
// 显示参数错误信息
|
||
showValidationErrors(data.errors);
|
||
break;
|
||
case 401:
|
||
// 清除本地token,跳转登录页
|
||
clearToken();
|
||
redirectToLogin();
|
||
break;
|
||
case 403:
|
||
// 显示权限不足提示
|
||
showPermissionDenied();
|
||
break;
|
||
case 404:
|
||
// 显示资源不存在
|
||
showNotFound();
|
||
break;
|
||
case 429:
|
||
// 实现指数退避重试
|
||
await retryWithBackoff();
|
||
break;
|
||
case 500:
|
||
case 502:
|
||
case 503:
|
||
case 504:
|
||
// 显示系统错误,建议稍后重试
|
||
showSystemError(data.message);
|
||
break;
|
||
default:
|
||
// 显示通用错误信息
|
||
showGenericError();
|
||
}
|
||
}
|
||
```
|
||
|
||
### 6. 监控和告警
|
||
|
||
- **4xx错误**: 监控客户端错误趋势,可能表示API设计问题
|
||
- **5xx错误**: 立即告警,表示系统问题需要紧急处理
|
||
- **特定错误码**: 针对业务关键错误设置专门监控
|
||
- **错误率阈值**: 设置错误率阈值告警
|
||
|
||
---
|
||
|
||
## 总结
|
||
|
||
正确使用HTTP状态码是RESTful API设计的重要组成部分。遵循标准的状态码使用规范,结合清晰的错误消息和完善的错误处理机制,能够显著提升API的可用性和开发体验。
|
||
|
||
### 关键原则
|
||
|
||
1. **语义明确**: 状态码应准确反映请求的处理结果
|
||
2. **一致性**: 相同类型的错误应使用相同的状态码
|
||
3. **用户友好**: 错误消息应易于理解且可操作
|
||
4. **安全性**: 生产环境不暴露敏感系统信息
|
||
5. **可追踪**: 每个错误都应有唯一标识便于追踪
|
||
6. **可监控**: 重要错误应有相应的监控和告警机制
|
||
|
||
正确实施这些错误处理策略将大大提升系统的健壮性和可维护性。
|