教程 koa tutorial

自定义中间件

在 Koa 中,中间件是构建应用的核心机制。它们能够在请求和响应之间进行拦截和处理,使得在 Koa 中构建复杂的应用变得更加灵活和可扩展。Koa 的中间件机制基于 async/await,使得在异步操作中传递控制变得非常简单。

本篇将介绍如何在 Koa 中创建和使用自定义中间件。

1. 创建自定义中间件

Koa 中的每个中间件都是一个异步函数,接收两个参数:ctx(上下文对象)和 next(一个函数,调用它可以将控制权传递给下一个中间件)。你可以根据需求在中间件中执行任何逻辑。

示例:简单的自定义中间件

js
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 允许你使用多个中间件,按照它们的顺序执行。每个中间件都会依次处理请求,直到最后一个中间件处理响应。

示例:使用多个中间件

js
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 对象

js
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 中,你可以使用自定义中间件来捕获错误,防止应用崩溃,并可以根据需求记录或返回自定义错误信息。

示例:全局错误捕获

js
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 提供了路由功能,你可以在路由中使用自定义中间件来处理特定路径的请求。

示例:自定义中间件与路由结合使用

js
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 更加简洁和强大,让开发者可以根据自己的需求,精确控制请求和响应的处理过程。