Back to Blog
2026-02-21ToolBox Team

REST API 设计与测试最佳实践

🔧 返回工具箱 | Back to Tools

浏览所有工具 | View All Tools
apirestbackenddesign-patterns

REST API 设计与测试最佳实践

REST(Representational State Transfer)已成为现代 Web 服务的事实标准。从 Google Maps API 到 Stripe 支付 API,几乎所有主流平台都遵循 REST 设计原则。掌握 REST API 的设计和测试,是后端工程师的必备技能。

1. REST API 核心原则

资源中心设计

REST 的核心思想是一切皆资源。不是"动作",而是"资源"。

// ❌ 不符合 REST 的设计(RPC 风格)
GET /api/getUserById?id=123
GET /api/createNewUser
GET /api/deleteUserByUserId?id=123

// ✅ 符合 REST 的设计(资源中心)
GET /api/users/123          // 获取用户 123
POST /api/users             // 创建新用户
DELETE /api/users/123       // 删除用户 123

HTTP 方法的正确用法

方法 含义 幂等性 缓存
GET 获取资源 ✅ 是 ✅ 是
POST 创建资源 ❌ 否 ❌ 否
PUT 整体更新资源 ✅ 是 ❌ 否
PATCH 部分更新资源 ❌ 否 ❌ 否
DELETE 删除资源 ✅ 是 ❌ 否
HEAD 同 GET,但不返回响应体 ✅ 是 ✅ 是

幂等性:多次调用与单次调用结果相同。GET、PUT、DELETE 都是幂等的;POST 和 PATCH 不是。

// GET - 幂等且安全(不改变服务器状态)
GET /api/users/123

// POST - 非幂等(多次调用创建多条记录)
POST /api/users
{ "name": "Alice", "email": "alice@example.com" }  // 调用 3 次创建 3 个用户

// PUT - 幂等(替换整个资源)
PUT /api/users/123
{ "id": 123, "name": "Bob", "email": "bob@example.com" }  // 多次调用结果相同

// PATCH - 非幂等(部分更新可能产生不同结果)
PATCH /api/users/123
{ "name": "Charlie" }  // 如果有条件逻辑,多次调用可能不同

2. API 设计规范

URL 命名规范

// ✅ 好的实践
GET    /api/v1/users                    // 获取所有用户
GET    /api/v1/users/123                // 获取特定用户
POST   /api/v1/users                    // 创建用户
PUT    /api/v1/users/123                // 更新用户
DELETE /api/v1/users/123                // 删除用户

// 嵌套资源
GET    /api/v1/users/123/posts          // 获取用户 123 的所有帖子
GET    /api/v1/users/123/posts/456      // 获取用户 123 的帖子 456
POST   /api/v1/users/123/posts          // 创建新帖子

最佳实践:

  • 使用复数形式/users 而非 /user
  • 包含版本号/api/v1/ 便于向后兼容
  • 使用小写字母:URL 区分大小写
  • 不使用文件扩展名:使用 Content-Type 头表示格式

查询参数

// 分页
GET /api/v1/users?page=1&limit=10

// 排序
GET /api/v1/users?sort=name&order=asc

// 过滤
GET /api/v1/users?role=admin&status=active

// 搜索
GET /api/v1/users?search=alice

3. 响应格式设计

成功响应

// 单个资源
{
  "code": 200,
  "message": "Success",
  "data": {
    "id": 123,
    "name": "Alice",
    "email": "alice@example.com",
    "createdAt": "2026-02-27T10:00:00Z"
  }
}

// 列表响应(含分页)
{
  "code": 200,
  "message": "Success",
  "data": [
    { "id": 1, "name": "Alice" },
    { "id": 2, "name": "Bob" }
  ],
  "pagination": {
    "page": 1,
    "limit": 10,
    "total": 2,
    "pages": 1
  }
}

错误响应

// 404 Not Found
{
  "code": 404,
  "message": "User not found",
  "error": "RESOURCE_NOT_FOUND",
  "details": "User with id 999 does not exist"
}

// 422 Unprocessable Entity(验证错误)
{
  "code": 422,
  "message": "Validation failed",
  "error": "VALIDATION_ERROR",
  "details": {
    "email": "Invalid email format",
    "age": "Must be between 18 and 120"
  }
}

// 500 Internal Server Error
{
  "code": 500,
  "message": "Internal Server Error",
  "error": "INTERNAL_ERROR",
  "requestId": "req_12345abcde"  // 便于日志追踪
}

