Koa 核心不包含路由功能,需要通过中间件实现。最常用的路由中间件是 @koa/router,它提供了强大的路由定义和管理功能。
安装路由中间件:
bashnpm install @koa/router
基本路由使用:
javascriptconst Koa = require('koa'); const Router = require('@koa/router'); const app = new Koa(); const router = new Router(); // 定义路由 router.get('/', async (ctx) => { ctx.body = 'Hello Koa'; }); router.get('/users/:id', async (ctx) => { const id = ctx.params.id; ctx.body = `User ${id}`; }); router.post('/users', async (ctx) => { const user = ctx.request.body; ctx.body = { success: true, user }; }); // 注册路由中间件 app.use(router.routes()); app.use(router.allowedMethods()); app.listen(3000);
路由参数:
- 路径参数:
javascriptrouter.get('/users/:id', async (ctx) => { const { id } = ctx.params; ctx.body = `User ID: ${id}`; }); // 多个参数 router.get('/posts/:postId/comments/:commentId', async (ctx) => { const { postId, commentId } = ctx.params; ctx.body = `Post: ${postId}, Comment: ${commentId}`; });
- 查询参数:
javascriptrouter.get('/search', async (ctx) => { const { keyword, page, limit } = ctx.query; ctx.body = { keyword, page, limit }; });
- 正则表达式路由:
javascriptrouter.get(/^\/users\/(\d+)$/, async (ctx) => { const id = ctx.params[0]; ctx.body = `User ID: ${id}`; });
路由方法:
javascriptrouter.get('/resource', handler); // GET router.post('/resource', handler); // POST router.put('/resource', handler); // PUT router.delete('/resource', handler); // DELETE router.patch('/resource', handler); // PATCH router.all('/resource', handler); // 所有方法
路由前缀:
javascriptconst apiRouter = new Router({ prefix: '/api/v1' }); apiRouter.get('/users', handler); // 实际路径: /api/v1/users apiRouter.post('/login', handler); // 实际路径: /api/v1/login app.use(apiRouter.routes());
路由嵌套:
javascriptconst userRouter = new Router({ prefix: '/users' }); userRouter.get('/', async (ctx) => { ctx.body = 'User list'; }); userRouter.get('/:id', async (ctx) => { ctx.body = `User ${ctx.params.id}`; }); const commentRouter = new Router({ prefix: '/:userId/comments' }); commentRouter.get('/', async (ctx) => { ctx.body = `Comments for user ${ctx.params.userId}`; }); userRouter.use(commentRouter.routes()); app.use(userRouter.routes());
路由中间件:
javascript// 单个路由中间件 router.get('/protected', authMiddleware, async (ctx) => { ctx.body = 'Protected content'; }); // 多个路由中间件 router.post('/admin', authMiddleware, adminMiddleware, async (ctx) => { ctx.body = 'Admin content'; } ); // 路由级中间件 router.use(async (ctx, next) => { console.log('Router middleware'); await next(); });
路由分组和模块化:
javascript// routes/users.js const Router = require('@koa/router'); const router = new Router({ prefix: '/users' }); router.get('/', async (ctx) => { ctx.body = 'User list'; }); router.get('/:id', async (ctx) => { ctx.body = `User ${ctx.params.id}`; }); module.exports = router; // app.js const userRoutes = require('./routes/users'); app.use(userRoutes.routes()); app.use(userRoutes.allowedMethods());
路由命名和重定向:
javascriptrouter.get('user', '/users/:id', async (ctx) => { ctx.body = `User ${ctx.params.id}`; }); router.redirect('/old-path', '/new-path'); router.redirect('/old-path', 'user', { id: 123 });
错误处理:
javascriptrouter.get('/error', async (ctx) => { ctx.throw(404, 'User not found'); }); // 使用 allowedMethods 处理不允许的方法 app.use(router.allowedMethods({ throw: true, notImplemented: () => new NotImplemented(), methodNotAllowed: () => new MethodNotAllowed() }));
最佳实践:
- 按功能模块划分路由文件
- 使用路由前缀组织 API 版本
- 合理使用路由中间件进行权限控制
- 统一错误处理和响应格式
- 为路由添加描述性注释
- 使用 TypeScript 增强类型安全