---
title: "服务器导入"
description: "`nuxt/server` 是服务器代码的导入接口，不依赖特定服务器运行时。"
canonical_url: "https://nuxt.zhcndoc.com/docs/4.x/guide/going-further/server-imports"
---
# 服务器导入

> `nuxt/server` 是服务器代码的导入接口，不依赖特定服务器运行时。

Nuxt 可以使用不同的[服务器构建器](https://nuxt.zhcndoc.com/docs/4.x/guide/going-further/builders)：Nitro 2（`nitropack`，Nuxt 3 和 4 中的默认选项）、Nitro 3（`nitro`，从 Nuxt 5 开始），或直接使用 Vite。

`nuxt/server` 提供与特定服务器运行时无关的服务器代码通用工具。它是 Nuxt 的第二个运行时接口，与 `nuxt/app`（也可以通过 `#app` 访问）并列；后者用于应用中也会在浏览器运行的部分。

```ts [server/api/hello.ts]
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，以及未来构建器带来的任何环境。

<tip>

每个 Nuxt 应用都安装了 `nuxt`，因此 `nuxt/server` 无需别名或额外依赖即可解析。导入它的模块无需依赖 h3 或 Nitro 的 peer dependency。

</tip>

## 类型和工具

<table>
<thead>
  <tr>
    <th>
      导入
    </th>
    
    <th>
      用途
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        defineEventHandler
      </code>
    </td>
    
    <td>
      定义请求处理程序。
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        createError
      </code>
      
      、<code>
        isNuxtError
      </code>
    </td>
    
    <td>
      创建并识别 HTTP 错误。
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        getRequestURL
      </code>
    </td>
    
    <td>
      获取请求的 URL。
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        getRequestHeader
      </code>
      
      、<code>
        getRequestHeaders
      </code>
    </td>
    
    <td>
      读取请求标头。
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        getRouterParam
      </code>
      
      、<code>
        getRouterParams
      </code>
    </td>
    
    <td>
      读取请求匹配到的动态片段。
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        getRequestIP
      </code>
    </td>
    
    <td>
      获取客户端 IP 地址，并且<a href="#client-ip">
        信任请求中的转发标头
      </a>
      
      。
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        getQuery
      </code>
      
      、<code>
        getValidatedQuery
      </code>
    </td>
    
    <td>
      读取查询字符串，也可以进行<a href="#validation">
        验证
      </a>
      
      。
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        readBody
      </code>
      
      、<code>
        readValidatedBody
      </code>
    </td>
    
    <td>
      读取并解析请求正文，也可以进行<a href="#validation">
        验证
      </a>
      
      。
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        getCookie
      </code>
      
      、<code>
        setCookie
      </code>
      
      、<code>
        deleteCookie
      </code>
    </td>
    
    <td>
      读取和写入 Cookie。
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        setResponseStatus
      </code>
    </td>
    
    <td>
      设置响应状态和原因短语。
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        handleCors
      </code>
    </td>
    
    <td>
      应用 <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS" rel="nofollow">
        CORS
      </a>
      
       标头并响应预检请求。
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        sendRedirect
      </code>
    </td>
    
    <td>
      重定向请求。
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        useSession
      </code>
      
      、<code>
        getSession
      </code>
      
      、<code>
        updateSession
      </code>
      
      、<code>
        clearSession
      </code>
    </td>
    
    <td>
      读取和写入<a href="#sessions">
        密封的会话 Cookie
      </a>
      
      。
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        deriveSecret
      </code>
    </td>
    
    <td>
      从 <code>
        appSecret
      </code>
      
       <a href="#deriving-secrets">
        派生
      </a>
      
      特定用途的密钥。
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        getRouteRules
      </code>
    </td>
    
    <td>
      获取请求匹配到的<a href="https://nuxt.zhcndoc.com/docs/4.x/guide/concepts/rendering#route-rules">
        路由规则
      </a>
      
      。
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        useRuntimeConfig
      </code>
    </td>
    
    <td>
      获取服务器的<a href="https://nuxt.zhcndoc.com/docs/4.x/guide/going-further/runtime-config">
        运行时配置
      </a>
      
      。
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        useAppConfig
      </code>
    </td>
    
    <td>
      获取<a href="https://nuxt.zhcndoc.com/docs/4.x/directory-structure/app/app-config">
        应用配置
      </a>
      
      ；传入 event 时，每个请求都会获得一份副本。
    </td>
  </tr>
</tbody>
</table>

这些工具旁边也导出了类型：`RequestEvent`、`RequestEventContext`、`NuxtRequestEvent`、`EventHandler`、`AppRouteRules`、`ServerRoutes`、`CorsOptions`、`ValidateResult`、`NuxtError`、`NuxtErrorDetails`、`NuxtErrorJSON`、`NuxtErrorLike`、`Session`、`SessionConfig`、`SessionData`、`SessionEvent`、`SessionManager`、`SessionPassword` 和 `SessionUpdate`。

这些名称不会从 `nuxt/server` 自动导入。在服务器代码中，同名的[自动导入](https://nuxt.zhcndoc.com/docs/4.x/directory-structure/server)名称是 h3 自己的辅助函数，它们接收 h3 event，并且在某些情况下行为不同（包括 `defineEventHandler`、`handleCors`、`getRouterParams` 和 `readValidatedBody`），因此请显式从 `nuxt/server` 导入。这也包括 `defineEventHandler`：`nuxt/server` 的辅助函数会读取它传给处理程序的 event。

<read-more to="https://nuxt.zhcndoc.com/docs/4.x/getting-started/upgrade#moving-to-nuxtserver">

了解如何将现有服务器代码迁移到 `nuxt/server`，以及它的辅助函数与 h3 的辅助函数有何不同。

</read-more>

<tip>

`defineEventHandler` 会保留处理程序的返回类型，而 [`$fetch` 和 `useFetch`](https://nuxt.zhcndoc.com/docs/4.x/getting-started/data-fetching) 对该路由的调用会用到这个类型。请注解返回值，而不是处理程序。

</tip>

## Event

`RequestEvent` 是 `nuxt/server` 工具操作所依据的 event，其中包含请求、请求 URL、待发送的响应以及请求上下文。

```ts
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()`；但这四个核心属性适用于所有运行时，无需使用辅助函数：

```ts [server/api/echo.post.ts]
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`。

## 验证

`readValidatedBody` 和 `getValidatedQuery` 接受任意 [Standard Schema](https://standardschema.dev)（Zod、Valibot、ArkType 等），也接受返回已验证值的函数；返回 `true` 表示接受输入，返回 `false` 则表示拒绝输入。

```ts [server/api/users.post.ts]
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](https://github.com/brc-dd/iron-webcrypto) 密封，因此数据存放在 Cookie 中，而非服务器存储中；Cookie 默认使用 `httpOnly`、`secure`、`sameSite: 'lax'` 和 `path: '/'`。

```ts [server/api/visits.ts]
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`](https://nuxt.zhcndoc.com/docs/4.x/guide/going-further/runtime-config#application-secret) 派生的密钥进行密封，因此只需设置 `NUXT_APP_SECRET`。传入至少 32 个字符的 `password`，即可改用你自己的密钥进行密封。设置 `maxAge`（以秒为单位）可使 Cookie 和密封值同时过期；设置 `name` 可将 Cookie 名称从 `nuxt-session` 更改为其他名称；设置 `cookie` 可覆盖任意 Cookie 属性。

每个请求只会解封一次会话，因此你可以在任意多个位置调用 `getSession`。`updateSession` 和 `clearSession` 是不使用 manager 对象的同类操作。

### 派生密钥

`deriveSecret(purpose)` 会从 `appSecret` 派生特定用途的密钥：32 字节，以十六进制编码，只要 `appSecret` 未更改就保持稳定，并且每个用途的密钥都各不相同。会话辅助函数使用的就是它；模块也应使用它，而不是自行请求密钥。请将用途命名为其所属对象的命名空间。

```ts
import { deriveSecret } from 'nuxt/server'

const password = await deriveSecret('my-module:tokens')
```

如果未设置 `appSecret`，或其长度少于 32 个字符，就会抛出一个提及 `NUXT_APP_SECRET` 的 `500` 错误。

<note>

h3 提供了同名的会话辅助函数；在 `@nuxt/nitro-server` 下，自动导入的 `useSession`、`getSession`、`updateSession` 和 `clearSession` 会解析为这些函数，因此请显式从 `nuxt/server` 导入。它们是不同的实现，不能互换：h3 默认的 Cookie 名称是 `h3` 而非 `nuxt-session`，使用自己的配置，并且其中一个实现签发的会话无法由另一个实现解封。

</note>

<note>

会话 API 稳定，但密封 Cookie 的格式可能会在次要版本中更改：Nuxt 计划在 `iron-webcrypto` 发布基于 AES-GCM 的密封方式后迁移到该方式。届时，现有会话会以旧格式读取，并在下次写入时以新格式重新密封，因此用户不会被登出。密封值与 h3 的 `useSession` 生成的值不可互换。

</note>

<warning>

会话存放在 Cookie 中，因此大小受浏览器可接受范围的限制。写入序列化后超过 4096 字节的会话会抛出错误；较大的数据应保存在服务器端，并通过 ID 在会话中引用。

</warning>

## 超出接口范围

`nuxt/server` 不是 h3 的重新导出，因此如果你需要 h3 和 Nitro 提供的其他功能（例如服务器生命周期相关功能，如 `defineNitroPlugin`、`defineNitroErrorHandler` 和 Nitro app 钩子），应直接导入。

如果处理程序需要 h3 自带的辅助函数（例如 `readRawBody`、`readMultipartFormData`、`assertMethod`、`proxyRequest`、`fetchWithEvent` 或 `writeEarlyHints`），或者会读取 `event.node` 或 `event.waitUntil()`，请从 `h3` 为该处理程序导入 `defineEventHandler`：

```ts [server/api/upload.post.ts]
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()` 和运行时钩子（`useNitroApp().hooks`，包括 `render:html`）来自 `nitropack/runtime`。
- **相对于应用的 fetch。** `useNitroApp().localFetch` 来自 `nitropack/runtime`。它无需 origin 即可调用应用的路由，这需要运行时的路由器。
- **惰性处理程序。** `lazyEventHandler()` 来自 `h3`。

## 仅限服务器代码

在 Vue 组件、插件或 `shared/` 目录中导入 `nuxt/server` 会导致构建失败；错误会提示你改用 `#app`、`#imports`、`$fetch` 和 `useFetch`。这些上下文仍可解析其类型，因此 `$fetch` 能知道服务器路由会返回什么。

## 模块

运行时代码仅从 `nuxt/server` 导入内容的模块，从 v4.6 起可在任何服务器构建器下运行，无需版本检查，也不依赖 h3 或 Nitro：

```ts [runtime/server/api/status.ts]
import { defineEventHandler, useRuntimeConfig } from 'nuxt/server'

export default defineEventHandler(() => ({
  version: useRuntimeConfig().myModule.version,
}))
```

<tip>

打包时请将 `nuxt/server` 保留为外部依赖；它会在 Nuxt 构建过程中解析为正确的服务器构建器工具。

</tip>

支持 Nuxt <4.6 版本需要多做一步，因为这些项目无法解析 `nuxt/server`。你可以同时注册可移植文件和当前随包发布的文件，Nuxt 会选择应用能够运行的文件。

<read-more to="https://nuxt.zhcndoc.com/docs/4.x/guide/modules/server-compatibility">

了解如何为每个服务器 API 注册一个处理程序。

</read-more>

<read-more to="https://nuxt.zhcndoc.com/docs/4.x/guide/going-further/builders">

了解服务器构建器如何提供 `nuxt/server` 背后的实现。

</read-more>

---

- [源码](https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/server/index.ts)


## Sitemap

See the full [sitemap](https://nuxt.zhcndoc.com/sitemap.md) for all pages.
