NextRequest 与 NextResponse
next/server 提供了专用于中间件和边缘 API 路由的服务端辅助工具。
NextRequest
NextRequest 对象是对原生 Request 接口的扩展,新增了以下方法和属性:
-
cookies- 一个包含请求中 Cookie 的 RequestCookies 实例。可读取/修改请求的Cookie头。另请参阅在中间件中使用 Cookie。get- 接收 Cookie 名称,返回包含name和value的对象。若未找到对应名称的 Cookie 则返回undefined。若存在多个匹配项,仅返回第一个匹配项。getAll- 类似get方法,但返回所有匹配名称的 Cookie 列表。若未指定名称,则返回所有可用 Cookie。set- 接收符合 W3C CookieStore API 规范中CookieListItem属性的对象。delete- 接收 Cookie 名称或名称列表,删除匹配的 Cookie。返回true表示删除成功,false表示未删除。has- 接收 Cookie 名称,返回布尔值表示该 Cookie 是否存在。clear- 无参数方法,将直接移除Cookie头。
-
nextUrl: 包含扩展的解析后 URL 对象,可访问 Next.js 特有属性如pathname、basePath、trailingSlash和i18n。包含以下属性:basePath(string)buildId(string || undefined)defaultLocale(string || undefined)domainLocaledefaultLocale: (string)domain: (string)http: (boolean || undefined)locales: (string[] || undefined)
locale(string || undefined)url(URL)
-
ip: (string || undefined) - 包含请求的 IP 地址。该信息由托管平台提供。 -
geo- 包含请求的地理位置信息。该信息由托管平台提供。包含以下属性:city(string || undefined)country(string || undefined)region(string || undefined)latitude(string || undefined)longitude(string || undefined)
您可以将 NextRequest 对象作为原生 Request 接口的直接替代,从而获得更多控制请求的能力。
可从 next/server 导入 NextRequest:
import type { NextRequest } from 'next/server'NextFetchEvent
NextFetchEvent 对象扩展了原生 FetchEvent 对象,并包含 waitUntil() 方法。
waitUntil() 方法可用于延长函数执行时间,以便完成其他后台任务。
import { NextResponse } from 'next/server'
import type { NextFetchEvent, NextRequest } from 'next/server'
export function middleware(req: NextRequest, event: NextFetchEvent) {
event.waitUntil(
fetch('https://my-analytics-platform.com', {
method: 'POST',
body: JSON.stringify({ pathname: req.nextUrl.pathname }),
})
)
return NextResponse.next()
}可从 next/server 导入 NextFetchEvent:
import type { NextFetchEvent } from 'next/server'NextResponse
NextResponse 类扩展了原生 Response 接口,具有以下特性:
公共方法
公共方法可通过 NextResponse 类实例调用。根据使用场景,您可以创建实例并赋值给变量,然后访问以下公共方法:
cookies- 一个包含响应中 Cookie 的 ResponseCookies 实例。可读取/修改响应的Set-Cookie头。另请参阅在中间件中使用 Cookie。get- 接收 Cookie 名称,返回包含name和value的对象。若未找到对应名称的 Cookie 则返回undefined。若存在多个匹配项,仅返回第一个匹配项。getAll- 类似get方法,但返回所有匹配名称的 Cookie 列表。若未指定名称,则返回所有可用 Cookie。set- 接收符合 W3C CookieStore API 规范中CookieListItem属性的对象。delete- 接收 Cookie 名称或名称列表,删除匹配的 Cookie。返回true表示删除成功,false表示未删除。
静态方法
以下静态方法可直接通过 NextResponse 类调用:
redirect()- 返回设置了重定向的NextResponserewrite()- 返回设置了重写的NextResponsenext()- 返回将继续中间件链的NextResponse
使用上述方法时,必须返回方法返回的 NextResponse 对象。可从 next/server 导入 NextResponse:
import { NextResponse } from 'next/server'userAgent
userAgent 辅助工具允许您与请求中的用户代理对象交互。它抽象自原生 Request 对象,是一项可选功能。具有以下属性:
isBot: (boolean) 请求是否来自已知爬虫browsername: (string || undefined) 浏览器名称version: (string || undefined) 动态确定的浏览器版本
devicemodel: (string || undefined) 动态确定的设备型号type: (string || undefined) 浏览器类型,可能值为:console、mobile、tablet、smarttv、wearable、embedded或undefinedvendor: (string || undefined) 动态确定的设备厂商
enginename: (string || undefined) 浏览器引擎名称,可能值为:Amaya、Blink、EdgeHTML、Flow、Gecko、Goanna、iCab、KHTML、Links、Lynx、NetFront、NetSurf、Presto、Tasman、Trident、w3m、WebKit或undefinedversion: (string || undefined) 动态确定的浏览器引擎版本或undefined
osname: (string || undefined) 操作系统名称,可能为undefinedversion: (string || undefined) 动态确定的操作系统版本或undefined
cpuarchitecture: (string || undefined) CPU 架构,可能值为:68k、amd64、arm、arm64、armhf、avr、ia32、ia64、irix、irix64、mips、mips64、pa-risc、ppc、sparc、sparc64或undefined
可从 next/server 导入 userAgent:
import { userAgent } from 'next/server'import { NextRequest, NextResponse, userAgent } from 'next/server'
export function middleware(request: NextRequest) {
const url = request.nextUrl
const { device } = userAgent(request)
const viewport = device.type === 'mobile' ? 'mobile' : 'desktop'
url.searchParams.set('viewport', viewport)
return NextResponse.rewrite(url)
}常见问题
为什么 redirect 使用 307 和 308?
使用 redirect() 时,您可能会注意到临时重定向使用 307 状态码,永久重定向使用 308。传统上临时重定向使用 302,永久重定向使用 301,但许多浏览器在使用 302 时会将重定向请求方法从 POST 改为 GET,无论原始请求方法是什么。
以从 /users 重定向到 /people 为例,如果您向 /users 发送 POST 请求创建新用户,并遵循 302 临时重定向,请求方法将从 POST 变为 GET。这不符合逻辑,因为创建新用户应该向 /people 发送 POST 请求而非 GET。
引入 307 状态码意味着请求方法将保留为 POST。
302- 临时重定向,会将请求方法从POST改为GET307- 临时重定向,会保留请求方法为POST
redirect() 方法默认使用 307 而非 302 临时重定向,意味着您的请求将始终保留为 POST 方法。
如果您希望 POST 请求返回 GET 响应,请使用 303。
了解更多关于 HTTP 重定向的信息。
如何访问环境变量?
可通过 process.env 在边缘中间件中访问环境变量。这些变量在 next build 时被评估:
| 有效用法 | 无效用法 |
|---|---|
console.log(process.env.MY_ENV_VARIABLE) | const getEnv = name => process.env[name] |
const { MY_ENV_VARIABLE } = process.env | |
const { "MY-ENV-VARIABLE": MY_ENV_VARIABLE } = process.env |