Skip to content

route.js

路由处理程序允许你使用 Web 请求响应 API 为给定路由创建自定义请求处理程序。

¥Route Handlers allow you to create custom request handlers for a given route using the Web Request and Response APIs.

ts
export async function GET() {
  return Response.json({ message: 'Hello World' })
}

参考

¥Reference

HTTP 方法

¥HTTP Methods

路由文件允许你为给定路由创建自定义请求处理程序。支持以下 HTTP 方法GETPOSTPUTPATCHDELETEHEADOPTIONS

¥A route file allows you to create custom request handlers for a given route. The following HTTP methods are supported: GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS.

ts
export async function GET(request: Request) {}

export async function HEAD(request: Request) {}

export async function POST(request: Request) {}

export async function PUT(request: Request) {}

export async function DELETE(request: Request) {}

export async function PATCH(request: Request) {}

// If `OPTIONS` is not defined, Next.js will automatically implement `OPTIONS` and set the appropriate Response `Allow` header depending on the other methods defined in the Route Handler.
export async function OPTIONS(request: Request) {}

参数

¥Parameters

request(可选)

¥request (optional)

request 对象是 NextRequest 对象,它是 Web 请求 API 的扩展。NextRequest 使你可以进一步控制传入请求,包括轻松访问 cookies 和扩展的、已解析的 URL 对象 nextUrl

¥The request object is a NextRequest object, which is an extension of the Web Request API. NextRequest gives you further control over the incoming request, including easily accessing cookies and an extended, parsed, URL object nextUrl.

ts
import type { NextRequest } from 'next/server'

export async function GET(request: NextRequest) {
  const url = request.nextUrl
}

context(可选)

¥context (optional)

ts
export async function GET(
  request: Request,
  { params }: { params: Promise<{ team: string }> }
) {
  const { team } = await params
}
示例URLparams
app/dashboard/[team]/route.js/dashboard/1Promise<{ team: '1' }>
app/shop/[tag]/[item]/route.js/shop/1/2Promise<{ tag: '1', item: '2' }>
app/blog/[...slug]/route.js/blog/1/2Promise<{ slug: ['1', '2'] }>

示例

¥Examples

Cookies

你可以从 next/headers 读取或设置 cookies 的 cookie。

¥You can read or set cookies with cookies from next/headers.

ts
import { cookies } from 'next/headers'

export async function GET(request: NextRequest) {
  const cookieStore = await cookies()

  const a = cookieStore.get('a')
  const b = cookieStore.set('b', '1')
  const c = cookieStore.delete('c')
}

或者,你可以使用 Set-Cookie 标头返回新的 Response

¥Alternatively, you can return a new Response using the Set-Cookie header.

ts
import { cookies } from 'next/headers'

export async function GET(request: Request) {
  const cookieStore = await cookies()
  const token = cookieStore.get('token')

  return new Response('Hello, Next.js!', {
    status: 200,
    headers: { 'Set-Cookie': `token=${token.value}` },
  })
}

你还可以使用底层 Web API 从请求中读取 cookie (NextRequest):

¥You can also use the underlying Web APIs to read cookies from the request (NextRequest):

ts
import { type NextRequest } from 'next/server'

export async function GET(request: NextRequest) {
  const token = request.cookies.get('token')
}

标头

¥Headers

你可以从 next/headers 读取带有 headers 的标头。

¥You can read headers with headers from next/headers.

ts
import { headers } from 'next/headers'
import type { NextRequest } from 'next/server'

export async function GET(request: NextRequest) {
  const headersList = await headers()
  const referer = headersList.get('referer')
}

headers 实例是只读的。要设置标头,你需要返回新的 Response 和新的 headers

¥This headers instance is read-only. To set headers, you need to return a new Response with new headers.

ts
import { headers } from 'next/headers'

export async function GET(request: Request) {
  const headersList = await headers()
  const referer = headersList.get('referer')

  return new Response('Hello, Next.js!', {
    status: 200,
    headers: { referer: referer },
  })
}

你还可以使用底层 Web API 从请求中读取标头 (NextRequest):

¥You can also use the underlying Web APIs to read headers from the request (NextRequest):

ts
import { type NextRequest } from 'next/server'

export async function GET(request: NextRequest) {
  const requestHeaders = new Headers(request.headers)
}

重新验证缓存数据

¥Revalidating Cached Data

你可以使用 revalidate 路由段配置选项进行 重新验证缓存数据

¥You can revalidate cached data using the revalidate route segment config option.

ts
export const revalidate = 60

export async function GET() {
  const data = await fetch('https://api.vercel.app/blog')
  const posts = await data.json()

  return Response.json(posts)
}

重定向

¥Redirects

ts
import { redirect } from 'next/navigation'

export async function GET(request: Request) {
  redirect('https://next.nodejs.cn/')
}

动态路由片段

¥Dynamic Route Segments

路由处理程序可以使用 动态片段 从动态数据创建请求处理程序。

