Koa 中间件是一个 async 函数,接收两个参数:ctx(上下文对象)和 next(下一个中间件的调用函数)。开发自定义中间件需要遵循特定的模式和最佳实践。
中间件基本结构:
javascriptasync function myMiddleware(ctx, next) { // 前置逻辑 console.log('请求进入'); // 调用下一个中间件 await next(); // 后置逻辑 console.log('请求处理完成'); } // 使用中间件 app.use(myMiddleware);
常见中间件类型:
- 日志中间件:
javascriptfunction loggerMiddleware(ctx, next) { const start = Date.now(); await next(); const ms = Date.now() - start; console.log(`${ctx.method} ${ctx.url} - ${ms}ms`); }
- 认证中间件:
javascriptasync function authMiddleware(ctx, next) { const token = ctx.headers.authorization; if (!token) { ctx.throw(401, 'Unauthorized'); } try { const user = await verifyToken(token); ctx.state.user = user; await next(); } catch (error) { ctx.throw(401, 'Invalid token'); } }
- 错误处理中间件:
javascriptasync function errorHandler(ctx, next) { try { await next(); } catch (err) { ctx.status = err.status || 500; ctx.body = { error: err.message, code: err.code }; ctx.app.emit('error', err, ctx); } }
- CORS 中间件:
javascriptasync function corsMiddleware(ctx, next) { ctx.set('Access-Control-Allow-Origin', '*'); ctx.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE'); ctx.set('Access-Control-Allow-Headers', 'Content-Type, Authorization'); if (ctx.method === 'OPTIONS') { ctx.status = 204; return; } await next(); }
- 请求体解析中间件:
javascriptasync function bodyParser(ctx, next) { if (ctx.method !== 'POST' && ctx.method !== 'PUT') { return await next(); } const chunks = []; for await (const chunk of ctx.req) { chunks.push(chunk); } const body = Buffer.concat(chunks).toString(); ctx.request.body = JSON.parse(body); await next(); }
中间件开发最佳实践:
- 命名规范: 使用描述性的函数名,如
authMiddleware、loggerMiddleware - 错误处理: 使用 try-catch 捕获错误,避免影响其他中间件
- 性能优化: 避免在中间件中执行耗时操作
- 配置化: 支持配置参数,提高中间件灵活性
- 文档完善: 提供清晰的使用文档和示例
可配置中间件示例:
javascriptfunction createLogger(options = {}) { const { format = 'default', includeQuery = false } = options; return async function logger(ctx, next) { const start = Date.now(); await next(); const ms = Date.now() - start; let log = `${ctx.method} ${ctx.url} - ${ms}ms`; if (includeQuery && Object.keys(ctx.query).length) { log += ` ${JSON.stringify(ctx.query)}`; } console.log(log); }; } // 使用配置化中间件 app.use(createLogger({ includeQuery: true }));
中间件组合:
javascriptconst compose = require('koa-compose'); const middleware = compose([ loggerMiddleware, authMiddleware, errorHandler ]); app.use(middleware);
开发高质量中间件的关键是理解洋葱模型的执行流程,合理使用前置和后置逻辑,并确保中间件的独立性和可复用性。