中间件

使用 H3 中间件拦截请求、响应和错误。
我们建议尽可能使用组合式工具。全局中间件可能会让应用逻辑变得更复杂,降低其可预测性和理解难度。

全局中间件在每个请求路由处理之前运行,作为包装器来拦截请求、响应和错误。

Read more in 请求生命周期.

你可以使用 H3.useapp 实例 注册全局中间件。

示例: 注册一个记录每个请求的全局中间件。

app.use((event) => {
  console.log(event);
});

示例: 注册一个匹配特定请求的全局中间件。

app.use(
  "/blog/**",
  (event, next) => {
    console.log("[alert] POST 请求访问 /blog 路径!");
  },
  {
    method: "POST",
    // match: (event) => event.req.method === "POST",
  },
);

你可以注册带有 next 参数的中间件,以拦截后续中间件和处理器的返回值。

app.use(async (event, next) => {
  const rawBody = await next();
  // [拦截响应]
  return rawBody;
});

下面示例中,总是响应 Middleware 1

app
  .use(() => "Middleware 1")
  .use(() => "Middleware 2")
  .get("/", "Hello");
如果中间件返回除 undefinednext() 结果之外的值,中间件会立即拦截请求处理并发送响应。

在添加路由时,可以注册只随该路由运行的中间件。

import { basicAuth } from "h3";

app.get(
  "/secret",
  (event) => {
    /* ... */
  },
  {
    middleware: [basicAuth({ password: "test" })],
  },
);

为方便起见,H3 提供了中间件工厂函数 onRequestonResponseonError

import { onRequest, onResponse, onError } from "h3";

app.use(
  onRequest((event) => {
    console.log(`[${event.req.method}] ${event.url.pathname}`);
  }),
);

app.use(
  onResponse((response, event) => {
    console.log(`[${event.req.method}] ${event.url.pathname} ~>`, body);
  }),
);

app.use(
  onError((error, event) => {
    console.log(
      `[${event.req.method}] ${event.url.pathname} !! ${error.message}`,
    );
  }),
);