require("dotenv").config(); const Koa = require("koa"); const Router = require("koa-router"); const jwt = require("jsonwebtoken"); const koaJwt = require("koa-jwt"); const fs = require("fs"); const path = require("path"); const bodyParser = require("koa-bodyparser"); const verifyThirdPartyToken = require("./auth/verifyThirdPartyToken"); const app = new Koa(); app.use(bodyParser()); // 添加在路由中间件之前 const router = new Router(); // 自动加载API路由函数 const loadAPIRoutes = (baseDir = 'api', baseRoute = '/api') => { const scanDirectory = (dir, routePrefix) => { const entries = fs.readdirSync(dir, { withFileTypes: true }); entries.forEach(entry => { const fullPath = path.join(dir, entry.name); const relativePath = path.relative(baseDir, dir); // 构建路由路径:工程目录结构 -> URL路径 const routePath = path.join( routePrefix, relativePath, entry.name.replace(/\.js$/, '') ).replace(/\\/g, '/'); // Windows路径转URL路径 if (entry.isDirectory()) { scanDirectory(fullPath, routePrefix); // 递归扫描子目录 } else if ( entry.isFile() && path.extname(entry.name) === '.js' && entry.name !== 'index.js' ) { registerRoute(fullPath, routePath); } }); }; // 路由注册器(支持扩展其他HTTP方法) const registerRoute = (filePath, routePath) => { try { const handler = require(filePath); router.post(routePath, async ctx => await handler(ctx)); console.log(`[Route] POST ${routePath} -> ${filePath}`); } catch (err) { console.error(`[Error] Failed to load route ${routePath}:`, err); } }; // 初始化扫描 scanDirectory(path.join(__dirname, baseDir), baseRoute); }; // 公开路由 router.get("/public", (ctx) => { ctx.body = "Public content"; }); // 自定义中间件:解析并验证第三方Token app.use(async (ctx, next) => { const authHeader = ctx.headers.authorization; if (authHeader && authHeader.startsWith('Bearer ')) { const thirdPartyToken = authHeader.split(' ')[1]; try { // 这里假设第三方Token可以通过某种方式验证并转换为JWT Token const decoded = verifyThirdPartyToken(thirdPartyToken); // 假设有一个验证函数 const jwtToken = jwt.sign(decoded, process.env.JWT_SECRET, { expiresIn: "1h" }); ctx.state.user = decoded; // 将用户信息存储在ctx.state中 ctx.headers.authorization = `Bearer ${jwtToken}`; // 替换为JWT Token } catch (err) { ctx.throw(401, 'Invalid third-party token'); } } await next(); }); // JWT中间件(保护下方所有路由) app.use( koaJwt({ secret: process.env.JWT_SECRET, }).unless({ path: [/^\/public/, /^\/login/], }) ); // 加载自动生成的路由 loadAPIRoutes(); // 受保护路由 router.get("/protected", (ctx) => { ctx.body = `Protected content for ${ctx.state.user.username}`; }); app.use(router.routes()); app.use(router.allowedMethods()); app.listen(process.env.PORT || 3000, () => { console.log(`Server running on http://localhost:${process.env.PORT || 3000}`); });