You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
3.7 KiB
139 lines
3.7 KiB
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;
|