API设计框架
概览
这项技能提供了全面的设计指导,用于设计健壮、可扩展且对开发者友好的API。无论是构建REST、GraphQL还是gRPC服务,此框架确保了一致性、可用性和可维护性。
何时使用这项技能:
- 设计新的API端点或服务
- 为团队或组织建立API约定
- 审核API设计以确保一致性和最佳实践
- 迁移或版本控制现有API
- 创建API文档(OpenAPI、AsyncAPI)
- 在REST、GraphQL或gRPC之间做出选择
API设计原则
1. 开发者体验优先
API应直观且自文档化:
- 清晰、一致的命名约定
- 可预测的行为和响应
- 全面的文档
- 有帮助的错误消息
2. 一致性优于巧妙
遵循既定模式而不是发明新模式:
- 标准的HTTP方法和状态代码(REST)
- 常规查询结构(GraphQL)
- 惯用的proto定义(gRPC)
3. 进化而不破坏变更
从第一天起就为变更设计:
- API版本控制策略
- 向后兼容性考虑
- 弃用政策
- 迁移路径
4. 性能由设计决定
考虑性能影响:
- 大数据集的分页
- 过滤和部分响应
- 缓存策略
- 速率限制
REST API设计
资源命名约定
对资源使用复数名词:
✅ GET /users
✅ GET /users/123
✅ GET /users/123/orders
❌ GET /user
❌ GET /getUser
❌ GET /user/123
使用层次关系:
✅ GET /users/123/orders # 特定用户的订单
✅ GET /teams/5/members # 特定团队的成员
✅ POST /projects/10/tasks # 在项目10中创建任务
❌ GET /userOrders/123 # 平坦结构
❌ GET /orders?userId=123 # 关系的查询参数
对多词资源使用kebab-case:
✅ /shopping-carts
✅ /order-items
✅ /user-preferences
❌ /shoppingCarts (camelCase)
❌ /shopping_carts (snake_case)
❌ /ShoppingCarts (PascalCase)
HTTP方法(动词)
| 方法 | 目的 | 幂等 | 安全 | 示例 |
|---|---|---|---|---|
| GET | 检索资源 | 是 | 是 | GET /users/123 |
| POST | 创建资源 | 否 | 否 | POST /users |
| PUT | 替换整个资源 | 是 | 否 | PUT /users/123 |
| PATCH | 部分更新 | 否* | 否 | PATCH /users/123 |
| DELETE | 移除资源 | 是 | 否 | DELETE /users/123 |
| HEAD | 仅元数据(无正文) | 是 | 是 | HEAD /users/123 |
| OPTIONS | 允许的方法 | 是 | 是 | OPTIONS /users |
*PATCH可以设计为幂等
状态代码
成功(2xx)
- 200 OK:成功的GET、PUT、PATCH或DELETE
- 201 Created:成功的POST(包括
Location头部) - 202 Accepted:请求被接受,异步处理
- 204 No Content:成功的DELETE或PUT无响应正文
客户端错误(4xx)
- 400 Bad Request:无效的请求正文或参数
- 401 Unauthorized:缺少或无效的身份验证
- 403 Forbidden:已认证但未授权
- 404 Not Found:资源不存在
- 405 Method Not Allowed:HTTP方法不支持资源
- 409 Conflict:资源冲突(例如,重复)
- 422 Unprocessable Entity:验证失败
- 429 Too Many Requests:速率限制超出
服务器错误(5xx)
- 500 Internal Server Error:通用服务器错误
- 502 Bad Gateway:上游服务错误
- 503 Service Unavailable:暂时不可用
- 504 Gateway Timeout:上游超时
请求/响应格式
请求正文(POST/PUT/PATCH):
POST /users
Content-Type: application/json
{
"email": "jane@example.com",
"name": "Jane Smith",
"role": "developer"
}
成功响应:
HTTP/1.1 201 Created
Location: /users/123
Content-Type: application/json
{
"id": 123,
"email": "jane@example.com",
"name": "Jane Smith",
"role": "developer",
"created_at": "2025-10-31T10:30:00Z",
"updated_at": "2025-10-31T10:30:00Z"
}
错误响应(标准格式):
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "请求验证失败",
"details": [
{
"field": "email",
"message": "电子邮件已注册",
"code": "DUPLICATE_EMAIL"
},
{
"field": "name",
"message": "名称至少2个字符",
"code": "NAME_TOO_SHORT"
}
],
"timestamp": "2025-10-31T10:30:00Z",
"request_id": "req_abc123"
}
}
分页
基于游标的分页(推荐):
GET /users?cursor=eyJpZCI6MTIzfQ&limit=20
响应:
{
"data": [...],
"pagination": {
"next_cursor": "eyJpZCI6MTQzfQ",
"has_more": true
}
}
优点:即使数据变化,结果也一致 用途:大数据集、实时数据、无限滚动
基于偏移量的分页:
GET /users?page=2&per_page=20
响应:
{
"data": [...],
"pagination": {
"page": 2,
"per_page": 20,
"total": 487,
"total_pages": 25
}
}
优点:易于理解,支持“跳至第N页” 用途:小数据集、管理面板、已知界限
过滤和排序
过滤:
GET /users?status=active&role=developer&created_after=2025-01-01
GET /products?price_min=10&price_max=100&category=electronics
排序:
GET /users?sort=created_at:desc
GET /users?sort=-created_at # 减号前缀表示降序
GET /users?sort=name:asc,created_at:desc # 多个字段
字段选择(部分响应):
GET /users?fields=id,name,email # 仅指定字段
GET /users/123?exclude=password_hash # 除了指定的之外全部
API版本控制
策略1:URI版本控制(推荐)
✅ /api/v1/users
✅ /api/v2/users
优点:清晰,易于测试,缓存友好
缺点:URL冗长
策略2:头部版本控制
GET /api/users
Accept: application/vnd.company.v2+json
优点:URL清晰
缺点:测试难度大,URL不可见
策略3:查询参数
GET /api/users?version=2
优点:简单
缺点:可能会被遗忘,与业务逻辑参数混合
最佳实践:公共API使用URI版本控制,内部服务使用头部版本控制
速率限制
响应头部:
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 987
X-RateLimit-Reset: 1635724800
超出时的响应:
HTTP/1.1 429 Too Many Requests
Retry-After: 3600
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "API速率限制超出",
"retry_after": 3600
}
}
认证与授权
Bearer Token(JWT):
GET /users/me
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
API密钥:
GET /users
X-API-Key: sk_live_abc123...
基本认证(生产中避免使用):
GET /users
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
GraphQL API设计
架构设计原则
1. 默认可空
type User {
id: ID! # 非空(必需)
email: String! # 非空
name: String # 可空(可选)
avatar: String # 可空
}
2. 对列表使用连接
type Query {
users(first: Int, after: String): UserConnection!
}
type UserConnection {
edges: [UserEdge!]!
pageInfo: PageInfo!
totalCount: Int!
}
type UserEdge {
node: User!
cursor: String!
}
type PageInfo {
hasNextPage: Boolean!
hasPreviousPage: Boolean!
startCursor: String
endCursor: String
}
3. 为突变使用输入类型
input CreateUserInput {
email: String!
name: String!
role: UserRole!
}
type Mutation {
createUser(input: CreateUserInput!): CreateUserPayload!
}
type CreateUserPayload {
user: User!
errors: [UserError!]
}
type UserError {
field: String!
message: String!
code: String!
}
查询设计
获取单个资源:
query GetUser {
user(id: "123") {
id
name
email
posts {
id
title
}
}
}
获取带有过滤器的列表:
query GetUsers {
users(
first: 10
after: "cursor123"
filter: { role: DEVELOPER, status: ACTIVE }
) {
edges {
node {
id
name
email
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
错误处理
字段级错误:
type Mutation {
createUser(input: CreateUserInput!): CreateUserPayload!
}
type CreateUserPayload {
user: User
errors: [UserError!]
}
响应:
{
"data": {
"createUser": {
"user": null,
"errors": [
{
"field": "email",
"message": "电子邮件已被占用",
"code": "DUPLICATE_EMAIL"
}
]
}
}
}
gRPC API设计
Proto文件结构
user.proto:
syntax = "proto3";
package company.user.v1;
import "google/protobuf/timestamp.proto";
import "google/protobuf/empty.proto";
// 用户服务定义
service UserService {
// 通过ID获取用户
rpc GetUser(GetUserRequest) returns (GetUserResponse);
// 分页列出用户
rpc ListUsers(ListUsersRequest) returns (ListUsersResponse);
// 创建新用户
rpc CreateUser(CreateUserRequest) returns (CreateUserResponse);
// 更新用户
rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse);
// 删除用户
rpc DeleteUser(DeleteUserRequest) returns (google.protobuf.Empty);
// 流更新(服务器流)
rpc WatchUsers(WatchUsersRequest) returns (stream UserEvent);
}
// 消息
message User {
string id = 1;
string email = 2;
string name = 3;
UserRole role = 4;
google.protobuf.Timestamp created_at = 5;
google.protobuf.Timestamp updated_at = 6;
}
enum UserRole {
USER_ROLE_UNSPECIFIED = 0;
USER_ROLE_ADMIN = 1;
USER_ROLE_DEVELOPER = 2;
USER_ROLE_VIEWER = 3;
}
message GetUserRequest {
string id = 1;
}
message GetUserResponse {
User user = 1;
}
message ListUsersRequest {
int32 page_size = 1;
string page_token = 2;
string filter = 3; // 例如,"role=DEVELOPER AND status=ACTIVE"
}
message ListUsersResponse {
repeated User users = 1;
string next_page_token = 2;
int32 total_size = 3;
}
message CreateUserRequest {
string email = 1;
string name = 2;
UserRole role = 3;
}
message CreateUserResponse {
User user = 1;
}
错误处理
使用gRPC状态代码:
// OK: 成功
// CANCELLED: 客户端取消
// INVALID_ARGUMENT: 无效请求(400等效)
// NOT_FOUND: 资源未找到(404等效)
// ALREADY_EXISTS: 重复(409等效)
// PERMISSION_DENIED: 禁止(403等效)
// UNAUTHENTICATED: 需要认证(401等效)
// RESOURCE_EXHAUSTED: 速率限制(429等效)
// INTERNAL: 服务器错误(500等效)
API文档
OpenAPI 3.1结构
参见/templates/openapi-template.yaml了解完整示例。
关键部分:
- info: API元数据(标题、版本、描述)
- servers: 不同环境的基础URL
- paths: 端点与操作
- components: 可重用的模式、响应、参数
- security: 认证方案
AsyncAPI 3.0(事件驱动)
用于记录基于消息的API(Kafka、RabbitMQ、WebSocket)。
参见/templates/asyncapi-template.yaml了解完整示例。
最佳实践
1. 使用标准媒体类型
Content-Type: application/json # JSON
Content-Type: application/xml # XML
Content-Type: application/protobuf # Protocol Buffers
Content-Type: application/octet-stream # 二进制数据
2. HATEOAS(REST可选)
包含相关资源的链接:
{
"id": 123,
"name": "Jane Smith",
"_links": {
"self": { "href": "/users/123" },
"orders": { "href": "/users/123/orders" },
"avatar": { "href": "/users/123/avatar" }
}
}
3. 幂等键
防止重复操作:
POST /payments
Idempotency-Key: unique-request-id-123
4. 批量操作
POST /users/bulk-create
POST /users/bulk-update
POST /users/bulk-delete
5. Webhooks
记录Webhook有效载荷和重试逻辑:
POST https://client.example.com/webhook
X-Webhook-Signature: sha256=abc123...
{
"event": "user.created",
"data": { ... },
"timestamp": "2025-10-31T10:30:00Z"
}
常见陷阱
❌ 在URL中使用动词
不良:POST /createUser
良好:POST /users
❌ 不一致的命名
不良:/users, /userOrders, /user_preferences
良好:/users, /orders, /preferences
❌ 忽略HTTP方法
不良:POST /users/123/delete
良好:DELETE /users/123
❌ 暴露实现细节
不良:/users-table, /get-user-from-db
良好:/users, /users/123
❌ 通用错误消息
不良:{ "error": "Something went wrong" }
良好:{ "error": { "code": "DUPLICATE_EMAIL", "message": "电子邮件已存在" }}
与代理集成
后端系统架构师
- 在设计新API时使用此框架
- 参考模式以实现服务间的一致性
- 从模板创建OpenAPI规范
前端UI开发人员
- 实施前审查API合同
- 提供开发者体验的反馈
- 与遵循文档模式的API集成
代码质量审查员
- 根据此框架验证API设计
- 确保OpenAPI文档准确完整
- 检查REST/GraphQL/gRPC最佳实践
技能版本:1.0.0 最后更新:2025-10-31 维护者:AI代理中心团队