API 路由
API 路由提供了一种使用 Next.js 构建公共 API的解决方案。
pages/api
文件夹内的任何文件都映射到 /api/*
,并将被视为 API 端点而不是页面
。它们仅是服务器端捆绑包,不会增加客户端捆绑包的大小。
例如,以下 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 响应,这必须是可序列化对象。在实际应用中,您可能希望根据请求端点的结果让客户端知道请求的状态。
以下示例发送一个 JSON 响应,其中包含状态码 200
(OK
)和异步操作的结果。它包含在一个 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
。
以下示例发送一个 HTTP 响应,其中包含状态码 200
(OK
)和异步操作的结果。
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 路由
如果您想将 API 路由与 Edge Runtime 一起使用,我们建议逐步采用 App Router 并使用路由处理器。
路由处理器函数签名是同构的,这意味着您可以对 Edge 和 Node.js 运行时使用相同的函数。
这有帮助吗?