- Published on
现代 Web API 设计完全指南
现代 Web API 设计完全指南
目录
简介
Web API 是现代应用程序的核心组件,它为前端应用、移动应用和第三方集成提供了统一的数据访问层。设计一个优秀的 API 不仅需要考虑功能实现,还需要注重可用性、可维护性和扩展性。本指南将详细介绍如何设计一个符合现代标准的 Web API。
核心设计原则
1. RESTful 架构
- 以资源为中心的设计
- 无状态通信
- 缓存支持
- 统一接口
- 分层系统
2. 一致性
- 命名约定保持一致
- 数据格式统一
- 错误处理标准化
- 响应结构保持一致
3. 版本控制
/api/v1/resources
/api/v2/resources
建议:
- 在 URL 中使用主版本号
- 使用 Header 处理次要版本更新
- 保持向后兼容性
- 提供版本升级指南
URL 设计
资源命名
✅ 好的设计:
GET /api/v1/users
GET /api/v1/user-groups
❌ 避免的设计:
GET /api/v1/getUsers
GET /api/v1/user_groups
资源关系
GET /api/v1/users/:id/posts # 获取用户的所有文章
GET /api/v1/users/:id/posts/:post_id # 获取用户的特定文章
查询参数规范
# 分页
GET /api/v1/users?page=1&per_page=20
# 排序
GET /api/v1/users?sort=created_at:desc
# 过滤
GET /api/v1/users?status=active&role=admin
# 字段选择
GET /api/v1/users?fields=id,username,email
HTTP 方法
标准用法
GET /users # 获取用户列表
GET /users/:id # 获取单个用户
POST /users # 创建用户
PUT /users/:id # 完整更新用户
PATCH /users/:id # 部分更新用户
DELETE /users/:id # 删除用户
状态码使用
- 200 OK:成功的 GET、PUT、PATCH 请求
- 201 Created:成功的 POST 请求
- 204 No Content:成功的 DELETE 请求
- 400 Bad Request:请求格式错误
- 401 Unauthorized:未提供认证信息
- 403 Forbidden:无权限访问
- 404 Not Found:资源不存在
- 409 Conflict:资源冲突
- 429 Too Many Requests:请求频率超限
- 500 Internal Server Error:服务器错误
请求与响应
请求格式
POST /api/v1/users
{
"username": "johndoe",
"email": "john@example.com",
"role": "user"
}
响应格式
{
"data": {
"id": "123",
"username": "johndoe",
"email": "john@example.com",
"role": "user",
"created_at": "2024-11-16T10:00:00Z"
},
"meta": {
"request_id": "req_abc123"
}
}
列表响应
{
"data": [...],
"meta": {
"total": 100,
"page": 1,
"per_page": 20,
"total_pages": 5
},
"links": {
"self": "/api/v1/users?page=1",
"next": "/api/v1/users?page=2",
"prev": null
}
}
错误处理
错误响应格式
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid email format",
"details": [
{
"field": "email",
"message": "Must be a valid email address"
}
],
"request_id": "req_abc123",
"timestamp": "2024-11-16T10:00:00Z"
}
}
错误码设计
enum ErrorCode {
VALIDATION_ERROR = 'VALIDATION_ERROR',
AUTHENTICATION_ERROR = 'AUTHENTICATION_ERROR',
AUTHORIZATION_ERROR = 'AUTHORIZATION_ERROR',
RESOURCE_NOT_FOUND = 'RESOURCE_NOT_FOUND',
RATE_LIMIT_EXCEEDED = 'RATE_LIMIT_EXCEEDED',
INTERNAL_SERVER_ERROR = 'INTERNAL_SERVER_ERROR'
}
安全性
认证
// JWT 认证示例
app.use((req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token) {
return res.status(401).json({
error: {
code: 'AUTHENTICATION_ERROR',
message: 'No token provided'
}
});
}
// 验证 token...
});
速率限制
import rateLimit from 'express-rate-limit';
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分钟
max: 100, // 限制100次请求
message: {
error: {
code: 'RATE_LIMIT_EXCEEDED',
message: 'Too many requests'
}
}
});
app.use('/api/', apiLimiter);
性能优化
缓存控制
// 缓存中间件示例
app.use((req, res, next) => {
if (req.method === 'GET') {
res.setHeader('Cache-Control', 'public, max-age=300'); // 5分钟缓存
res.setHeader('ETag', generateETag(req));
}
next();
});
压缩
import compression from 'compression';
app.use(compression({
filter: (req, res) => {
return req.headers['accept-encoding']?.includes('gzip');
}
}));
文档化
OpenAPI 规范示例
openapi: 3.0.0
info:
title: User API
version: 1.0.0
paths:
/users:
get:
summary: Get users list
parameters:
- name: page
in: query
schema:
type: integer
- name: per_page
in: query
schema:
type: integer
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/UsersList'
最佳实践示例
完整的用户 API 实现
import express from 'express';
import { validateRequest } from './middleware/validation';
import { authenticate } from './middleware/auth';
import { rateLimit } from './middleware/rate-limit';
const router = express.Router();
// 获取用户列表
router.get('/users',
authenticate,
rateLimit,
async (req, res) => {
const { page = 1, per_page = 20, sort, fields } = req.query;
try {
const users = await UserService.list({
page: Number(page),
perPage: Number(per_page),
sort,
fields: fields?.split(',')
});
res.json({
data: users.items,
meta: {
total: users.total,
page: users.page,
per_page: users.perPage,
total_pages: Math.ceil(users.total / users.perPage)
}
});
} catch (error) {
next(error);
}
}
);
// 创建用户
router.post('/users',
authenticate,
validateRequest(createUserSchema),
async (req, res) => {
try {
const user = await UserService.create(req.body);
res.status(201).json({
data: user
});
} catch (error) {
next(error);
}
}
);
// 错误处理中间件
router.use((error, req, res, next) => {
console.error(error);
res.status(getStatusCode(error)).json({
error: {
code: error.code || 'INTERNAL_SERVER_ERROR',
message: error.message,
details: error.details,
request_id: req.id,
timestamp: new Date().toISOString()
}
});
});
结语
设计优秀的 Web API 是一个持续改进的过程。遵循这些最佳实践可以帮助你构建出更易用、更可靠、更易维护的 API。记住:
- 保持简单性和一致性
- 注重安全性和性能
- 提供完善的文档
- 收集用户反馈并持续改进
希望本指南能够帮助你设计出更好的 API!