From ea8a70c43d2ec6bd1ed72de940291f852411b788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=A2=E4=BA=9A=E6=98=95?= <1549469775@qq.com> Date: Fri, 20 Jun 2025 14:27:02 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=87=8D=E6=9E=84=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E5=99=A8=EF=BC=8C=E6=B7=BB=E5=8A=A0=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=B3=A8=E5=86=8C=E8=B7=AF=E7=94=B1=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E6=9B=B4=E6=96=B0=E4=B8=AD=E9=97=B4=E4=BB=B6=E8=B7=AF?= =?UTF-8?q?=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/AuthController.js | 44 ++++++++++++++++++++++++ src/controllers/userController.js | 44 ------------------------ src/middlewares/install.js | 9 ++--- src/utils/ForRegister.js | 70 +++++++++++++++++++++++++++++++++++++++ src/utils/autoRegister.js | 70 --------------------------------------- src/utils/router.js | 23 +++++++------ 6 files changed, 128 insertions(+), 132 deletions(-) create mode 100644 src/controllers/AuthController.js delete mode 100644 src/controllers/userController.js create mode 100644 src/utils/ForRegister.js delete mode 100644 src/utils/autoRegister.js diff --git a/src/controllers/AuthController.js b/src/controllers/AuthController.js new file mode 100644 index 0000000..ca0605c --- /dev/null +++ b/src/controllers/AuthController.js @@ -0,0 +1,44 @@ +import UserService from "services/UserService.js" +import { formatResponse } from "utils/helper.js" + +const userService = new UserService() + +export const hello = async (ctx) => { + ctx.body = formatResponse(true, "Hello World") +} + +export const getUser = async (ctx) => { + const user = await userService.getUserById(ctx.params.id) + ctx.body = formatResponse(true, user) +} + +export const register = async (ctx) => { + try { + const { username, email, password } = ctx.request.body + const user = await userService.register({ username, email, password }) + ctx.body = formatResponse(true, user) + } catch (err) { + ctx.body = formatResponse(false, null, err.message) + } +} + +export const login = async (ctx) => { + try { + const { username, email, password } = ctx.request.body + const result = await userService.login({ username, email, password }) + ctx.body = formatResponse(true, result) + } catch (err) { + ctx.body = formatResponse(false, null, err.message) + } +} + +// 路由注册示例 +import Router from "utils/router.js" +export function createRoutes() { + const router = new Router({ prefix: "/api" }) + router.get("/hello", hello, { auth: false }) + router.get("/user/:id", getUser) + router.post("/register", register) + router.post("/login", login) + return router +} diff --git a/src/controllers/userController.js b/src/controllers/userController.js deleted file mode 100644 index b00549d..0000000 --- a/src/controllers/userController.js +++ /dev/null @@ -1,44 +0,0 @@ -import UserService from "services/UserService.js" -import { formatResponse } from "utils/helper.js" - -const userService = new UserService() - -export const hello = async (ctx) => { - ctx.body = formatResponse(true, "Hello World") -} - -export const getUser = async (ctx) => { - const user = await userService.getUserById(ctx.params.id) - ctx.body = formatResponse(true, user) -} - -export const register = async (ctx) => { - try { - const { username, email, password } = ctx.request.body - const user = await userService.register({ username, email, password }) - ctx.body = formatResponse(true, user) - } catch (err) { - ctx.body = formatResponse(false, null, err.message) - } -} - -export const login = async (ctx) => { - try { - const { username, email, password } = ctx.request.body - const result = await userService.login({ username, email, password }) - ctx.body = formatResponse(true, result) - } catch (err) { - ctx.body = formatResponse(false, null, err.message) - } -} - -// 路由注册示例 -import Router from "utils/router.js" -export function createRoutes() { - const router = new Router({ prefix: "/api" }) - router.get("/hello", hello) - router.get("/user/:id", getUser) - router.post("/register", register) - router.post("/login", login) - return router -} diff --git a/src/middlewares/install.js b/src/middlewares/install.js index 69ca2d6..f337e8e 100644 --- a/src/middlewares/install.js +++ b/src/middlewares/install.js @@ -7,7 +7,7 @@ import ErrorHandler from "./ErrorHandler" import { auth } from "./Auth" import bodyParser from "koa-bodyparser" import Views from "./Views" -import { autoRegisterControllers } from "utils/autoRegister.js" +import { autoRegisterControllers } from "@/utils/ForRegister.js" const __dirname = path.dirname(fileURLToPath(import.meta.url)) const publicPath = resolve(__dirname, "../../public") @@ -18,12 +18,7 @@ export default app => { app.use( auth({ whiteList: [ - // // API接口访问 - // "/api/login", - // "/api/register", - // { pattern: "/api/v1/status", auth: "try" }, - // { pattern: "/api/**/*", auth: true }, - // // 静态资源访问 + // 所有请求放行 { pattern: "/", auth: false }, { pattern: "/**/*", auth: false }, ], diff --git a/src/utils/ForRegister.js b/src/utils/ForRegister.js new file mode 100644 index 0000000..ad0499f --- /dev/null +++ b/src/utils/ForRegister.js @@ -0,0 +1,70 @@ +// 自动扫描 controllers 目录并注册路由 +// 兼容传统 routes 方式和自动注册 controller 方式 +import fs from "fs" +import path from "path" + +/** + * 自动扫描 controllers 目录,注册所有导出的路由 + * 自动检测 routes 目录下已手动注册的 controller,避免重复注册 + * @param {Koa} app - Koa 实例 + * @param {string} controllersDir - controllers 目录路径 + * @param {string} prefix - 路由前缀 + * @param {Set} [manualControllers] - 可选,手动传入已注册 controller 文件名集合,优先于自动扫描 + */ +export function autoRegisterControllers(app, controllersDir = path.resolve(__dirname, "../controllers")) { + let allRouter = [] + async function scan(dir, routePrefix = "") { + for (const file of fs.readdirSync(dir)) { + const fullPath = path.join(dir, file) + const stat = fs.statSync(fullPath) + if (stat.isDirectory()) { + await scan(fullPath, routePrefix + "/" + file) + } else if (file.endsWith("Controller.js")) { + let controller + try { + controller = require(fullPath) + } catch (e) { + controller = (await import(fullPath)).default + } + const routes = controller.createRoutes || controller.default?.createRoutes || controller.default || controller + if (typeof routes === "function") { + allRouter.push(routes()) + } + } + } + } + + ;(async () => { + await scan(controllersDir) + // TODO: 存在问题:每个Controller都是有顺序的,如果其中一个Controller没有next方法,可能会导致后续的Controller无法执行 + allRouter.forEach(router => { + app.use(router.middleware()) + }) + // // 聚合中间件:只分发到匹配的router + // app.use(async (ctx, next) => { + // let matched = false + // for (const router of allRouter) { + // // router._matchRoute 只在 router.js 内部,需暴露或用 middleware 包一层 + // if (typeof router._matchRoute === "function") { + // const route = router._matchRoute(ctx.method.toLowerCase(), ctx.path) + // if (route) { + // matched = true + // await router.middleware()(ctx, next) + // break // 命中一个即停止 + // } + // } else { + // // fallback: 直接尝试middleware,若未命中会自动next + // const before = ctx.status + // await router.middleware()(ctx, next) + // if (ctx.status !== before) { + // matched = true + // break + // } + // } + // } + // if (!matched) { + // await next() + // } + // }) + })() +} diff --git a/src/utils/autoRegister.js b/src/utils/autoRegister.js deleted file mode 100644 index 9ddfd93..0000000 --- a/src/utils/autoRegister.js +++ /dev/null @@ -1,70 +0,0 @@ -// 自动扫描 controllers 目录并注册路由 -// 兼容传统 routes 方式和自动注册 controller 方式 -import fs from "fs" -import path from "path" - -/** - * 自动扫描 controllers 目录,注册所有导出的路由 - * 自动检测 routes 目录下已手动注册的 controller,避免重复注册 - * @param {Koa} app - Koa 实例 - * @param {string} controllersDir - controllers 目录路径 - * @param {string} prefix - 路由前缀 - * @param {Set} [manualControllers] - 可选,手动传入已注册 controller 文件名集合,优先于自动扫描 - */ -export function autoRegisterControllers(app, controllersDir = path.resolve(__dirname, "../controllers")) { - let allRouter = [] - async function scan(dir, routePrefix = "") { - for (const file of fs.readdirSync(dir)) { - const fullPath = path.join(dir, file) - const stat = fs.statSync(fullPath) - if (stat.isDirectory()) { - await scan(fullPath, routePrefix + "/" + file) - } else if (file.endsWith("Controller.js")) { - let controller - try { - controller = require(fullPath) - } catch (e) { - controller = (await import(fullPath)).default - } - const routes = controller.createRoutes || controller.default?.createRoutes || controller.default || controller - if (typeof routes === "function") { - allRouter.push(routes()) - } - } - } - } - - ;(async () => { - await scan(controllersDir) - // TODO: 存在问题:每个Controller都是有顺序的,如果其中一个Controller没有next方法,可能会导致后续的Controller无法执行 - // allRouter.forEach(router => { - // app.use(router.middleware()) - // }) - // 聚合中间件:只分发到匹配的router - app.use(async (ctx, next) => { - let matched = false - for (const router of allRouter) { - // router._matchRoute 只在 router.js 内部,需暴露或用 middleware 包一层 - if (typeof router._matchRoute === "function") { - const route = router._matchRoute(ctx.method.toLowerCase(), ctx.path) - if (route) { - matched = true - await router.middleware()(ctx, next) - break // 命中一个即停止 - } - } else { - // fallback: 直接尝试middleware,若未命中会自动next - const before = ctx.status - await router.middleware()(ctx, next) - if (ctx.status !== before) { - matched = true - break - } - } - } - if (!matched) { - await next() - } - }) - })() -} diff --git a/src/utils/router.js b/src/utils/router.js index 82f8b80..e6c5a06 100644 --- a/src/utils/router.js +++ b/src/utils/router.js @@ -32,9 +32,9 @@ class Router { * 注册GET路由,支持中间件链 * @param {string} path - 路由路径 * @param {Function} handler - 中间件和处理函数 - * @param {...Object} others - 其他参数(可选) + * @param {Object} others - 其他参数(可选) */ - get(path, handler, ...others) { + get(path, handler, others) { this._registerRoute("get", path, handler, others) } @@ -42,23 +42,23 @@ class Router { * 注册POST路由,支持中间件链 * @param {string} path - 路由路径 * @param {Function} handler - 中间件和处理函数 - * @param {...Object} others - 其他参数(可选) + * @param {Object} others - 其他参数(可选) */ - post(path, handler, ...others) { + post(path, handler, others) { this._registerRoute("post", path, handler, others) } /** * 注册PUT路由,支持中间件链 */ - put(path, handler, ...others) { + put(path, handler, others) { this._registerRoute("put", path, handler, others) } /** * 注册DELETE路由,支持中间件链 */ - delete(path, handler, ...others) { + delete(path, handler, others) { this._registerRoute("delete", path, handler, others) } @@ -89,6 +89,7 @@ class Router { // 组合全局中间件、路由专属中间件和 handler const middlewares = [...this.middlewares]; if (route) { + // 如果匹配到路由,添加路由专属中间件和处理函数 ctx.params = route.params; let isAuth = this.options.auth; @@ -98,13 +99,13 @@ class Router { middlewares.push(RouteAuth({ auth: isAuth })); middlewares.push(route.handler) + // 用 koa-compose 组合 + const composed = compose(middlewares); + await composed(ctx, next); } else { - middlewares.push(RouteAuth({ auth: this.options.auth })); + // 如果没有匹配到路由,直接调用 next + await next(); } - - // 用 koa-compose 组合 - const composed = compose(middlewares); - await composed(ctx, next); }; }