服务器路由
Nitro 支持基于文件的 API 路由(文件会自动映射到 h3 路由)。定义路由就像在
server/api/或server/routes/目录内创建一个文件一样简单。
每个文件只能定义一个处理程序,您可以 将 HTTP 方法附加 到文件名,以定义特定的请求方法。
routes/
api/
test.ts <-- /api/test
hello.get.ts <-- /hello (GET only)
hello.post.ts <-- /hello (POST only)
vite.config.ts
您可以通过创建子目录来嵌套路由。
routes/
api/
[org]/
[repo]/
index.ts <-- /api/:org/:repo
issues.ts <-- /api/:org/:repo/issues
index.ts <-- /api/:org
package.json
/api/ 目录作为特性使用,因此放在 /api 中的路由将无法工作。
您需要使用 server/routes/api/。简单路由
首先,在 server/routes/ 或 server/api/ 目录中创建一个文件。文件名将是路由路径。
然后,导出一个用 defineEventHandler 包裹的函数,该函数将在路由匹配时执行。
import { defineHandler } from "nitro/h3";
export default defineHandler(() => {
return { hello: "API" };
});
带参数的路由
单个参数
要定义带参数的路由,请使用 [<param>] 语法,其中 <param> 是参数的名称。该参数将在 event.context.params 对象中可用,或使用 getRouterParam 工具。
import { defineHandler } from "nitro/h3";
export default defineHandler((event) => {
const { name } = event.context.params;
return `Hello ${name}!`;
});
调用带参数的路由 /hello/nitro,您将得到:
Hello nitro!
多个参数
您可以通过使用 [<param1>]/[<param2>] 语法在路由中定义多个参数,其中每个参数都是一个文件夹。您 不能 在单个文件名的文件夹中定义多个参数。
import { defineHandler } from "nitro/h3";
export default defineHandler((event) => {
const { name, age } = event.context.params;
return `Hello ${name}! You are ${age} years old.`;
});
捕获所有参数
您可以使用 [...<param>] 语法捕获 URL 中剩余的所有部分。这将包括斜杠 / 在参数中。
import { defineHandler } from "nitro/h3";
export default defineHandler((event) => {
const { name } = event.context.params;
return `Hello ${name}!`;
});
调用带参数的路由 /hello/nitro/is/hot,您将得到:
Hello nitro/is/hot!
特定请求方法
您可以将 HTTP 方法附加到文件名,以强制路由仅匹配特定的 HTTP 请求方法,例如 hello.get.ts 将仅匹配 GET 请求。您可以使用任何您想要的 HTTP 方法。
// routes/users/[id].get.ts
import { defineHandler } from "nitro/h3";
export default defineHandler(async (event) => {
const { id } = event.context.params;
// 对 id 执行某些操作
return `用户资料!`
})
// routes/users.post.ts
import { defineHandler, readBody } from "nitro/h3";
export default defineHandler(async (event) => {
const body = await readBody(event);
// 对 body 执行某些操作,例如将其保存到数据库
return { updated: true };
});
捕获所有路由
您可以创建一个特殊的路由,匹配未被任何其他路由匹配的所有路由。这对于创建默认路由非常有用。
要创建捕获所有路由,请在 server/routes/ 或 server/api/ 目录或任何子目录中创建一个名为 [...].ts 的文件。
import { defineHandler } from "nitro/h3";
export default defineHandler((event) => {
return `Hello ${event.url}!`;
});
环境特定处理程序
您可以指定仅在特定构建中包含的路由,通过在文件名后添加 .dev、.prod 或 .prerender 后缀,例如:routes/test.get.dev.ts 或 routes/test.get.prod.ts。
handlers[] 配置的程序注册为环境指定多个环境或预设名称作为环境。中间件
Nitro 路由中间件可以挂钩到请求生命周期中。
中间件在 server/middleware/ 目录中自动注册。
middleware/
auth.ts
logger.ts
...
routes/
hello.ts
简单中间件
中间件与路由处理程序的定义方式完全相同,唯一例外是它们不应返回任何内容。
从中间件返回的行为类似于从请求返回 - 该值将作为响应返回,且不会执行后续代码。
export default defineEventHandler((event) => {
// 扩展或修改事件
event.context.user = { name: 'Nitro' }
})
在 server/middleware/ 目录中的中间件会自动注册到所有路由。如果您想为特定路由注册中间件,请参见 对象语法事件处理程序。
路由元数据
您可以在构建时使用 defineRouteMeta 宏在事件处理程序文件中定义路由处理程序的元数据。
import { defineRouteMeta } from "nitro/runtime";
import { defineHandler } from "nitro/h3";
defineRouteMeta({
openAPI: {
tags: ["test"],
description: "测试路由描述",
parameters: [{ in: "query", name: "test", required: true }],
},
});
export default defineHandler(() => "OK");
执行顺序
中间件按目录列表顺序执行。
server/
middleware/
auth.ts <-- 第一个
logger.ts <-- 第二个
... <-- 第三个
用数字前缀中间件以控制其执行顺序。
server/
middleware/
1.logger.ts <-- 第一个
2.auth.ts <-- 第二个
3.... <-- 第三个
1.filename.ts、2.filename.ts 和 10.filename.ts,则 10.filename.ts 将在 1.filename.ts 之后出现。为避免这种情况,前缀 1-9 时使用 0,如 01,如果您在同一目录中有超过 10 个中间件。请求过滤
中间件在每个请求上执行。
应用自定义逻辑,将其作用域限制为特定条件。
例如,您可以使用 URL 将中间件应用于特定路由:
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 对象。
这种行为可以被某些请求属性(例如:Accept 或 User-Agent 头)覆盖。
路由规则
Nitro 允许您在配置的顶层为每个路由添加逻辑。这可以用于重定向、代理、缓存和为路由添加头。
它是从路由模式(遵循 rou3)到路由选项的映射。
当 cache 选项设置时,匹配模式的处理程序将自动包裹在 defineCachedEventHandler 中。有关此功能的更多信息,请参见 缓存指南。
swr: true|number 是 cache: { swr: true, maxAge: number } 的快捷方式。您可以在 nitro.config.ts 中使用 routeRules 选项设置路由规则。
import { defineNitroConfig } from "nitro/config";
export default defineConfig({
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/**' },
}
});