Route Handlers
路线处理程序
Route Handlers allow you to create custom request handlers for a given route using the Web Request and Response APIs.
路由处理程序允许您使用 Web 请求为给定路由创建自定义请求处理程序
和响应
蜜蜂。
Good to know: Route Handlers are only available inside the
app
directory. They are the equivalent of API Routes inside thepages
directory meaning you do not need to use API Routes and Route Handlers together.提示:路由处理程序仅在 app 目录内可用。它们相当于页面目录中的 API 路由,这意味着您不需要同时使用 API 路由和路由处理程序。
Convention
习俗
Route Handlers are defined in a route.js|ts
file inside the app
directory:
路由处理程序在 app 目录内的 route.js|ts 文件中定义:
app/api/route.ts
TypeScript
export async function GET(request: Request) {}
Route Handlers can be nested inside the app
directory, similar to page.js
and layout.js
. But there cannot be a route.js
file at the same route segment level as page.js
.
Route Handlers 可以嵌套在 app 目录中,类似于 page.js 和 layout.js。但是不能有和page.js同级的route.js文件。
Supported HTTP Methods
支持的 HTTP 方法
The following HTTP methods are supported: GET
, POST
, PUT
, PATCH
, DELETE
, HEAD
, and OPTIONS
. If an unsupported method is called, Next.js will return a 405 Method Not Allowed
response.
以下 HTTP 方法
支持:GET、POST、PUT、PATCH、DELETE、HEAD 和 OPTIONS。如果调用了不受支持的方法,Next.js 将返回 405 Method Not Allowed 响应。
Extended NextRequest
and NextResponse
APIs
扩展的 NextRequest 和 NextResponse API
In addition to supporting native Request and Response. Next.js extends them with NextRequest
and NextResponse
to provide convenient helpers for advanced use cases.
除了支持原生的Request
和响应
. Next.js 使用 NextRequest 和 NextResponse 扩展它们,为高级用例提供方便的帮助程序。
Behavior
行为
Static Route Handlers
静态路由处理程序
Route Handlers are statically evaluated by default when using the GET
method with the Response
object.
将 GET 方法与 Response 对象一起使用时,默认情况下会静态评估路由处理程序。
app/items/route.ts
TypeScript
import { NextResponse } from 'next/server'; export async function GET() { const res = await fetch('https://data.mongodb-api.com/...', { headers: { 'Content-Type': 'application/json', 'API-Key': process.env.DATA_API_KEY, }, }); const data = await res.json(); return NextResponse.json({ data });}
TypeScript Warning: Although
Response.json()
is valid, native TypeScript types currently shows an error, you can useNextResponse.json()
for typed responses instead.TypeScript 警告:尽管 Response.json() 有效,但原生 TypeScript 类型当前显示错误,您可以使用 NextResponse.json() 代替类型化响应。
Dynamic Route Handlers
动态路由处理程序
Route handlers are evaluated dynamically when:
在以下情况下会动态评估路由处理程序:
- Using the
Request
object with theGET
method. - 使用带有 GET 方法的 Request 对象。
- Using any of the other HTTP methods.
- 使用任何其他 HTTP 方法。
- Using Dynamic Functions like
cookies
andheaders
. - 使用 cookie 和标头等动态功能。
- The Segment Config Options manually specifies dynamic mode.
- Segment Config Options 手动指定动态模式。
For example:
例如:
app/products/api/route.ts
TypeScript
import { NextResponse } from 'next/server'; export async function GET(request: Request) { const { searchParams } = new URL(request.url); const id = searchParams.get('id'); const res = await fetch(`https://data.mongodb-api.com/product/${id}`, { headers: { 'Content-Type': 'application/json', 'API-Key': process.env.DATA_API_KEY, }, }); const product = await res.json(); return NextResponse.json({ product });}
Similarly, the POST
method will cause the Route Handler to be evaluated dynamically.
同样,POST 方法将导致路由处理程序被动态评估。
app/items/route.ts
TypeScript
import { NextResponse } from 'next/server'; export async function GET() { const res = await fetch('https://data.mongodb-api.com/...', { headers: { 'Content-Type': 'application/json', 'API-Key': process.env.DATA_API_KEY, }, }); const data = await res.json(); return NextResponse.json({ data });}
注意:以前,API 路由可以用于处理表单提交等用例。路由处理程序可能不是这些用例的解决方案。准备就绪后,我们将建议为此使用突变。
Route Resolution
路由解析
You can consider a route
the lowest level routing primitive.
您可以将路由视为最低级别的路由原语。
- They do not participate in layouts or client-side navigations like
page
. - 他们不参与页面布局或客户端导航。
- There cannot be a
route.js
file at the same route aspage.js
. - route.js 文件不能与 page.js 位于同一路径。
Page | Route | Result |
app/page.js |
app/route.js |
Conflict |
app/page.js |
app/api/route.js |
Valid |
app/[user]/page.js |
app/api/route.js |
Valid |
Each route.js
or page.js
file takes over all HTTP verbs for that route.
每个 route.js 或 page.js 文件接管该路由的所有 HTTP 动词。
app/page.js
javascript
复制代码
exportdefaultfunctionPage() { return<h1>Hello, Next.js!</h1>;} // ❌ Conflict// `app/route.js`export async function POST(request) {}
Examples
例子
The following examples show how to combine Route Handlers with other Next.js APIs and features.
以下示例展示了如何将路由处理程序与其他 Next.js API 和功能相结合。
Revalidating Static Data
重新验证静态数据
You can revalidate static data fetches using the next.revalidate
option:
您可以重新验证静态数据
使用 next.revalidate 选项获取:
app/items/route.ts
TypeScript
javascript
复制代码
import { NextResponse } from'next/server'; exportasyncfunctionGET() { const res = awaitfetch('https://data.mongodb-api.com/...', { next: { revalidate: 60 }, // Revalidate every 60 seconds }); const data = await res.json(); return NextResponse.json(data);}
Alternatively, you can use the revalidate
segment config option:
或者,您可以使用 revalidate segment 配置选项:
ini
export const revalidate = 60;
Dynamic Functions
动态函数
Route Handlers can be used with dynamic functions from Next.js, like cookies
and headers
.
路由处理程序可以与来自 Next.js 的动态函数一起使用,例如 cookie 和标头。
Cookies
饼干
You can read cookies with cookies
from next/headers
. This server function can be called directly in a Route Handler, or nested inside of another function.
您可以从 next/headers 读取带有 cookie 的 cookie。这个服务器函数可以直接在路由处理程序中调用,也可以嵌套在另一个函数中。
This cookies
instance is read-only. To set cookies, you need to return a new Response
using the Set-Cookie
header.
此 cookie 实例是只读的。要设置 cookie,您需要使用 Set-Cookie 返回一个新的 Response
标头。
app/api/route.ts
TypeScript
import { cookies } from 'next/headers'; export async function GET(request: Request) { const cookieStore = cookies(); const token = cookieStore.get('token'); return new Response('Hello, Next.js!', { status: 200, headers: { 'Set-Cookie': `token=${token}` }, });}
Alternatively, you can use abstractions on top of the underlying Web APIs to read cookies (NextRequest
):
或者,您可以在底层 Web API 之上使用抽象来读取 cookie (NextRequest):
app/api/route.ts
TypeScript
import { type NextRequest } from 'next/server'; export async function GET(request: NextRequest) { const token = request.cookies.get('token');}
Headers
标头
You can read headers with headers
from next/headers
. This server function can be called directly in a Route Handler, or nested inside of another function.
您可以从 next/headers 中读取带有标题的标题。这个服务器函数可以直接在路由处理程序中调用,也可以嵌套在另一个函数中。
This headers
instance is read-only. To set headers, you need to return a new Response
with new headers
.
此标头实例是只读的。要设置标头,您需要返回带有新标头的新响应。
app/api/route.ts
TypeScript
import { headers } from 'next/headers'; export async function GET(request: Request) { const headersList = headers(); const referer = headersList.get('referer'); return new Response('Hello, Next.js!', { status: 200, headers: { referer: referer }, });}
Alternatively, you can use abstractions on top of the underlying Web APIs to read headers (NextRequest
):
或者,您可以在底层 Web API 之上使用抽象来读取标头 (NextRequest):
app/api/route.ts
TypeScript
import { type NextRequest } from 'next/server'; export async function GET(request: NextRequest) { const requestHeaders = new Headers(request.headers);}
Redirects
重定向
app/api/route.ts
TypeScript
import { redirect } from 'next/navigation'; export async function GET(request: Request) { redirect('https://nextjs.org/');} Dynamic Route Segments
动态路线段
We recommend reading the Defining Routes page before continuing.
我们建议在继续之前阅读定义路由页面。
Route Handlers can use Dynamic Segments to create request handlers from dynamic data.
Route Handlers 可以使用 Dynamic Segments 从动态数据创建请求处理程序。
app/items/[slug]/route.js
export async function GET( request: Request, { params, }: { params: { slug: string }; },) { const slug = params.slug; // 'a', 'b', or 'c'}
Route | Example URL | params |
app/items/[slug]/route.js |
/items/a |
{ slug: 'a' } |
app/items/[slug]/route.js |
/items/b |
{ slug: 'b' } |
app/items/[slug]/route.js |
/items/c |
{ slug: 'c' } |
Streaming
串流
app/api/route.ts
TypeScript
lua
// https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream#convert_async_iterator_to_streamfunction iteratorToStream(iterator: any) { return new ReadableStream({ async pull(controller) { const { value, done } = await iterator.next(); if (done) { controller.close(); } else { controller.enqueue(value); } }, });} function sleep(time: number) { return new Promise((resolve) => { setTimeout(resolve, time); });} const encoder = new TextEncoder(); async function* makeIterator() { yield encoder.encode('<p>One</p>'); await sleep(200); yield encoder.encode('<p>Two</p>'); await sleep(200); yield encoder.encode('<p>Three</p>');} export async function GET() { const iterator = makeIterator(); const stream = iteratorToStream(iterator); return new Response(stream);}
Request Body
请求正文
You can read the Request
body using the standard Web API methods:
您可以使用标准 Web API 方法读取请求正文:
app/items/route.ts
TypeScript
import { NextResponse } from 'next/server'; export async function POST(request: Request) { const res = await request.json(); return NextResponse.json({ res });}
CORS
You can set CORS headers on a Response
using the standard Web API methods:
您可以使用标准 Web API 方法在响应上设置 CORS 标头:
app/api/route.ts
TypeScript
export async function GET(request: Request) { return new Response('Hello, Next.js!', { status: 200, headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization', }, });} Edge and Node.js Runtimes
Edge 和 Node.js 运行时
Route Handlers have an isomorphic Web API to support both Edge and Node.js runtimes seamlessly, including support for streaming. Since Route Handlers use the same route segment configuration as pages and layouts, they support long-awaited features like general-purpose statically regenerated Route Handlers.
Route Handlers 有一个同构的 Web API 来无缝支持 Edge 和 Node.js 运行时,包括对流的支持。由于路由处理程序使用与页面和布局相同的路由段配置,因此它们支持期待已久的功能,如通用静态重新生成的路由处理程序。
You can use the runtime
segment config option to specify the runtime:
您可以使用运行时段配置选项来指定运行时:
arduino
export const runtime = 'edge'; // 'nodejs' is the default
Non-UI Responses
非 UI 响应
You can use Route Handlers to return non-UI content. Note that sitemap.xml
, robots.txt
, favicon.ico
, and open graph images all have built-in SEO support.
您可以使用路由处理程序返回非 UI 内容。请注意,sitemap.xml、robots.txt、favicon.ico 和开放图形图像都具有内置的 SEO 支持。
app/rss.xml/route.ts
TypeScript
xml
export async function GET() { return new Response(`<?xml version="1.0" encoding="UTF-8" ?><rss version="2.0"> <channel> <title>Next.js Documentation</title> <link>https://nextjs.org/docs</link> <description>The React Framework for the Web</description></channel> </rss>`);} Segment Config Options
段配置选项
Route Handlers use the same route segment configuration as pages and layouts.
路由处理程序使用与页面和布局相同的路由段配置。
app/items/route.ts
TypeScript
dart
export const dynamic = 'auto';export const dynamicParams = true;export const revalidate = false;export const fetchCache = 'auto';export const runtime = 'nodejs';export const preferredRegion = 'auto'; See the API reference for more details.
有关详细信息,请参阅 API 参考。
Middleware
中间件
Middleware allows you to run code before a request is completed. Then, based on the incoming request, you can modify the response by rewriting, redirecting, modifying the request or response headers, or responding directly.
中间件允许您在请求完成之前运行代码。然后,根据传入的请求,您可以通过重写、重定向、修改请求或响应标头或直接响应来修改响应。
Middleware runs before cached content and routes are matched. See Matching Paths for more details.
中间件在缓存内容和路由匹配之前运行。有关详细信息,请参阅匹配路径。
Convention
习俗
Use the file middleware.ts
(or .js
) in the root of your project to define Middleware. For example, at the same level as pages
or app
, or inside src
if applicable.
使用项目根目录中的文件 middleware.ts(或 .js)来定义中间件。例如,与页面或应用处于同一级别,或者在 src 内部(如果适用)。