NextRequest 與 NextResponse

next/server 提供專用於伺服器的輔助工具,可用於中介軟體邊緣 API 路由

NextRequest

NextRequest 物件是原生 Request 介面的擴展,新增了以下方法和屬性:

  • cookies - 一個 RequestCookies 實例,包含來自 Request 的 cookies。它讀取/修改請求的 Cookie 標頭。另請參閱在中介軟體中使用 cookies

    • get - 一個方法,接收 cookie name 並回傳包含 namevalue 的物件。如果找不到對應 name 的 cookie,則回傳 undefined。如果有多個 cookies 匹配,只會回傳第一個匹配項。
    • getAll - 類似 get 的方法,但回傳所有匹配 name 的 cookies 列表。如果未指定 name,則回傳所有可用的 cookies。
    • set - 一個方法,接收符合 W3C CookieStore API 規範的 CookieListItem 屬性物件。
    • delete - 一個方法,接收 cookie name 或名稱列表,並移除匹配名稱的 cookies。對於已刪除的 cookies 回傳 true,未刪除的回傳 false
    • has - 一個方法,接收 cookie name 並根據 cookie 是否存在回傳 booleantrue 表示存在,false 表示不存在)。
    • clear - 一個無參數方法,將有效移除 Cookie 標頭。
  • nextUrl: 包含一個擴展的、解析過的 URL 物件,可存取 Next.js 專用屬性,如 pathnamebasePathtrailingSlashi18n。包含以下屬性:

    • basePath (string)
    • buildId (string || undefined)
    • defaultLocale (string || undefined)
    • domainLocale
      • defaultLocale: (string)
      • domain: (string)
      • http: (boolean || undefined)
      • locales: (string[] || undefined)
    • locale (string || undefined)
    • url (URL)
  • ip: (string || undefined) - 包含 Request 的 IP 位址。此資訊由您的託管平台提供。

  • geo - 包含 Request 的地理位置資訊。此資訊由您的託管平台提供。包含以下屬性:

    • city (string || undefined)
    • country (string || undefined)
    • region (string || undefined)
    • latitude (string || undefined)
    • longitude (string || undefined)

您可以將 NextRequest 物件直接替代原生 Request 介面使用,從而更靈活地操作請求。

NextRequest 可從 next/server 導入:

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()
}

NextFetchEvent 物件可從 next/server 導入:

import type { NextFetchEvent } from 'next/server'

NextResponse

NextResponse 類別擴展了原生 Response 介面,具有以下功能:

公開方法

公開方法可在 NextResponse 類別的實例上使用。根據您的使用情境,您可以建立一個實例並賦值給變數,然後存取以下公開方法:

  • cookies - 一個 ResponseCookies 實例,包含來自 Response 的 cookies。它讀取/修改回應的 Set-Cookie 標頭。另請參閱在中介軟體中使用 cookies
    • get - 一個方法,接收 cookie name 並回傳包含 namevalue 的物件。如果找不到對應 name 的 cookie,則回傳 undefined。如果有多個 cookies 匹配,只會回傳第一個匹配項。
    • getAll - 類似 get 的方法,但回傳所有匹配 name 的 cookies 列表。如果未指定 name,則回傳所有可用的 cookies。
    • set - 一個方法,接收符合 W3C CookieStore API 規範的 CookieListItem 屬性物件。
    • delete - 一個方法,接收 cookie name 或名稱列表,並移除匹配名稱的 cookies。對於已刪除的 cookies 回傳 true,未刪除的回傳 false

靜態方法

以下靜態方法可直接在 NextResponse 類別上使用:

  • redirect() - 回傳一個設定重定向的 NextResponse
  • rewrite() - 回傳一個設定重寫的 NextResponse
  • next() - 回傳一個將繼續中介軟體鏈的 NextResponse

要使用上述方法,您必須回傳返回的 NextResponse 物件NextResponse 可從 next/server 導入:

import { NextResponse } from 'next/server'

userAgent

userAgent 輔助工具可讓您與請求中的使用者代理 (user agent) 物件互動。它是從原生 Request 物件抽象出來的,是一個可選功能。具有以下屬性:

  • isBot: (boolean) 請求是否來自已知的機器人
  • browser
    • name: (string || undefined) 瀏覽器名稱
    • version: (string || undefined) 瀏覽器版本,動態判斷
  • device
    • model: (string || undefined) 裝置型號,動態判斷
    • type: (string || undefined) 瀏覽器類型,可以是以下值之一:consolemobiletabletsmarttvwearableembeddedundefined
    • vendor: (string || undefined) 裝置供應商,動態判斷
  • engine
    • name: (string || undefined) 瀏覽器引擎名稱,可能是以下值之一:AmayaBlinkEdgeHTMLFlowGeckoGoannaiCabKHTMLLinksLynxNetFrontNetSurfPrestoTasmanTridentw3mWebKitundefined
    • version: (string || undefined) 瀏覽器引擎版本,動態判斷,或 undefined
  • os
    • name: (string || undefined) 作業系統名稱,可能是 undefined
    • version: (string || undefined) 作業系統版本,動態判斷,或 undefined
  • cpu
    • architecture: (string || undefined) CPU 架構,可能是以下值之一:68kamd64armarm64armhfavria32ia64irixirix64mipsmips64pa-riscppcsparcsparc64undefined

userAgent 可從 next/server 導入:

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 更改為 GET
  • 307 - 臨時重定向,會保留請求方法為 POST

redirect() 方法預設使用 307 而非 302 臨時重定向,這意味著您的請求將始終保留為 POST 請求。

如果您想讓 POST 請求回傳 GET 回應,請使用 303

了解更多關於 HTTP 重定向的資訊。

如何存取環境變數?

process.env 可用於從邊緣中介軟體 (Edge Middleware) 存取環境變數。它們會在 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

On this page