新建API模块标准指南 - Quark API
概述
本文档提供在现有 Quark API 项目中新建 API 服务的标准化流程和最佳实践。适用于项目维护者或 AI 助手参考,确保新模块的一致性、可维护性和部署友好性。
核心原则
- 单一函数原则:每个 API 模块应尽量聚合到单个 Serverless Function 中
- 配置驱动:路由和功能通过统一配置管理
- 一致性:保持与现有 API 相同的响应格式和错误处理
- 资源优化:必须考虑 Vercel 免费计划限制(12个函数,已用4个)
项目结构标准
quark-api/
├── api/ # API 路由入口
│ ├── {module-name}/ # 新模块目录
│ │ └── index.js # 聚合入口(唯一必需文件)
│ ├── index.js # 主API入口(需更新)
│ └── health.js # 健康检查(保持不变)
├── lib/ # 业务逻辑
│ └── {module}-manager.js # 新模块管理器
├── data/ # 数据文件(可选)
│ └── {module}/ # 模块专属数据
├── public/ # 静态资源及 API 文档
└── vercel.json # 部署配置
新建API模块完整流程
步骤1:确定模块需求
- 明确API功能范围和数据源
- 设计端点结构和参数
- 预估数据量和访问频率
步骤2:创建管理器模块 (lib/)
// lib/{module}-manager.js 模板
class ModuleManager {
constructor() {
// 初始化配置、缓存等
this.cache = new Map();
this.cacheTTL = 5 * 60 * 1000; // 5分钟缓存
}
// 核心数据获取方法
async getData(id, options = {}) {
// 实现业务逻辑
}
// 数据验证和清理
sanitizeData(data, options = {}) {
// 数据清理逻辑
}
// 缓存管理
async getWithCache(key, fetchFunction) {
const cached = this.cache.get(key);
if (cached && (Date.now() - cached.timestamp) < this.cacheTTL) {
return cached.data;
}
const data = await fetchFunction();
this.cache.set(key, { data, timestamp: Date.now() });
return data;
}
}
module.exports = new ModuleManager();
步骤3:创建聚合API入口 (api/{module}/index.js)
// api/{module-name}/index.js 模板
const moduleManager = require('../../lib/{module}-manager');
module.exports = async function handler(req, res) {
// 1. 基础响应头设置
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
// 2. 处理预检请求
if (req.method === 'OPTIONS') {
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
return res.status(200).end();
}
// 3. 方法限制
if (req.method !== 'GET') {
res.setHeader('Content-Type', 'application/json');
return res.status(405).json({
success: false,
error: 'Method Not Allowed'
});
}
// 4. 解析URL路径
const url = new URL(req.url, `http://${req.headers.host}`);
const pathSegments = url.pathname.split('/').filter(Boolean);
const endpointIndex = pathSegments.indexOf('{module-name}') + 1;
const endpoint = endpointIndex < pathSegments.length ? pathSegments[endpointIndex] : '';
try {
// 5. 路由分发
switch (endpoint) {
case 'random':
await handleRandom(req, res, url.searchParams);
break;
case 'search':
await handleSearch(req, res, url.searchParams);
break;
// 添加更多端点...
default:
// 检查是否是ID格式或使用主入口
if (endpoint && /^{id-pattern}$/.test(endpoint)) {
await handleById(req, res, endpoint, url.searchParams);
} else {
await handleMain(req, res, url.searchParams);
}
}
} catch (error) {
// 6. 统一错误处理
handleError(res, error);
}
};
// 7. 各端点处理函数
async function handleMain(req, res, params) {
res.setHeader('Content-Type', 'application/json');
res.setHeader('Cache-Control', 'public, max-age=3600');
try {
const data = await moduleManager.getMainData();
res.status(200).json({
success: true,
api: {
name: "{API名称}",
version: "1.0.0",
base_url: `https://quark-api.130923.xyz/api/{module-name}`
},
data: data,
endpoints: {
// 列出所有可用端点
},
meta: {
timestamp: new Date().toISOString()
}
});
} catch (error) {
handleError(res, error);
}
}
// 8. 错误处理函数
function handleError(res, error) {
console.error('API Error:', error);
res.setHeader('Content-Type', 'application/json');
const statusCode = error.message.includes('not found') ? 404 :
error.message.includes('Invalid') ? 400 : 500;
res.status(statusCode).json({
success: false,
error: error.message,
meta: { timestamp: new Date().toISOString() }
});
}
步骤4:更新主API入口 (api/index.js)
// 在原有 endpoints 对象中添加新模块
const response = {
// ... 原有内容
endpoints: {
// ... 原有端点
"{module-name}": {
base: "/api/{module-name}",
description: "{模块描述}",
endpoints: {
list: "GET /api/{module-name}",
random: "GET /api/{module-name}/random",
// 其他端点...
}
}
}
};
步骤5:更新配置部署 (vercel.json)
应当在"rewrites"中添加:
{
"source": "/api/{module-name}/:path*",
"destination": "/api/{module-name}"
}
步骤6:创建 API 文档 (api/{module}/README.md)
# 模块中文名 {module} API - Quark API 文档
## 概述
## 统一响应结构
## 认证与速率限制
## 核心概念
## 端点索引
## 端点详情
## 错误代码参考
## 客户端使用示例
## 最佳实践
并应当复制到quarkdoc项目中/docs/QuarkAPI/{module-name} API.md
关键注意事项
1. 路由设计最佳实践
- 扁平化结构:尽量使用查询参数而非深层路径
- 语义化端点:
/api/module/action而非/api/module/doSomething - ID格式统一:使用
{resource}-{id}格式,如item-42
2. 参数处理规范
// 参数解析示例
function parseParams(params) {
return {
id: params.get('id'),
limit: Math.min(parseInt(params.get('limit')) || 10, 50),
page: Math.max(parseInt(params.get('page')) || 1, 1),
// 布尔值参数
includeDetails: params.get('include_details') === 'true'
};
}
3. 响应格式标准
{
"success": true,
"data": { /* 核心数据 */ },
"meta": {
"timestamp": "ISO时间戳",
"request_id": "唯一请求ID",
"pagination": { /* 分页信息 */ }
}
}
4. 错误处理标准
- 400:参数错误
- 404:资源不存在
- 429:请求过多(如需限流)
- 500:服务器内部错误
5. 性能优化要点
- 缓存策略:适当使用内存缓存减少重复计算
- 分页支持:大数据集必须支持分页
- CDN集成:静态资源使用CDN加速
- 压缩响应:Vercel自动处理
常见问题解决
Q1: 路由返回404
- 检查
vercel.json的rewrites配置 - 确认文件路径和命名正确
- 查看部署日志确认函数构建成功
Q2: Vercel函数数量超限
- 聚合相关功能到单个文件中
- 删除未使用的函数文件
- 使用
vercel ls查看当前函数数量
Q3: CORS问题
- 确保响应头包含
Access-Control-Allow-Origin: * - 正确处理 OPTIONS 预检请求
- 检查
vercel.json中的 headers 配置
Q4: 环境变量使用
// 在Vercel项目设置中配置环境变量
const apiKey = process.env.API_KEY;
const isProd = process.env.NODE_ENV === 'production';
测试清单
- [ ] 本地运行
npm start测试基本功能 - [ ] 测试所有端点的成功和错误情况
- [ ] 验证响应格式符合标准
- [ ] 检查CORS头正确设置
- [ ] 确认缓存头合理设置
- [ ] 部署到Vercel测试环境
- [ ] 更新主API入口的文档
- [ ] 创建独立的API文档页面
快速启动模板
可在项目根目录创建 templates/ 目录,存放以下模板文件:
module-manager-template.js- 管理器模板api-index-template.js- API入口模板docs-template.html- 文档模板
使用时复制模板并替换 {placeholders} 即可快速创建新模块。