自定义中间件
在 Koa 中,中间件是构建应用的核心机制。它们能够在请求和响应之间进行拦截和处理,使得在 Koa 中构建复杂的应用变得更加灵活和可扩展。Koa 的中间件机制基于 async/await
,使得在异步操作中传递控制变得非常简单。
本篇将介绍如何在 Koa 中创建和使用自定义中间件。
1. 创建自定义中间件
Koa 中的每个中间件都是一个异步函数,接收两个参数:ctx
(上下文对象)和 next
(一个函数,调用它可以将控制权传递给下一个中间件)。你可以根据需求在中间件中执行任何逻辑。
示例:简单的自定义中间件
const Koa = require('koa');
const app = new Koa();
// 自定义中间件:记录请求时间
const logTime = async (ctx, next) => {
const start = Date.now();
await next(); // 继续处理下一个中间件
const duration = Date.now() - start;
console.log(`Request to ${ctx.url} took ${duration}ms`);
};
app.use(logTime); // 使用自定义中间件
app.use((ctx) => {
ctx.body = 'Hello Koa!';
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
在上面的代码中,我们创建了一个 logTime
中间件,它记录了请求的开始时间和结束时间,并输出请求的处理时长。
自定义中间件的结构
一个标准的中间件包含两部分:
- 请求处理逻辑:你可以在中间件中执行任何逻辑,比如读取请求数据、修改
ctx
对象、记录日志等。 - 调用
next()
:中间件需要调用next()
来传递控制权给下一个中间件,否则请求会被挂起,无法继续处理。
2. 使用多个中间件
Koa 允许你使用多个中间件,按照它们的顺序执行。每个中间件都会依次处理请求,直到最后一个中间件处理响应。
示例:使用多个中间件
app.use(async (ctx, next) => {
console.log('Middleware 1');
await next(); // 调用下一个中间件
console.log('Middleware 1 - After next');
});
app.use(async (ctx, next) => {
console.log('Middleware 2');
await next();
console.log('Middleware 2 - After next');
});
app.use((ctx) => {
console.log('Final middleware');
ctx.body = 'Hello from Koa!';
});
在这个示例中,多个中间件会按照顺序执行,next()
会将控制权传递给下一个中间件。
中间件的执行顺序
- 中间件的执行顺序是按照它们的
app.use()
顺序执行的。 - 在每个中间件内部,
await next()
表示在当前中间件完成之后,继续执行下一个中间件。可以在next()
之后添加代码,用于响应阶段的处理。
3. 在中间件中操作 ctx
对象
ctx
(上下文对象)是 Koa 中所有中间件共享的对象,它包含了请求和响应的相关信息。你可以在中间件中修改 ctx
来传递数据或改变请求与响应的内容。
示例:在中间件中修改 ctx
对象
const addCustomHeader = async (ctx, next) => {
ctx.set('X-Custom-Header', 'Koa Middleware Example');
await next();
};
app.use(addCustomHeader);
app.use((ctx) => {
ctx.body = 'Hello Koa!';
});
在这个例子中,addCustomHeader
中间件会在每个响应中添加一个自定义的 HTTP 头。
4. 异常处理与错误捕获
在 Koa 中,你可以使用自定义中间件来捕获错误,防止应用崩溃,并可以根据需求记录或返回自定义错误信息。
示例:全局错误捕获
const errorHandler = async (ctx, next) => {
try {
await next();
} catch (err) {
console.error('Error occurred:', err.message);
ctx.status = err.status || 500;
ctx.body = { error: err.message };
}
};
app.use(errorHandler);
app.use(async (ctx) => {
throw new Error('Something went wrong!');
});
在这个例子中,errorHandler
中间件捕获了应用中发生的所有错误,并返回自定义的错误信息。
5. 自定义中间件与路由结合
你可以将自定义中间件与路由结合使用。在 Koa 中,koa-router
提供了路由功能,你可以在路由中使用自定义中间件来处理特定路径的请求。
示例:自定义中间件与路由结合使用
const Router = require('koa-router');
const router = new Router();
const authMiddleware = async (ctx, next) => {
if (ctx.headers.authorization === 'Bearer secret') {
await next();
} else {
ctx.status = 401;
ctx.body = 'Unauthorized';
}
};
router.get('/protected', authMiddleware, (ctx) => {
ctx.body = 'This is a protected route';
});
app.use(router.routes());
在这个例子中,authMiddleware
中间件检查请求头中的授权信息,只有通过认证的请求才能访问 /protected
路由。
6. 总结
自定义中间件是 Koa 应用灵活性和可扩展性的核心。你可以在中间件中进行请求处理、响应修改、错误捕获等多种操作。通过自定义中间件,可以很容易地实现请求日志记录、认证授权、数据处理等功能,并将它们与路由、其他中间件结合使用,帮助你构建高效且灵活的 Web 应用。
自定义中间件使得 Koa 更加简洁和强大,让开发者可以根据自己的需求,精确控制请求和响应的处理过程。