¥Route Handlers can use Dynamic Segments to create request handlers from dynamic data.

ts
export async function GET(
  request: Request,
  { params }: { params: Promise<{ slug: string }> }
) {
  const { slug } = await params // 'a', 'b', or 'c'
}
路由示例 URLparams
app/items/[slug]/route.js/items/aPromise<{ slug: 'a' }>
app/items/[slug]/route.js/items/bPromise<{ slug: 'b' }>
app/items/[slug]/route.js/items/cPromise<{ slug: 'c' }>

URL 查询参数

¥URL Query Parameters

传递给路由处理程序的请求对象是一个 NextRequest 实例,其中包含 一些额外的便利方法,例如用于更轻松地处理查询参数的 一些额外的便利方法

¥The request object passed to the Route Handler is a NextRequest instance, which includes some additional convenience methods, such as those for more easily handling query parameters.

ts
import { type NextRequest } from 'next/server'

export function GET(request: NextRequest) {
  const searchParams = request.nextUrl.searchParams
  const query = searchParams.get('query')
  // query is "hello" for /api/search?query=hello
}

流式

¥Streaming

流式通常与大型语言模型 (LLM)(例如 OpenAI)结合使用,用于 AI 生成的内容。了解有关 AI SDK 的更多信息。

¥Streaming is commonly used in combination with Large Language Models (LLMs), such as OpenAI, for AI-generated content. Learn more about the AI SDK.

ts
import { openai } from '@ai-sdk/openai'
import { StreamingTextResponse, streamText } from 'ai'

export async function POST(req: Request) {
  const { messages } = await req.json()
  const result = await streamText({
    model: openai('gpt-4-turbo'),
    messages,
  })

  return new StreamingTextResponse(result.toAIStream())
}

这些抽象使用 Web API 来创建流。你还可以直接使用底层 Web API。

¥These abstractions use the Web APIs to create a stream. You can also use the underlying Web APIs directly.

ts
// https://web.nodejs.cn/docs/Web/API/ReadableStream#convert_async_iterator_to_stream
function 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

你可以使用标准 Web API 方法读取 Request 正文:

¥You can read the Request body using the standard Web API methods:

ts
export async function POST(request: Request) {
  const res = await request.json()
  return Response.json({ res })
}

请求主体表单数据

¥Request Body FormData

你可以使用 request.formData() 函数读取 FormData

¥You can read the FormData using the request.formData() function:

ts
export async function POST(request: Request) {
  const formData = await request.formData()
  const name = formData.get('name')
  const email = formData.get('email')
  return Response.json({ name, email })
}

由于 formData 数据都是字符串,因此你可能希望使用 zod-form-data 来验证请求并以你喜欢的格式检索数据(例如 number)。

¥Since formData data are all strings, you may want to use zod-form-data to validate the request and retrieve data in the format you prefer (e.g. number).

CORS

你可以使用标准 Web API 方法为特定路由处理程序设置 CORS 标头:

¥You can set CORS headers for a specific Route Handler using the standard Web API methods:

ts
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',
    },
  })
}

需要了解:

¥Good to know:

Webhook

你可以使用路由处理程序从第三方服务接收 webhook:

¥You can use a Route Handler to receive webhooks from third-party services:

ts
export async function POST(request: Request) {
  try {
    const text = await request.text()
    // Process the webhook payload
  } catch (error) {
    return new Response(`Webhook error: ${error.message}`, {
      status: 400,
    })
  }

  return new Response('Success!', {
    status: 200,
  })
}

值得注意的是,与页面路由的 API 路由不同,你不需要使用 bodyParser 来使用任何其他配置。

¥Notably, unlike API Routes with the Pages Router, you do not need to use bodyParser to use any additional configuration.

非 UI 响应

¥Non-UI Responses

你可以使用路由处理程序返回非 UI 内容。请注意,sitemap.xmlrobots.txtapp icons打开图形图片 都有内置支持。

¥You can use Route Handlers to return non-UI content. Note that sitemap.xml, robots.txt, app icons, and open graph images all have built-in support.

ts
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://next.nodejs.cn/docs</link>
  <description>The React Framework for the Web</description>
</channel>

</rss>`,
    {
      headers: {
        'Content-Type': 'text/xml',
      },
    }
  )
}

片段配置选项

¥Segment Config Options

路由处理程序使用与页面和布局相同的 路由段配置

¥Route Handlers use the same route segment configuration as pages and layouts.

ts
export const dynamic = 'auto'
export const dynamicParams = true
export const revalidate = false
export const fetchCache = 'auto'
export const runtime = 'nodejs'
export const preferredRegion = 'auto'

有关详细信息,请参阅 API 参考

¥See the API reference for more details.

版本历史

¥Version History

版本更改
v15.0.0-RCcontext.params 现在是一个 promise。codemod 可用
v15.0.0-RCGET 处理程序的默认缓存已从静态更改为动态
v13.2.0引入路由处理程序。