import { match } from 'path-to-regexp'; import compose from 'koa-compose'; import RouteAuth from './router/RouteAuth.js'; class Router { /** * 初始化路由实例 * @param {Object} options - 路由配置 * @param {string} options.prefix - 全局路由前缀 * @param {Object} options.auth - 全局默认auth配置(可选,优先级低于路由级) */ constructor(options = {}) { this.routes = { get: [], post: [], put: [], delete: [] }; this.middlewares = []; this.options = Object.assign({}, this.options, options); } options = { prefix: '', auth: true, } /** * 注册中间件 * @param {Function} middleware - 中间件函数 */ use(middleware) { this.middlewares.push(middleware); } /** * 注册GET路由,支持中间件链 * @param {string} path - 路由路径 * @param {Function} handler - 中间件和处理函数 * @param {Object} others - 其他参数(可选) */ get(path, handler, others) { this._registerRoute("get", path, handler, others) } /** * 注册POST路由,支持中间件链 * @param {string} path - 路由路径 * @param {Function} handler - 中间件和处理函数 * @param {Object} others - 其他参数(可选) */ post(path, handler, others) { this._registerRoute("post", path, handler, others) } /** * 注册PUT路由,支持中间件链 */ put(path, handler, others) { this._registerRoute("put", path, handler, others) } /** * 注册DELETE路由,支持中间件链 */ delete(path, handler, others) { this._registerRoute("delete", path, handler, others) } /** * 创建路由组 * @param {string} prefix - 组内路由前缀 * @param {Function} callback - 组路由注册回调 */ group(prefix, callback) { const groupRouter = new Router({ prefix: this.options.prefix + prefix }) callback(groupRouter); // 合并组路由到当前路由 Object.keys(groupRouter.routes).forEach(method => { this.routes[method].push(...groupRouter.routes[method]); }); this.middlewares.push(...groupRouter.middlewares); } /** * 生成Koa中间件 * @returns {Function} Koa中间件函数 */ middleware() { return async (ctx, next) => { const { method, path } = ctx; const route = this._matchRoute(method.toLowerCase(), path); // 组合全局中间件、路由专属中间件和 handler const middlewares = [...this.middlewares]; if (route) { // 如果匹配到路由,添加路由专属中间件和处理函数 ctx.params = route.params; let isAuth = this.options.auth; if (route.meta && route.meta.auth !== undefined) { isAuth = route.meta.auth; } middlewares.push(RouteAuth({ auth: isAuth })); middlewares.push(route.handler) // 用 koa-compose 组合 const composed = compose(middlewares); await composed(ctx, next); } else { // 如果没有匹配到路由,直接调用 next await next(); } }; } /** * 内部路由注册方法,支持中间件链 * @private */ _registerRoute(method, path, handler, others) { const fullPath = this.options.prefix + path const keys = []; const matcher = match(fullPath, { decode: decodeURIComponent }); this.routes[method].push({ path: fullPath, matcher, keys, handler, meta: others }) } /** * 匹配路由 * @private */ _matchRoute(method, currentPath) { const routes = this.routes[method] || []; for (const route of routes) { const matchResult = route.matcher(currentPath); if (matchResult) { return { ...route, params: matchResult.params }; } } return null; } } export default Router;