返回博客
技术 2025年2月11日 4 分钟阅读 · 966 字
RESTful API 设计最佳实践:从 URI 规范到错误处理的完整指南
构建可维护、可扩展的 RESTful API 需要遵循的 10 条核心原则,涵盖 URI 设计、状态码、分页、版本控制与安全。
#RESTful API
#后端开发
#HTTP
#API 设计
本文由 AI 辅助生成,经人工审核发布
1. URI 设计:名词而非动词
REST 的核心是资源,URI 应该用名词描述资源,HTTP 方法描述操作:
# ✅ 正确
GET /api/users # 获取用户列表
POST /api/users # 创建用户
GET /api/users/123 # 获取单个用户
PUT /api/users/123 # 更新用户(完整替换)
PATCH /api/users/123 # 部分更新
DELETE /api/users/123 # 删除用户
# ❌ 错误
GET /api/getUsers
POST /api/createUser
GET /api/deleteUserById?id=123
嵌套资源
GET /api/users/123/orders # 用户的订单列表
GET /api/users/123/orders/456 # 用户的特定订单
嵌套层级建议不超过 2 层。更深的关联用查询参数:
GET /api/orders?user_id=123&status=paid
2. HTTP 状态码
使用语义化的状态码,不要所有响应都返回 200:
| 状态码 | 含义 | 使用场景 |
|---|---|---|
| 200 OK | 成功 | GET、PUT、PATCH 成功 |
| 201 Created | 已创建 | POST 成功创建资源 |
| 204 No Content | 无内容 | DELETE 成功 |
| 400 Bad Request | 请求错误 | 参数验证失败 |
| 401 Unauthorized | 未认证 | 缺少/无效的 Token |
| 403 Forbidden | 禁止 | 权限不足 |
| 404 Not Found | 不存在 | 资源未找到 |
| 409 Conflict | 冲突 | 唯一约束冲突 |
| 422 Unprocessable | 无法处理 | 业务逻辑验证失败 |
| 429 Too Many Requests | 频率限制 | 限流触发 |
统一错误响应格式
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "请求参数验证失败",
"details": [
{ "field": "email", "message": "邮箱格式不正确" },
{ "field": "password", "message": "密码至少 8 位" }
]
}
}
3. 分页、排序与过滤
分页
GET /api/users?page=2&per_page=20
响应中包含分页元数据:
{
"data": [...],
"meta": {
"current_page": 2,
"per_page": 20,
"total": 150,
"last_page": 8
},
"links": {
"prev": "/api/users?page=1&per_page=20",
"next": "/api/users?page=3&per_page=20"
}
}
游标分页(大数据量)
传统分页在数据量大时性能差(OFFSET 100000 需要扫描 100000 行)。游标分页用上一页最后一条记录的 ID 作为起点:
GET /api/users?cursor=eyJpZCI6MTAwfQ&per_page=20
-- 传统分页:慢
SELECT * FROM users ORDER BY id DESC LIMIT 20 OFFSET 100000;
-- 游标分页:快
SELECT * FROM users WHERE id < 100 ORDER BY id DESC LIMIT 20;
排序
GET /api/users?sort=-created_at,name
# - 表示降序,多个字段用逗号分隔
过滤
GET /api/orders?status=paid&amount_min=100&amount_max=500
4. 版本控制
URI 版本(推荐)
GET /api/v1/users
GET /api/v2/users
简单直接,易于调试和缓存。
Header 版本
GET /api/users
Accept: application/vnd.myapp.v2+json
不污染 URI,但调试困难,需要文档说明。
5. 请求与响应格式
请求 Content-Type
POST /api/users
Content-Type: application/json
{ "name": "Li Xiang", "email": "li@example.com" }
字段命名
统一使用 snake_case 或 camelCase,团队内保持一致:
{
"user_id": 123,
"created_at": "2025-01-15T10:30:00Z",
"is_active": true
}
时间格式
始终使用 ISO 8601 UTC:
{ "created_at": "2025-01-15T10:30:00Z" }
不要使用时间戳(1736933400)或本地时间格式。
6. 认证与授权
Bearer Token
GET /api/users/123
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
API Key(服务间调用)
GET /api/internal/sync
X-API-Key: your-secret-key
7. 限流
在响应头中返回限流信息:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1736933700
超过限制时返回 429:
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "请求过于频繁,请稍后再试",
"retry_after": 60
}
}
8. 幂等性
| 方法 | 幂等 | 安全 |
|---|---|---|
| GET | ✅ | ✅ |
| POST | ❌ | ❌ |
| PUT | ✅ | ❌ |
| DELETE | ✅ | ❌ |
| PATCH | ❌ | ❌ |
DELETE /api/users/123 调用一次和调用十次效果相同——用户被删除。客户端可以在网络超时后安全重试。
9. CORS 配置
// Laravel CORS 配置
'paths' => ['api/*'],
'allowed_methods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
'allowed_origins' => ['https://example.com'],
'allowed_headers' => ['Content-Type', 'Authorization'],
生产环境不要使用 * 作为 allowed_origins。
10. 文档与测试
OpenAPI / Swagger
用注释生成 API 文档:
/**
* @OA\Get(
* path="/api/users/{id}",
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
* @OA\Response(response=200, description="用户详情",
* @OA\JsonContent(ref="#/components/schemas/User")
* ),
* @OA\Response(response=404, description="用户不存在")
* )
*/
集成测试
public function test_can_create_user(): void
{
$response = $this->postJson('/api/v1/users', [
'name' => 'Li Xiang',
'email' => 'li@example.com',
'password' => 'secure-password',
]);
$response->assertStatus(201)
->assertJsonStructure([
'data' => ['id', 'name', 'email', 'created_at']
]);
}
总结
好的 RESTful API 设计核心是一致性和可预测性。开发者看到 GET /api/orders/123/items 就应该知道这是获取订单 123 的商品列表,不需要查文档。遵循这些规范可以显著降低团队协作和后续维护的成本。