4. 版本管理

URL 版本管理(推荐)

GET /api/v1/users           // 旧版本 API
GET /api/v2/users           // 新版本 API

优势:清晰、便于浏览器直接访问

请求头版本管理

GET /api/users
Accept: application/vnd.company.v2+json

渐进式迁移策略

  1. 发布新版本/api/v2/v1 并存
  2. 文档更新:告知用户升级路线
  3. 弃用通知:在响应头添加警告
    Deprecation: true
    Sunset: Sun, 27 Feb 2027 00:00:00 GMT
    
  4. 版本下线:6-12 个月后关闭旧版本

5. 安全性

认证与授权

// JWT 认证
GET /api/v1/users
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

// API Key
GET /api/v1/users
X-API-Key: sk_live_12345abcde

// OAuth 2.0(第三方应用)
GET /api/v1/users
Authorization: Bearer <access_token>

Rate Limiting

防止 API 被滥用或 DDoS 攻击:

// Nginx 配置
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

server {
  location /api/v1/ {
    limit_req zone=api_limit burst=20;
  }
}

// 响应头表示限制信息
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1645000000

6. 错误处理

标准 HTTP 状态码

状态码 含义 示例
200 OK 请求成功
201 Created 资源创建成功
204 No Content 成功但无返回内容
400 Bad Request 请求参数错误
401 Unauthorized 未认证
403 Forbidden 已认证但无权限
404 Not Found 资源不存在
409 Conflict 资源冲突(如重复创建)
422 Unprocessable Entity 参数验证失败
429 Too Many Requests 请求过于频繁
500 Internal Server Error 服务器错误

Express 中的错误处理

// 中间件验证
const validateUser = (req, res, next) => {
  const { name, email } = req.body;
  
  if (!name || !email) {
    return res.status(400).json({
      code: 400,
      message: 'Validation failed',
      details: {
        name: name ? undefined : 'Required',
        email: email ? undefined : 'Required'
      }
    });
  }
  
  next();
};

// 路由处理
app.post('/api/v1/users', validateUser, async (req, res, next) => {
  try {
    const user = await User.create(req.body);
    res.status(201).json({
      code: 201,
      message: 'User created successfully',
      data: user
    });
  } catch (error) {
    // 统一错误处理
    next(error);
  }
});

// 错误处理中间件
app.use((error, req, res, next) => {
  console.error('Error:', error);
  
  res.status(error.status || 500).json({
    code: error.status || 500,
    message: error.message || 'Internal Server Error',
    error: error.code || 'INTERNAL_ERROR'
  });
});

7. API 测试

使用 Postman / API Tester

我们的 API 测试工具 可以在线测试 API 端点,无需安装桌面应用。

自动化测试(Jest)

describe('User API', () => {
  test('GET /api/v1/users 返回用户列表', async () => {
    const response = await request(app)
      .get('/api/v1/users')
      .expect(200);
    
    expect(response.body.code).toBe(200);
    expect(Array.isArray(response.body.data)).toBe(true);
  });

  test('POST /api/v1/users 创建新用户', async () => {
    const response = await request(app)
      .post('/api/v1/users')
      .send({
        name: 'Alice',
        email: 'alice@example.com'
      })
      .expect(201);
    
    expect(response.body.data.id).toBeDefined();
    expect(response.body.data.name).toBe('Alice');
  });

  test('GET /api/v1/users/999 返回 404', async () => {
    await request(app)
      .get('/api/v1/users/999')
      .expect(404);
  });
});

8. 文档化

使用 OpenAPI(Swagger)标准:

openapi: 3.0.0
info:
  title: User API
  version: 1.0.0

paths:
  /api/v1/users:
    get:
      summary: 获取所有用户
      parameters:
        - name: page
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: 成功返回用户列表
    post:
      summary: 创建新用户
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [name, email]
              properties:
                name:
                  type: string
                email:
                  type: string

API 设计清单

在部署到生产前检查:

  • 使用正确的 HTTP 方法和状态码
  • 响应格式一致(统一的错误响应结构)
  • 包含 API 版本号
  • 实现速率限制
  • 添加完整的认证和授权
  • 提供清晰的文档和错误信息
  • 包含 CORS 配置(如需要)
  • 实现日志和监控
  • 添加自动化测试覆盖
  • 定义清晰的弃用和升级策略

相关工具推荐