Lzh on GitHub

服务器端路由

Nitro 支持文件系统路由,可自动将文件映射到 h3 路由。

事件处理程序

事件处理程序 是一个函数,它将被绑定到路由并在路由器匹配到传入请求的路由时执行。

请参阅 h3.unjs.io/guide/event-handler 了解更多信息。

Read more in 请参阅 h3.unjs.io/guide/event-handler 了解更多信息.

文件系统路由

Nitro 支持文件级路由来处理您的 API 路由(文件会自动映射到 h3 路由)。定义路由就像在 server/api/server/routes/ 目录中创建文件一样简单。

每个文件只能定义一个处理程序,您可以 将 HTTP 方法附加到文件名 来定义特定的请求方法。

server/
  api/
    test.ts        <-- /api/test
  routes/
    hello.get.ts   <-- GET /hello
    hello.post.ts  <-- POST /hello
nitro.config.ts

您可以通过创建子目录来嵌套路由。

server/
  routes/
    communities/
      index.get.ts
      index.post.ts
      [id]/
        index.get.ts
        index.post.ts
    hello.get.ts
    hello.post.ts
像 Vercel 这样的一些提供商会将顶层 /api/ 目录作为一项功能,因此放置在 /api 中的路由将无法工作。您必须使用 server/routes/api/

简单路由

首先,在 server/routes/server/api/ 目录中创建一个文件。文件名将是路由路径。

然后,导出一个用 defineEventHandler 包装的函数,该函数将在路由匹配时执行。

server/api/test.ts
export default defineEventHandler(() => {
  return { hello: 'API' }
})

带路径参数的路由

单个参数

要定义带参数的路由,请使用 [<param>] 语法,其中 <param> 是参数的名称。该参数将在 event.context.params 对象中可用,或者使用 unjs/h3 中的 getRouterParam 工具。

server/routes/hello/[name].ts
export default defineEventHandler(event => {
  const name = getRouterParam(event, 'name')

  return `Hello ${name}!`
})

使用参数 /hello/nitro 调用路由,您将得到:

Response
Hello nitro!

多个参数

您可以使用 [<param1>]/[<param2>] 语法在路由中定义多个参数,其中每个参数都是一个文件夹。您不能 在单个文件名或文件夹中定义多个参数。

server/routes/hello/[name]/[age].ts
export default defineEventHandler(event => {
  const name = getRouterParam(event, 'name')
  const age = getRouterParam(event, 'age')

  return `Hello ${name}! You are ${age} years old.`
})

捕获所有参数

您可以使用 [...<param>] 语法捕获 URL 的所有剩余部分。这将包含参数中的 /

server/routes/hello/[...name].ts
export default defineEventHandler(event => {
  const name = getRouterParam(event, 'name')

  return `Hello ${name}!`
})

使用参数 /hello/nitro/is/hot 调用路由,您将得到:

Response
Hello nitro/is/hot!

特定请求方法

您可以将 HTTP 方法附加到文件名,以强制路由仅匹配特定的 HTTP 请求方法,例如 hello.get.ts 将仅匹配 GET 请求。您可以使用任何您想要的 HTTP 方法。

// server/routes/users/[id].get.ts
export default defineEventHandler(async (event) => {
  const id = getRouterParam(event, 'id')

  // 对 id 做一些操作

  return `User profile!`
})

捕获所有路由

您可以创建一个特殊路由,它将匹配所有未被其他路由匹配的路由。这对于创建默认路由很有用。

要创建捕获所有路由,请在 server/routes/server/api/ 目录或任何子目录中创建一个名为 [...].ts 的文件。

server/routes/[...].ts
export default defineEventHandler(event => {
  const url = getRequestURL(event)

  return `Hello ${url}!`
})

环境特定处理程序

您可以通过在文件名后添加 .dev.prod.prerender 后缀来指定仅包含在特定构建中的路由,例如:routes/test.get.dev.tsroutes/test.get.prod.ts

您可以指定多个环境,或使用通过 handlers[] 配置的路由的程序化注册来指定预设名称作为环境。

中间件

Nitro 路由中间件可以挂接到请求生命周期中。

中间件可以在请求处理之前修改请求,而不是之后。
Read more in 请参阅 h3.unjs.io/guide/event-handler#middleware 了解更多信息.

