好的 API 设计让前端、移动端和第三方集成事半功倍;差的 API 则让每个人都在 Slack 上问「这个字段什么意思」。本文总结我们在多个项目中沉淀的 RESTful API 设计规范。
资源命名:名词复数,层级清晰
GET /api/v1/users # 用户列表
GET /api/v1/users/{id} # 单个用户
POST /api/v1/users # 创建用户
PUT /api/v1/users/{id} # 全量更新
PATCH /api/v1/users/{id} # 部分更新
DELETE /api/v1/users/{id} # 删除用户
GET /api/v1/users/{id}/orders # 用户的订单(嵌套资源)
避免的反面模式:
/getUserById— 动词不应出现在 URL 中/user— 用复数形式/api/deleteUser/123— 用 HTTP 方法表达动作
HTTP 方法语义
正确使用 HTTP 方法是 REST 的基本功:
- GET:安全且幂等,不修改资源
- POST:创建资源,非幂等
- PUT:全量替换,幂等
- PATCH:部分更新(JSON Merge Patch 或 JSON Patch)
- DELETE:删除资源,幂等
状态码:精确表达结果
| 状态码 | 场景 |
|---|---|
| 200 OK | 成功返回数据 |
| 201 Created | 创建成功,Location 头指向新资源 |
| 204 No Content | 删除成功或更新成功无返回体 |
| 400 Bad Request | 请求参数校验失败 |
| 401 Unauthorized | 未认证(缺少或无效的 token) |
| 403 Forbidden | 已认证但无权限 |
| 404 Not Found | 资源不存在 |
| 409 Conflict | 资源冲突(如重复创建) |
| 422 Unprocessable Entity | 语义校验失败(业务规则不满足) |
| 429 Too Many Requests | 限流 |
统一错误响应格式
遵循 RFC 9457 Problem Details 标准,让客户端可以程序化地处理错误:
{
"type": "https://api.example.com/errors/validation",
"title": "Validation Error",
"status": 400,
"detail": "Email format is invalid",
"instance": "/api/v1/users",
"errors": [
{"field": "email", "message": "must be a valid email address"}
]
}
分页、过滤与排序
列表接口的标准参数约定:
GET /api/v1/users?page=2&size=20&sort=createdAt,desc&status=active
# 响应
{
"data": [...],
"meta": {
"page": 2,
"size": 20,
"total": 156,
"totalPages": 8
}
}
数据量极大时考虑 cursor-based 分页(?cursor=xxx&limit=20),避免深翻页性能问题。
版本控制策略
三种主流方式,推荐 URL 路径版本(最简单直观):
- URL 路径:
/api/v1/users— 推荐,清晰明确 - 请求头:
Accept: application/vnd.api+json;version=1 - 查询参数:
?version=1— 不推荐,容易被忽略
破坏性变更必须升 major 版本,新增字段、新增端点是向后兼容的。
文档与契约
- 用 OpenAPI 3.1 描述 API 契约,自动生成文档和客户端 SDK
- 请求/响应示例覆盖正常和异常场景
- 字段标注 required/optional、类型、枚举值和默认值
- CI 中做 breaking change 检测(如 oasdiff)
安全基线
- 全站 HTTPS,HSTS 强制
- 认证用 Bearer Token(JWT 或 opaque token)
- 输入校验在服务端做,不信任客户端
- 敏感字段(密码、token)不出现在 URL 中
- 限流 + 幂等键(
Idempotency-Key头)防止重复提交
小结
优秀的 API 设计原则:一致的命名、正确的 HTTP 语义、统一的错误格式、完善的文档。API 是前后端之间的契约,投入设计时间,回报是更少的联调扯皮和更快的迭代速度。