服务器导入
Geprüfte Übersetzung ·0 % geprüft
Nuxt 可以使用不同的服务器构建器:Nitro 2(nitropack,Nuxt 3 和 4 中的默认选项)、Nitro 3(nitro,从 Nuxt 5 开始),或直接使用 Vite。
nuxt/server 提供与特定服务器运行时无关的服务器代码通用工具。它是 Nuxt 的第二个运行时接口,与 nuxt/app(也可以通过 #app 访问)并列;后者用于应用中也会在浏览器运行的部分。
import { defineEventHandler, getQuery } from 'nuxt/server'
export default defineEventHandler((event) => {
const { name } = getQuery<{ name?: string }>(event)
return { message: `Hello, ${name ?? 'world'}!` }
})这段代码可以在 @nuxt/nitro-server 和 @nuxt/vite-server 下运行;即使 h3 或 Nitro 升级主版本,也能继续运行,因为 Nuxt 会集中处理这些变化。
nuxt/server 从 Nuxt 4.6 开始提供,因此一个文件就能同时用于运行 nitropack v2 的 Nuxt 4.6、运行 Nitro v3 的 Nuxt 5,以及未来构建器带来的任何环境。
nuxt,因此 nuxt/server 无需别名或额外依赖即可解析。导入它的模块无需依赖 h3 或 Nitro 的 peer dependency。类型和工具
| 导入 | 用途 |
|---|---|
defineEventHandler | 定义请求处理程序。 |
createError、isNuxtError | 创建并识别 HTTP 错误。 |
getRequestURL、getRequestHost、getRequestProtocol | 获取请求的 URL、主机和协议。仅在你控制且会覆盖这些请求头的代理之后,才传入 { xForwardedHost: true, xForwardedProto: true } 来信任对应的转发标头。 |
getRequestHeader、getRequestHeaders | 读取请求标头。 |
getRouterParam、getRouterParams | 读取与请求匹配的动态路径段。 |
getRequestIP | 获取客户端 IP 地址,请求中会信任转发标头。 |
getQuery、getValidatedQuery | 读取查询字符串,可选择进行校验。 |
readBody、readValidatedBody | 读取并解析请求体,可选择进行校验。 |
getCookie、parseCookies、setCookie、deleteCookie | 读取单个或全部 Cookie,以及写入 Cookie。 |
setResponseStatus | 设置响应状态和原因短语。 |
handleCors | 应用 CORS 标头并响应预检请求。 |
sendRedirect | 重定向请求。 |
serverFetch | 在进程内获取应用的路由,路径相对于 app.baseURL,并转发 cookie 和 authorization 标头(除非设置 forwardHeaders)。在不支持进程内 fetch 的服务器构建器上会拒绝。 |
useSession、getSession、updateSession、clearSession | 读取和写入密封的会话 Cookie。 |
deriveSecret | 从 appSecret 派生用途专属的密钥。 |
getRouteRules、matchRouteRules | 获取请求匹配的路由规则,或获取其他路径匹配的规则。 |
useRuntimeConfig | 获取服务器的运行时配置。 |
useServerHooks | 获取服务器运行时钩子,包括 render:html 等渲染器钩子,以及 NuxtServerHooks 中声明的钩子。 |
useAppConfig | 获取应用配置;传入事件时,每个请求都会得到一份副本。 |
工具旁还导出了以下类型:RequestEvent、RequestEventContext、NuxtRequestEvent、EventHandler、AppRouteRules、ServerRoutes、CorsOptions、ValidateResult、NuxtError、NuxtErrorDetails、NuxtErrorJSON、NuxtErrorLike、Session、SessionConfig、SessionData、SessionEvent、SessionManager、SessionPassword 和 SessionUpdate。
这些名称不会从 nuxt/server 自动导入。在服务器代码中,同名的自动导入项是 h3 自身的辅助函数,它们接收 h3 event,且部分行为有所不同(例如 defineEventHandler、handleCors、getRouterParams 和 readValidatedBody),因此请显式从 nuxt/server 导入。其中也包括 defineEventHandler:nuxt/server 中的辅助函数会读取它传给处理程序的 event。
defineEventHandler 会保留处理程序的返回类型,而这正是路由的 $fetch 和 useFetch 调用以及对其调用 serverFetch 时的 response.json() 所需的类型。请为返回值添加类型注解,而不是为处理程序添加。Event
RequestEvent 是 nuxt/server 工具操作所依据的 event,其中包含请求、请求 URL、待发送的响应以及请求上下文。
interface RequestEvent {
readonly req: Request
url: URL
readonly res: { status?: number, statusText?: string, readonly headers: Headers }
readonly context: RequestEventContext
}要设置、读取、追加或移除响应标头,请直接使用 event.res.headers:它是标准的 Headers 对象。
Nitro 还提供了更多内容,例如 event.node 和 event.waitUntil();但这四个核心属性适用于所有运行时,无需使用辅助函数:
export default defineEventHandler(async (event) => {
const { id } = await event.req.json()
return { id, page: event.url.searchParams.get('page') }
})NuxtRequestEvent 是配置的构建器所提供形态的同一个请求;在 @nuxt/nitro-server 下,它是 h3 v1 的 H3Event。
处理程序
处理程序文件必须默认导出 nuxt/server 中 defineEventHandler 的返回值。直接导出函数,或使用 h3 的 defineEventHandler 包装函数,收到的会是服务器运行时自己的 event。
处理程序可以返回:
- 可 JSON 序列化的值,作为 JSON 发送,并使用设置在
event.res上的状态和标头。 Response,使用其自身状态发送。设置在event.res.headers上的标头也会发送,并且会保留两处设置的set-cookie值。ReadableStream,作为响应正文流式发送。
验证
readValidatedBody 和 getValidatedQuery 接受任意 Standard Schema(Zod、Valibot、ArkType 等),也接受返回已验证值的函数;返回 true 表示接受输入,返回 false 则表示拒绝输入。
import { defineEventHandler, readValidatedBody } from 'nuxt/server'
import { z } from 'zod'
export default defineEventHandler(async (event) => {
const user = await readValidatedBody(event, z.object({ name: z.string() }))
return { created: user.name }
})无效输入会被拒绝,并返回 400 错误;其 data.issues 会列出验证失败的内容。传入 onError 可以使用其他错误来拒绝输入。
客户端 IP
getRequestIP(event) 返回服务器运行时报告的连接地址;如果没有报告地址,则返回 undefined。默认情况下,不会信任任何转发标头,因为客户端可以在其中发送任意值。
在你控制的代理后面,可以传入 { xForwardedFor: true },改为读取 X-Forwarded-For 的第一个条目。仅当代理会覆盖该标头时才这样做:如果代理只是追加内容,客户端发送的值仍会排在最前面。
会话
useSession 会读取请求的会话;如果没有可读取的会话,就会将新会话密封到 Cookie 中。数据使用 iron 密封,因此数据存放在 Cookie 中,而非服务器存储中;Cookie 默认使用 httpOnly、secure、sameSite: 'lax' 和 path: '/'。
import { defineEventHandler, useSession } from 'nuxt/server'
export default defineEventHandler(async (event) => {
const session = await useSession<{ visits: number }>(event)
await session.update(data => ({ visits: (data.visits ?? 0) + 1 }))
return { visits: session.data.visits }
})如果没有设置 password,会话会使用从应用的 appSecret 派生的密钥进行密封,因此只需设置 NUXT_APP_SECRET。传入至少 32 个字符的 password,即可改用你自己的密钥进行密封。设置 maxAge(以秒为单位)可使 Cookie 和密封值同时过期;设置 name 可将 Cookie 名称从 nuxt-session 更改为其他名称;设置 cookie 可覆盖任意 Cookie 属性。
每个请求只会解封一次会话,因此你可以在任意多个位置调用 getSession。updateSession 和 clearSession 是不使用 manager 对象的同类操作。
派生密钥
deriveSecret(purpose) 会从 appSecret 派生特定用途的密钥:32 字节,以十六进制编码,只要 appSecret 未更改就保持稳定,并且每个用途的密钥都各不相同。会话辅助函数使用的就是它;模块也应使用它,而不是自行请求密钥。请将用途命名为其所属对象的命名空间。
import { deriveSecret } from 'nuxt/server'
const password = await deriveSecret('my-module:tokens')如果未设置 appSecret,或其长度少于 32 个字符,就会抛出一个提及 NUXT_APP_SECRET 的 500 错误。
@nuxt/nitro-server 下,自动导入的 useSession、getSession、updateSession 和 clearSession 会解析为这些函数,因此请显式从 nuxt/server 导入。它们是不同的实现,不能互换:h3 默认的 Cookie 名称是 h3 而非 nuxt-session,使用自己的配置,并且其中一个实现签发的会话无法由另一个实现解封。iron-webcrypto 发布基于 AES-GCM 的密封方式后迁移到该方式。届时,现有会话会以旧格式读取,并在下次写入时以新格式重新密封,因此用户不会被登出。密封值与 h3 的 useSession 生成的值不可互换。超出接口范围
nuxt/server 不是 h3 的重新导出,因此如果你需要 h3 和 Nitro 提供的其他功能(例如服务器生命周期相关功能,如 defineNitroPlugin 和 defineNitroErrorHandler,或 Nitro 自己的运行时钩子),应直接导入。
如果处理程序需要 h3 自带的辅助函数(例如 readRawBody、readMultipartFormData、assertMethod、proxyRequest、fetchWithEvent 或 writeEarlyHints),或者会读取 event.node 或 event.waitUntil(),请从 h3 为该处理程序导入 defineEventHandler:
import { defineEventHandler, readMultipartFormData } from 'h3'
export default defineEventHandler(async (event) => {
const parts = await readMultipartFormData(event)
return { received: parts?.length ?? 0 }
})Nitro 自己的 API 大多不需要传入 event:defineCachedEventHandler()、useStorage()、useDatabase() 和 tasks。请从 nitropack/runtime 导入它们。
不具备可移植性的内容
以下功能需要使用 nuxt/server 之外的内容,因为 Nuxt 无法为每个构建器都提供这些功能:
- 存储。
useStorage()来自nitropack/runtime,其背后的 driver 配置也来自这里。 - 缓存。
defineCachedEventHandler()和defineCachedFunction()来自nitropack/runtime。要使用能在任何环境运行的缓存,请直接依赖缓存库。 - 服务器插件。
defineNitroPlugin()来自nitropack/runtime。在插件中,nuxt/server的useServerHooks()可注册渲染器钩子(包括render:html)以及NuxtServerHooks中声明的钩子;Nitro 自己的request、beforeResponse和error等钩子则来自nitropack/runtime中的useNitroApp().hooks。 - 惰性处理程序。
lazyEventHandler()来自h3。
仅限服务器代码
在 Vue 组件、插件或 shared/ 目录中导入 nuxt/server 会导致构建失败;错误会提示你改用 #app、#imports、$fetch 和 useFetch。这些上下文仍可解析其类型,因此 $fetch 能知道服务器路由会返回什么。
nuxt/server 也只能用于由服务器构建器打包的代码,因为构建器会提供其背后的运行时配置、应用配置、钩子和进程内 fetch。在 Nuxt 进程中运行的代码(例如 nuxt.config.ts、模块的 setup,或传给 addDevServerHandler 的函数)并不具备这些能力,因此不要在那里导入 nuxt/server:例如,useRuntimeConfig() 和 useAppConfig() 会返回空对象。请改为读取 nuxt.options,并参阅开发服务器处理程序了解如何在模块中编写处理程序。
模块
运行时代码仅从 nuxt/server 导入内容的模块,从 v4.6 起可在任何服务器构建器下运行,无需版本检查,也不依赖 h3 或 Nitro:
import { defineEventHandler, useRuntimeConfig } from 'nuxt/server'
export default defineEventHandler(() => ({
version: useRuntimeConfig().myModule.version,
}))nuxt/server 保留为外部依赖;它会在 Nuxt 构建过程中解析为正确的服务器构建器工具。支持 Nuxt <4.6 版本需要多做一步,因为这些项目无法解析 nuxt/server。你可以同时注册可移植文件和当前随包发布的文件,Nuxt 会选择应用能够运行的文件。