123 lines
2.8 KiB
JavaScript
123 lines
2.8 KiB
JavaScript
/**
|
|
* 路由辅助工具
|
|
* 用于简化 HTTP 路由处理
|
|
*/
|
|
|
|
import { URL } from 'url';
|
|
|
|
/**
|
|
* JSON 响应辅助函数
|
|
*/
|
|
export function jsonResponse(res, data, status = 200, origin = '*') {
|
|
const headers = {
|
|
'Content-Type': 'application/json',
|
|
'Access-Control-Allow-Origin': origin,
|
|
'Access-Control-Allow-Methods': 'GET, HEAD, POST, PUT, DELETE, OPTIONS',
|
|
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
|
};
|
|
|
|
res.writeHead(status, headers);
|
|
res.end(JSON.stringify(data));
|
|
}
|
|
|
|
/**
|
|
* 读取请求体
|
|
*/
|
|
export async function readBody(req) {
|
|
return new Promise((resolve, reject) => {
|
|
const chunks = [];
|
|
req.on('data', chunk => chunks.push(chunk));
|
|
req.on('end', () => resolve(Buffer.concat(chunks)));
|
|
req.on('error', reject);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 解析 JSON 请求体
|
|
*/
|
|
export async function readJsonBody(req) {
|
|
const body = await readBody(req);
|
|
if (body.length === 0) return {};
|
|
try {
|
|
return JSON.parse(body.toString());
|
|
} catch {
|
|
throw new Error('Invalid JSON');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 解析 URL 路径参数
|
|
* @param {string} pathname - 请求路径
|
|
* @param {string} pattern - 路由模式,如 '/api/documents/:id'
|
|
* @returns {Object|null} 解析出的参数或 null
|
|
*/
|
|
export function parsePathParams(pathname, pattern) {
|
|
const patternParts = pattern.split('/');
|
|
const pathnameParts = pathname.split('/');
|
|
|
|
if (patternParts.length !== pathnameParts.length) {
|
|
return null;
|
|
}
|
|
|
|
const params = {};
|
|
for (let i = 0; i < patternParts.length; i++) {
|
|
if (patternParts[i].startsWith(':')) {
|
|
params[patternParts[i].slice(1)] = pathnameParts[i];
|
|
} else if (patternParts[i] !== pathnameParts[i]) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
return params;
|
|
}
|
|
|
|
/**
|
|
* 检查路径是否匹配
|
|
* @param {string} pathname - 请求路径
|
|
* @param {string} prefix - 路径前缀
|
|
* @returns {boolean}
|
|
*/
|
|
export function pathStartsWith(pathname, prefix) {
|
|
return pathname.startsWith(prefix);
|
|
}
|
|
|
|
/**
|
|
* 获取路径剩余部分
|
|
* @param {string} pathname - 请求路径
|
|
* @param {string} prefix - 路径前缀
|
|
* @returns {string}
|
|
*/
|
|
export function getPathRemainder(pathname, prefix) {
|
|
return pathname.slice(prefix.length);
|
|
}
|
|
|
|
/**
|
|
* 解析查询参数
|
|
* @param {string} searchParams - URL 查询字符串
|
|
* @returns {Object}
|
|
*/
|
|
export function parseQuery(searchParams) {
|
|
const params = new URLSearchParams(searchParams);
|
|
const result = {};
|
|
for (const [key, value] of params) {
|
|
result[key] = value;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* 验证 UUID 格式
|
|
*/
|
|
export function isValidUUID(id) {
|
|
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id);
|
|
}
|
|
|
|
/**
|
|
* 生成 UUID
|
|
*/
|
|
export function generateUUID() {
|
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
|
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
|
|
return v.toString(16);
|
|
});
|
|
} |