12.7.1 API 版本的规则——API 版本策略:URL/Header 版本控制
一句话破题
API 版本控制有三种主流方式:URL 路径、Query 参数、请求头——选择哪种取决于你的场景和团队偏好。
版本控制方式对比
| 方式 | 示例 | 优点 | 缺点 |
|---|---|---|---|
| URL 路径 | /api/v1/users | 直观、易缓存 | URL 变化大 |
| Query 参数 | /api/users?version=1 | 灵活 | 容易被忽略 |
| 请求头 | Accept: application/vnd.api+json;version=1 | URL 干净 | 不直观 |
URL 路径版本控制
最常见的方式,推荐用于大多数场景:
typescript
// app/api/v1/users/route.ts
export async function GET() {
return Response.json({ version: 'v1', users: [] });
}
// app/api/v2/users/route.ts
export async function GET() {
return Response.json({
version: 'v2',
data: { users: [] }, // v2 改变了响应结构
meta: { total: 0 },
});
}请求头版本控制
适合不想改变 URL 的场景:
typescript
// app/api/users/route.ts
export async function GET(req: Request) {
const version = req.headers.get('X-API-Version') || '1';
switch (version) {
case '1':
return Response.json({ users: [] });
case '2':
return Response.json({ data: { users: [] }, meta: {} });
default:
return Response.json({ error: '不支持的版本' }, { status: 400 });
}
}语义化版本
遵循 SemVer 规范:
主版本.次版本.修订号
^ ^ ^
| | +--- 向后兼容的问题修复
| +---------- 向后兼容的新功能
+----------------- 破坏性变更typescript
// 版本比较工具
interface Version {
major: number;
minor: number;
patch: number;
}
function parseVersion(version: string): Version {
const [major, minor, patch] = version.split('.').map(Number);
return { major, minor, patch };
}
function isCompatible(required: string, current: string): boolean {
const req = parseVersion(required);
const cur = parseVersion(current);
// 主版本必须匹配
if (req.major !== cur.major) return false;
// 当前版本必须 >= 要求版本
if (cur.minor < req.minor) return false;
if (cur.minor === req.minor && cur.patch < req.patch) return false;
return true;
}Next.js 中的多版本 API
typescript
// lib/api-versions.ts
type Handler = (req: Request) => Promise<Response>;
const handlers: Record<string, Record<string, Handler>> = {
'v1': {
'GET /users': async () => Response.json({ users: [] }),
},
'v2': {
'GET /users': async () => Response.json({ data: { users: [] } }),
},
};
export function createVersionedHandler(path: string) {
return async (req: Request) => {
const version = req.headers.get('X-API-Version') || 'v2'; // 默认最新版本
const method = req.method;
const key = `${method} ${path}`;
const handler = handlers[version]?.[key];
if (!handler) {
return Response.json({ error: '端点不存在' }, { status: 404 });
}
return handler(req);
};
}AI 协作指南
- 核心意图:让 AI 帮你设计 API 版本策略。
- 需求定义公式:
"请帮我设计一个 Next.js API 的版本控制方案,支持 URL 路径版本和请求头版本两种方式。" - 关键术语:
API 版本控制、SemVer、向后兼容、破坏性变更
避坑指南
- 从 v1 开始:不要用 v0,它暗示不稳定。
- 文档要跟上:每个版本都需要独立的文档。
- 设置默认版本:未指定版本时使用稳定版本(不一定是最新版)。
