API 路由
API 路由提供了一個使用 Next.js 建置公開 API 的解決方案。
pages/api
資料夾內的任何檔案都會對應到 /api/*
,並將被視為 API 端點而不是 page
。它們是僅限伺服器端的捆綁包,不會增加您的用戶端捆綁包大小。
例如,以下 API 路由會傳回狀態碼為 200
的 JSON 回應
import type { NextApiRequest, NextApiResponse } from 'next'
type ResponseData = {
message: string
}
export default function handler(
req: NextApiRequest,
res: NextApiResponse<ResponseData>
) {
res.status(200).json({ message: 'Hello from Next.js!' })
}
要知道的好處:
- API 路由未指定 CORS 標頭,表示它們預設為僅限同源。您可以透過使用 CORS 請求輔助程式包裝請求處理器來自訂此行為。
- API 路由不能與靜態匯出一起使用。但是,App Router 中的路由處理器可以。
- API 路由將會受到
next.config.js
中的pageExtensions
設定影響。
- API 路由將會受到
參數
export default function handler(req: NextApiRequest, res: NextApiResponse) {
// ...
}
req
:http.IncomingMessage 的實例res
:http.ServerResponse 的實例
HTTP 方法
若要在 API 路由中處理不同的 HTTP 方法,您可以在請求處理器中使用 req.method
,如下所示
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'POST') {
// Process a POST request
} else {
// Handle any other HTTP method
}
}
請求輔助程式
API 路由提供內建的請求輔助程式,可剖析傳入的請求 (req
)
req.cookies
- 包含請求傳送的 Cookie 的物件。預設為{}
req.query
- 包含查詢字串的物件。預設為{}
req.body
- 包含由content-type
剖析的內文的物件,如果未傳送內文,則為null
自訂設定
每個 API 路由都可以匯出 config
物件來變更預設設定,預設設定如下
export const config = {
api: {
bodyParser: {
sizeLimit: '1mb',
},
},
// Specifies the maximum allowed duration for this function to execute (in seconds)
maxDuration: 5,
}
bodyParser
會自動啟用。如果您想要將內文作為 Stream
或使用 raw-body
取用,您可以將其設定為 false
。
停用自動 bodyParsing
的一個用例是讓您驗證 webhook 請求的原始內文,例如來自 GitHub。
export const config = {
api: {
bodyParser: false,
},
}
bodyParser.sizeLimit
是允許剖析的內文的最大大小,以 bytes 支援的任何格式表示,如下所示
export const config = {
api: {
bodyParser: {
sizeLimit: '500kb',
},
},
}
externalResolver
是一個明確的標誌,告知伺服器此路由正由外部解析器(如 express 或 connect)處理。啟用此選項會停用未解析請求的警告。
export const config = {
api: {
externalResolver: true,
},
}
responseLimit
會自動啟用,當 API 路由的回應內文超過 4MB 時發出警告。
如果您未使用伺服器環境中的 Next.js,並且了解不使用 CDN 或專用媒體主機的效能影響,您可以將此限制設定為 false
。
export const config = {
api: {
responseLimit: false,
},
}
responseLimit
也可以採用位元組數或 bytes
支援的任何字串格式,例如 1000
、'500kb'
或 '3mb'
。此值將是顯示警告前的最大回應大小。預設值為 4MB。(請參閱上方)
export const config = {
api: {
responseLimit: '8mb',
},
}
回應輔助程式
伺服器回應物件(通常縮寫為 res
)包含一組類似 Express.js 的輔助方法,以改善開發人員體驗並提高建立新 API 端點的速度。
包含的輔助程式為
res.status(code)
- 設定狀態碼的函數。code
必須是有效的HTTP 狀態碼res.json(body)
- 傳送 JSON 回應。body
必須是可序列化的物件res.send(body)
- 傳送 HTTP 回應。body
可以是string
、object
或Buffer
res.redirect([status,] path)
- 重新導向至指定的路徑或 URL。status
必須是有效的HTTP 狀態碼。如果未指定,status
預設為 "307" "暫時重新導向"。res.revalidate(urlPath)
- 使用getStaticProps
依需求重新驗證頁面。urlPath
必須是string
。
設定回應的狀態碼
當將回應傳送回用戶端時,您可以設定回應的狀態碼。
以下範例將回應的狀態碼設定為 200
(OK
),並傳回具有值為 Hello from Next.js!
的 message
屬性作為 JSON 回應
import type { NextApiRequest, NextApiResponse } from 'next'
type ResponseData = {
message: string
}
export default function handler(
req: NextApiRequest,
res: NextApiResponse<ResponseData>
) {
res.status(200).json({ message: 'Hello from Next.js!' })
}
傳送 JSON 回應
當將回應傳送回用戶端時,您可以傳送 JSON 回應,這必須是可序列化的物件。在真實世界的應用程式中,您可能想要根據請求端點的結果,讓用戶端知道請求的狀態。
以下範例傳送狀態碼為 200
(OK
) 的 JSON 回應以及非同步操作的結果。它包含在 try catch 區塊中,以處理可能發生的任何錯誤,並捕獲適當的狀態碼和錯誤訊息並傳送回用戶端
import type { NextApiRequest, NextApiResponse } from 'next'
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
try {
const result = await someAsyncOperation()
res.status(200).json({ result })
} catch (err) {
res.status(500).json({ error: 'failed to load data' })
}
}
傳送 HTTP 回應
傳送 HTTP 回應的方式與傳送 JSON 回應的方式相同。唯一的區別在於回應內文可以是 string
、object
或 Buffer
。
以下範例傳送狀態碼為 200
(OK
) 的 HTTP 回應以及非同步操作的結果。
import type { NextApiRequest, NextApiResponse } from 'next'
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
try {
const result = await someAsyncOperation()
res.status(200).send({ result })
} catch (err) {
res.status(500).send({ error: 'failed to fetch data' })
}
}
重新導向至指定的路徑或 URL
以表單為例,您可能希望在用戶端提交表單後將其重新導向至指定的路徑或 URL。
以下範例會在表單成功提交後將用戶端重新導向至 /
路徑
import type { NextApiRequest, NextApiResponse } from 'next'
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const { name, message } = req.body
try {
await handleFormInputAsync({ name, message })
res.redirect(307, '/')
} catch (err) {
res.status(500).send({ error: 'Failed to fetch data' })
}
}
新增 TypeScript 類型
您可以從 next
匯入 NextApiRequest
和 NextApiResponse
類型,讓您的 API 路由更具類型安全性,此外,您也可以為您的回應資料輸入類型
import type { NextApiRequest, NextApiResponse } from 'next'
type ResponseData = {
message: string
}
export default function handler(
req: NextApiRequest,
res: NextApiResponse<ResponseData>
) {
res.status(200).json({ message: 'Hello from Next.js!' })
}
要知道的好處:
NextApiRequest
的內文是any
,因為用戶端可能包含任何酬載。您應該在使用內文之前,在執行階段驗證內文的類型/形狀。
動態 API 路由
API 路由支援動態路由,並遵循用於 pages/
的相同檔案命名規則。
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) {
const { pid } = req.query
res.end(`Post: ${pid}`)
}
現在,對 /api/post/abc
的請求將會回應文字:Post: abc
。
捕捉所有 API 路由
API 路由可以擴展為透過在括號內新增三個點 (...
) 來捕捉所有路徑。例如
pages/api/post/[...slug].js
符合/api/post/a
,但也符合/api/post/a/b
、/api/post/a/b/c
等等。
要知道的好處:您可以使用
slug
以外的名稱,例如:[...param]
相符的參數將作為查詢參數(範例中為 slug
)傳送至頁面,而且它永遠會是一個陣列,因此路徑 /api/post/a
將具有以下 query
物件
{ "slug": ["a"] }
在 /api/post/a/b
和任何其他相符路徑的情況下,新的參數將會新增至陣列,如下所示
{ "slug": ["a", "b"] }
例如
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) {
const { slug } = req.query
res.end(`Post: ${slug.join(', ')}`)
}
現在,對 /api/post/a/b/c
的請求將會回應文字:Post: a, b, c
。
可選的捕捉所有 API 路由
捕捉所有路由可以透過將參數包含在雙括號 ([[...slug]]
) 中來設為可選。
例如,pages/api/post/[[...slug]].js
將會符合 /api/post
、/api/post/a
、/api/post/a/b
等等。
捕捉所有路由和可選的捕捉所有路由之間的主要區別在於,對於可選的捕捉所有路由,不帶參數的路由也會符合(在上面的範例中為 /api/post
)。
query
物件如下
{ } // GET `/api/post` (empty object)
{ "slug": ["a"] } // `GET /api/post/a` (single-element array)
{ "slug": ["a", "b"] } // `GET /api/post/a/b` (multi-element array)
注意事項
- 預先定義的 API 路由優先於動態 API 路由,而動態 API 路由優先於捕捉所有 API 路由。查看以下範例
pages/api/post/create.js
- 將會符合/api/post/create
pages/api/post/[pid].js
- 將會符合/api/post/1
、/api/post/abc
等等。但不會符合/api/post/create
pages/api/post/[...slug].js
- 將會符合/api/post/1/2
、/api/post/a/b/c
等等。但不會符合/api/post/create
、/api/post/abc
Edge API 路由
如果您想要搭配 Edge Runtime 使用 API 路由,我們建議逐步採用 App Router 並改用路由處理器。
路由處理器函數簽名是同構的,這表示您可以對 Edge 和 Node.js 執行階段使用相同的函數。
這有幫助嗎?