server/middleware/ 目录中的中间件会自动注册。

server/
  routes/
    hello.ts
  middleware/
    auth.ts
    logger.ts
    ...
nitro.config.ts

简单中间件

中间件的定义方式与路由处理程序完全相同,唯一的例外是它们不应该返回任何内容。从中间件返回就像从请求返回一样——该值将作为响应返回,并且不会运行后续代码。

server/middleware/auth.ts
export default defineEventHandler((event) => {
  // 扩展或修改事件
  event.context.user = { name: 'Nitro' }
})

server/middleware/ 目录中的中间件会自动注册到所有路由。如果您想为特定路由注册中间件,请参阅 对象语法事件处理程序

从中间件返回任何内容都会关闭请求,应避免这样做!中间件返回的任何值都将作为响应,并且不会执行后续代码,但不建议这样做!

路由元数据

您可以使用 defineRouteMeta 宏在事件处理程序文件中定义构建时路由处理程序元数据。

此功能目前处于实验阶段。
server/api/test.ts
defineRouteMeta({
  openAPI: {
    tags: ["test"],
    description: "Test route description",
    parameters: [{ in: "query", name: "test", required: true }],
  },
});

export default defineEventHandler(() => "OK");
Read more in 此功能目前可用于指定 OpenAPI 元数据。请参阅 swagger 规范以获取可用的 OpenAPI 选项.

执行顺序

中间件按目录列表顺序执行。

server/
  middleware/
    auth.ts    <-- 首先
    logger.ts  <-- 其次
    ...        <-- 第三

使用数字作为中间件的前缀来控制它们的执行顺序。

server/
  middleware/
    1.logger.ts <-- 首先
    2.auth.ts   <-- 其次
    3....       <-- 第三
请记住,文件名是按字符串排序的,因此例如,如果您有 3 个文件 1.filename.ts2.filename.ts10.filename.ts,则 10.filename.ts 将排在 1.filename.ts 之后。为避免这种情况,如果同一目录中有 10 个以上中间件,则在 1-9 的数字前加上 0,例如 01

请求过滤

中间件在每个请求上执行。

应用自定义逻辑将它们限制在特定条件下。

例如,您可以使用 URL 将中间件应用于特定路由:

server/middleware/auth.ts
export default defineEventHandler((event) => {
  // 仅对 /auth 路由执行
  if (getRequestURL(event).pathname.startsWith('/auth')) {
    event.context.user = { name: 'Nitro' }
  }
})

错误处理

您可以使用 H3 中可用的工具 在路由和中间件中处理错误。

错误发送回客户端的方式取决于路由的路径。对于大多数路由,Content-Type 默认为 text/html,并提供一个简单的 HTML 错误页面。如果路由以 /api/ 开头(无论是因为它放置在 api/ 还是 routes/api/ 中),默认值将更改为 application/json,并发送一个 JSON 对象。

此行为可以通过一些请求属性(例如:AcceptUser-Agent 头)覆盖。

路由规则

Nitro 允许您为配置中的每个路由在顶层添加逻辑。它可用于重定向、代理、缓存和向路由添加头信息。

它是从路由模式(遵循 unjs/radix3)到路由选项的映射。

当设置 cache 选项时,匹配模式的处理程序将自动用 defineCachedEventHandler 包装。请参阅 缓存指南 了解有关此函数的更多信息。

swr: true|numbercache: { swr: true, maxAge: number } 的快捷方式。

您可以在 nitro.config.ts 中使用 routeRules 选项设置路由规则。

export default defineNitroConfig({
  routeRules: {
    '/blog/**': { swr: true },
    '/blog/**': { swr: 600 },
    '/blog/**': { static: true },
    '/blog/**': { cache: { /* 缓存选项 */ } },
    '/assets/**': { headers: { 'cache-control': 's-maxage=0' } },
    '/api/v1/**': { cors: true, headers: { 'access-control-allow-methods': 'GET' } },
    '/old-page': { redirect: '/new-page' },
    '/old-page/**': { redirect: '/new-page/**' },
    '/proxy/example': { proxy: 'https://example.com' },
    '/proxy/**': { proxy: '/api/**' },
  }
})