2026-02-21•ToolBox Team
REST API 设计与测试最佳实践
🔧 返回工具箱 | Back to Tools
浏览所有工具 | View All Toolsapirestbackenddesign-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
渐进式迁移策略
- 发布新版本:
/api/v2/与v1并存 - 文档更新:告知用户升级路线
- 弃用通知:在响应头添加警告
Deprecation: true Sunset: Sun, 27 Feb 2027 00:00:00 GMT - 版本下线: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 配置(如需要)
- 实现日志和监控
- 添加自动化测试覆盖
- 定义清晰的弃用和升级策略
相关工具推荐: