接口开发
本页面详细介绍Magic-API接口开发的各个方面。
接口配置
基本配置
| 配置项 | 说明 |
|---|---|
| 接口名称 | 接口的显示名称 |
| 接口路径 | URL路径,如:/user/list |
| 请求方法 | GET/POST/PUT/DELETE |
| 分组 | 所属接口分组 |
高级配置
| 配置项 | 说明 |
|---|---|
| 接口描述 | 接口功能描述 |
| 请求Header | 必需的请求头 |
| 请求Body | 请求体格式说明 |
| 响应示例 | 响应数据示例 |
请求参数
路径参数
javascript
// 接口路径: /user/{id}
// 请求: GET /api/custom/user/123
var userId = path.id; // 123
return db.selectOne("SELECT * FROM eb_user WHERE id = ?", userId);Query参数
javascript
// 请求: GET /api/custom/users?page=1&limit=10&keyword=张三
var page = param.page || 1;
var limit = param.limit || 10;
var keyword = param.keyword;
var sql = "SELECT * FROM eb_user WHERE 1=1";
if (keyword) {
sql += " AND nickname LIKE '%${keyword}%'";
}
sql += " LIMIT ${limit} OFFSET ${(page-1)*limit}";
return db.select(sql);Body参数
javascript
// 请求: POST /api/custom/user
// Body: { "nickname": "张三", "phone": "13800138000" }
var nickname = body.nickname;
var phone = body.phone;
// 参数验证
if (!nickname) {
exit 400, "昵称不能为空";
}
return {
nickname: nickname,
phone: phone
};Header参数
javascript
// 获取请求头
var token = header.Authorization;
var contentType = header['Content-Type'];
var customHeader = header['X-Custom-Header'];响应处理
标准响应
javascript
// 自动包装为标准格式
return {
list: [],
total: 0
};
// 响应结果:
// { "code": 200, "message": "success", "data": { "list": [], "total": 0 } }自定义响应码
javascript
// 方式1:使用exit
exit 400, "参数错误";
// 方式2:返回完整结构
return response.json({
code: 400,
message: "参数错误",
data: null
});设置响应头
javascript
response.setHeader('X-Custom-Header', 'value');
response.setHeader('Cache-Control', 'no-cache');
return data;文件下载
javascript
// 设置下载头
response.setHeader('Content-Type', 'application/octet-stream');
response.setHeader('Content-Disposition', 'attachment; filename="export.csv"');
// 返回文件内容
return fileContent;参数验证
基础验证
javascript
import assert from '@/utils/assert';
// 非空验证
assert.notNull(body.username, "用户名不能为空");
assert.notNull(body.password, "密码不能为空");
// 长度验证
assert.isTrue(body.username.length >= 3, "用户名至少3个字符");
// 格式验证
var phonePattern = /^1[3-9]\d{9}$/;
assert.isTrue(phonePattern.test(body.phone), "手机号格式不正确");自定义验证
javascript
// 验证函数
function validate(data) {
var errors = [];
if (!data.name) {
errors.push("名称不能为空");
}
if (data.price && data.price < 0) {
errors.push("价格不能为负数");
}
return errors;
}
var errors = validate(body);
if (errors.length > 0) {
exit 400, errors.join(", ");
}业务逻辑
条件判断
javascript
var userType = param.type;
if (userType == 'vip') {
return db.select("SELECT * FROM eb_user WHERE level > 0");
} else if (userType == 'new') {
return db.select("SELECT * FROM eb_user WHERE create_time > DATE_SUB(NOW(), INTERVAL 7 DAY)");
} else {
return db.select("SELECT * FROM eb_user LIMIT 100");
}循环处理
javascript
var orders = db.select("SELECT * FROM eb_store_order WHERE status = 1");
var result = [];
for (order in orders) {
// 获取订单商品
var items = db.select("SELECT * FROM eb_store_order_info WHERE order_id = ?", order.id);
result.push({
orderId: order.id,
orderNo: order.order_id,
items: items
});
}
return result;数据转换
javascript
var users = db.select("SELECT * FROM eb_user LIMIT 10");
// 数据脱敏
return users.map(user => ({
id: user.id,
nickname: user.nickname,
phone: user.phone ? user.phone.substring(0, 3) + "****" + user.phone.substring(7) : null,
createTime: user.create_time
}));异常处理
try-catch
javascript
try {
var result = http.get('https://api.example.com/data', {
timeout: 5000
});
return result.data;
} catch (e) {
log.error("请求失败: {}", e.message);
exit 500, "获取数据失败";
}业务异常
javascript
var user = db.selectOne("SELECT * FROM eb_user WHERE id = ?", param.id);
if (!user) {
exit 404, "用户不存在";
}
if (user.status == 0) {
exit 403, "用户已被禁用";
}
return user;接口安全
Token验证
javascript
var token = header.Authorization;
if (!token) {
exit 401, "请先登录";
}
// 验证Token
var userInfo = redis.get("token:" + token);
if (!userInfo) {
exit 401, "登录已过期";
}
// 将用户信息存入上下文
var user = JSON.parse(userInfo);权限验证
javascript
var user = getCurrentUser(); // 获取当前用户
// 验证权限
if (user.role != 'admin') {
exit 403, "无权访问";
}签名验证
javascript
import md5 from 'md5';
var sign = header.sign;
var timestamp = header.timestamp;
var secret = env.get('API_SECRET');
// 验证时间戳(5分钟有效)
if (Math.abs(Date.now() / 1000 - timestamp) > 300) {
exit 401, "请求已过期";
}
// 验证签名
var expectedSign = md5(JSON.stringify(body) + timestamp + secret);
if (sign != expectedSign) {
exit 401, "签名验证失败";
}