什么是好的 API?

好的 API 应该是:

  • 易于理解 - 清晰的命名和文档
  • 易于使用 - 一致的设计模式
  • 易于维护 - 良好的版本控制和向后兼容性
  • 安全可靠 - 身份验证、授权、速率限制
  • 高性能 - 快速响应和高效的资源使用

RESTful API 原则

基本概念

REST(Representational State Transfer)是一种架构风格,基于以下原则:

  1. 客户端-服务器架构 - 分离关注点
  2. 无状态 - 每个请求包含所有必要信息
  3. 可缓存 - 响应应该定义自己是否可缓存
  4. 统一接口 - 一致的 API 设计
  5. 分层系统 - 客户端不知道是否直接连接到最终服务器

HTTP 方法

GET     获取资源
POST    创建新资源
PUT     替换整个资源
PATCH   部分更新资源
DELETE  删除资源
HEAD    获取资源元数据(不返回响应体)
OPTIONS 获取资源的通信选项

资源和 URL 设计

好的设计:
GET    /api/v1/users              获取用户列表
POST   /api/v1/users              创建新用户
GET    /api/v1/users/:id          获取特定用户
PUT    /api/v1/users/:id          更新用户
DELETE /api/v1/users/:id          删除用户
GET    /api/v1/users/:id/posts    获取用户的文章

不好的设计:
GET    /api/getUser               
GET    /api/createUser            
GET    /api/updateUser?id=1       
GET    /api/deleteUser?id=1       

关键原则

  1. 使用名词而不是动词 - /users 而不是 /getUsers
  2. 使用复数形式 - /users 而不是 /user
  3. 使用小写 - /api/users 而不是 /api/Users
  4. 使用连字符分隔单词 - /user-profiles 而不是 /userProfiles
  5. 避免深层嵌套 - 最多两层 /users/:id/posts

版本控制

URL 版本控制(推荐)

/api/v1/users
/api/v2/users

请求头版本控制

GET /api/users
Accept: application/vnd.myapi.v1+json

查询参数版本控制

GET /api/users?version=1

请求和响应格式

请求示例

POST /api/v1/users
Content-Type: application/json

{
  "name": "John Doe",
  "email": "john@example.com",
  "age": 30
}

成功响应示例

HTTP/1.1 201 Created
Content-Type: application/json

{
  "id": 1,
  "name": "John Doe",
  "email": "john@example.com",
  "age": 30,
  "createdAt": "2025-12-15T10:00:00Z"
}

响应结构

{
  "status": "success",
  "code": 200,
  "data": {
    "id": 1,
    "name": "John Doe"
  },
  "message": "User retrieved successfully"
}

HTTP 状态码

2xx 成功

200 OK              请求成功
201 Created         资源创建成功
204 No Content      请求成功但无返回内容

3xx 重定向

301 Moved Permanently    永久重定向
302 Found               临时重定向
304 Not Modified        资源未修改

4xx 客户端错误

400 Bad Request         请求格式错误
401 Unauthorized        需要身份验证
403 Forbidden          无权限访问
404 Not Found          资源不存在
409 Conflict           请求冲突
422 Unprocessable Entity 请求格式正确但包含语义错误
429 Too Many Requests   请求过于频繁

5xx 服务器错误

500 Internal Server Error   服务器内部错误
502 Bad Gateway            网关错误
503 Service Unavailable    服务不可用

错误处理

统一的错误响应格式

{
  "status": "error",
  "code": 400,
  "error": {
    "type": "ValidationError",
    "message": "Invalid input",
    "details": [
      {
        "field": "email",
        "message": "Invalid email format"
      },
      {
        "field": "age",
        "message": "Age must be at least 18"
      }
    ]
  }
}

错误处理最佳实践

// Express.js 示例
app.post('/api/v1/users', (req, res) => {
  try {
    // 验证输入
    if (!req.body.email) {
      return res.status(400).json({
        status: 'error',
        code: 400,
        error: {
          type: 'ValidationError',
          message: 'Email is required'
        }
      });
    }

    // 处理请求
    const user = createUser(req.body);
    
    res.status(201).json({
      status: 'success',
      code: 201,
      data: user
    });
  } catch (error) {
    res.status(500).json({
      status: 'error',
      code: 500,
      error: {
        type: 'InternalServerError',
        message: 'An unexpected error occurred'
      }
    });
  }
});

分页和过滤

分页

GET /api/v1/users?page=1&limit=10
GET /api/v1/users?offset=0&limit=10

响应示例

{
  "status": "success",
  "data": [...],
  "pagination": {
    "page": 1,
    "limit": 10,
    "total": 100,
    "totalPages": 10
  }
}

过滤和排序

GET /api/v1/users?status=active&sort=name&order=asc
GET /api/v1/users?role=admin&createdAfter=2025-01-01

身份验证和授权

JWT 身份验证

// 登录端点
POST /api/v1/auth/login
{
  "email": "user@example.com",
  "password": "password123"
}

// 响应
{
  "status": "success",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "expiresIn": 3600
  }
}

// 使用 token 访问受保护的资源
GET /api/v1/users/me
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

速率限制

HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 1640000000

API 文档

使用 OpenAPI/Swagger

openapi: 3.0.0
info:
  title: User API
  version: 1.0.0
paths:
  /api/v1/users:
    get:
      summary: Get all users
      parameters:
        - name: page
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: List of users
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'
    post:
      summary: Create a new user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserInput'
      responses:
        '201':
          description: User created

向后兼容性

版本控制策略

  1. 添加新字段 - 安全,客户端可以忽略
  2. 重命名字段 - 保留旧字段,添加新字段
  3. 删除字段 - 先弃用,后删除
  4. 更改字段类型 - 创建新版本

弃用策略

HTTP/1.1 200 OK
Deprecation: true
Sunset: Sun, 31 Dec 2025 23:59:59 GMT
Link: </api/v2/users>; rel="successor-version"

安全最佳实践

  1. 使用 HTTPS - 加密传输
  2. 验证输入 - 防止注入攻击
  3. 实施速率限制 - 防止滥用
  4. 使用 CORS - 控制跨域访问
  5. 实施身份验证 - 保护敏感资源
  6. 记录和监控 - 追踪异常活动
  7. 定期更新依赖 - 修复安全漏洞

性能优化

  1. 使用缓存 - 减少数据库查询
  2. 分页 - 限制返回数据量
  3. 字段选择 - 只返回需要的字段
  4. 异步处理 - 长时间操作使用后台任务
  5. 数据库优化 - 索引、查询优化

API 设计检查清单

  • 使用 RESTful 原则
  • 一致的 URL 设计
  • 适当的 HTTP 方法
  • 正确的状态码
  • 统一的错误格式
  • 版本控制
  • 身份验证和授权
  • 速率限制
  • 完整的文档
  • 向后兼容性
  • 安全措施
  • 性能优化

总结

设计好的 API 需要考虑多个方面,包括可用性、安全性、性能和可维护性。遵循这些最佳实践能帮助你创建高质量的 API,提供更好的开发者体验。