Обработчики маршрутов
Обработчики маршрутов позволяют создавать пользовательские обработчики запросов для заданного маршрута, используя API веб-запросов Request и Response.


Важно знать: Обработчики маршрутов доступны только внутри каталога
app. Они эквивалентны маршрутам API маршрутов API внутри каталогаpages, что означает, что вам не нужно использовать маршруты API и обработчики маршрутов вместе.
Конвенция
Обработчики маршрутов определяются в файле route.js|ts внутри каталога app.
export const dynamic = 'force-dynamic' // defaults to auto
export async function GET(request: Request) {}Обработчики маршрутов могут быть вложены внутри каталога app, аналогично page.js и layout.js. Но не должно быть файла route.js на одном уровне маршрута с файлом page.js.
Поддерживаемые HTTP-методы
Поддерживаются следующие HTTP-методы: GET, POST, PUT, PATCH, DELETE, HEAD, и OPTIONS. Если используется неподдерживаемый метод, Next.js вернёт ответ 405 Method Not Allowed.
Расширенные API NextRequest и NextResponse
Помимо поддержки стандартных API Request и Response. Next.js расширяет их с помощью NextRequest и NextResponse для предоставления удобных помощников для сложных случаев использования.
Поведение
Кэширование
Обработчики маршрутов кэшируются по умолчанию при использовании метода GET с объектом Response.
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 Response.json({ data })
}Предупреждение для TypeScript:
Response.json()действителен только начиная с TypeScript 5.2. Если вы используете более раннюю версию TypeScript, вы можете использоватьNextResponse.json()для типизированных ответов.
Отключение кэширования
Вы можете отключить кэширование, используя:
- Объект
Requestс методомGET. - Любой другой HTTP-метод.
- Использование динамических функций, таких как
cookiesиheaders. - Раздел конфигурации сегмента (Segment Config Options) вручную указывает динамический режим.
Например:
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 Response.json({ product })
}Аналогично, метод POST заставит обработчик маршрута оцениваться динамически.
export async function POST() {
const res = await fetch('https://data.mongodb-api.com/...', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'API-Key': process.env.DATA_API_KEY!,
},
body: JSON.stringify({ time: new Date().toISOString() }),
})
const data = await res.json()
return Response.json(data)
}Важно знать: Как и маршруты API, обработчики маршрутов могут использоваться для обработки таких случаев, как обработка отправки форм. Разрабатывается новая абстракция для обработки форм и мутаций, которая глубоко интегрируется с React.
Разрешение маршрута
Вы можете рассматривать обработчик маршрута как примитив маршрутизации низкого уровня.
- Они не участвуют в макетах или клиентской навигации, таких как
page. - Не может быть файла
route.jsна одном маршруте с файломpage.js.
| Страница | Маршрут | Результат |
|---|---|---|
app/page.js |
app/route.js |
Конфликт |
app/page.js |
app/api/route.js |
Валидно |
app/[user]/page.js |
app/api/route.js |
Валидно |
Каждый файл route.js или page.js обрабатывает все HTTP-глаголы для данного маршрута.
export default function Page() {
return <h1>Hello, Next.js!</h1>
}
// ❌ Conflict
// `app/route.js`
export async function POST(request) {}Примеры
В следующих примерах показано, как комбинировать обработчики маршрутов с другими API и функциями Next.js.
Перепроверка кэшированных данных
Вы можете перепроверить кэшированные данные с помощью параметра next.revalidate:
export async function GET() {
const res = await fetch('https://data.mongodb-api.com/...', {
next: { revalidate: 60 }, // Revalidate every 60 seconds
})
const data = await res.json()
return Response.json(data)
}В качестве альтернативы, вы можете использовать параметр конфигурации сегмента revalidate:
export const revalidate = 60
Динамические функции
Обработчики маршрутов могут использоваться с динамическими функциями Next.js, такими как cookies и headers.
Куки
Вы можете читать или устанавливать куки с помощью cookies из next/headers. Эту серверную функцию можно вызывать непосредственно в обработчике маршрута или внутри другой функции.
В качестве альтернативы, вы можете вернуть новые Response используя заголовок Set-Cookie.
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.value}` },
})
}Вы также можете использовать основные веб-API для чтения куков из запроса (NextRequest):
import { type NextRequest } from 'next/server'
export async function GET(request: NextRequest) {
const token = request.cookies.get('token')
}Заголовки
Вы можете читать заголовки с помощью headers из next/headers. Эту серверную функцию можно вызывать непосредственно в обработчике маршрута или внутри другой функции.
Этот объект headers является только для чтения. Для установки заголовков вам необходимо вернуть новый объект Response с новыми headers.
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 },
})
}Вы также можете использовать основные веб-API для чтения заголовков из запроса (NextRequest):
import { type NextRequest } from 'next/server'
export async function GET(request: NextRequest) {
const requestHeaders = new Headers(request.headers)
}Перенаправления
import { redirect } from 'next/navigation'
export async function GET(request: Request) {
redirect('https://nextjs.org/')
}Динамические сегменты маршрута
Перед продолжением рекомендуем прочитать страницу Определения маршрутов.
Обработчики маршрутов могут использовать Динамические сегменты для создания обработчиков запросов из динамических данных.
export async function GET(
request: Request,
{ params }: { params: { slug: string } }
) {
const slug = params.slug // 'a', 'b', or 'c'
}| Маршрут | Пример 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' } |
Параметры запроса URL
Объект запроса, передаваемый обработчику маршрута, является экземпляром NextRequest с некоторыми дополнительными удобными методами, включая более удобную обработку параметров запроса.
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
}Потоковая передача
Потоковая передача обычно используется в сочетании с большими языковыми моделями (LLM), такими как OpenAI, для создания контента, сгенерированного ИИ. Подробнее об AI SDK.
import OpenAI from 'openai'
import { OpenAIStream, StreamingTextResponse } from 'ai'
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
})
export const runtime = 'edge'
export async function POST(req: Request) {
const { messages } = await req.json()
const response = await openai.chat.completions.create({
model: 'gpt-3.5-turbo',
stream: true,
messages,
})
const stream = OpenAIStream(response)
return new StreamingTextResponse(stream)
}Эти абстракции используют веб-API для создания потока. Вы также можете использовать основные веб-API напрямую.
// https://developer.mozilla.org/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 запроса, используя стандартные методы веб-API:
export async function POST(request: Request) {
const res = await request.json()
return Response.json({ res })
}Тело запроса FormData
Вы можете прочитать тело FormData с помощью функции request.formData():
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).
CORS
Вы можете установить заголовки CORS для конкретного обработчика маршрута, используя стандартные методы веб-API:
export const dynamic = 'force-dynamic' // defaults to auto
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',
},
})
}Важно знать:
- Чтобы добавить заголовки CORS к нескольким обработчикам маршрутов, можно использовать Средства промежуточного программного обеспечения или
next.config.jsфайл.- В качестве альтернативы, ознакомьтесь с нашим примером CORS в пакете CORS example.
Обработчики веб-хуков
Вы можете использовать обработчик маршрута для получения веб-хуков от сторонних сервисов:
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 для использования дополнительных настроек.
Edge и Node.js среды выполнения
Обработчики маршрутов имеют изоморфный веб-API для поддержки как Edge, так и Node.js сред выполнения без проблем, включая поддержку потоковой передачи. Поскольку обработчики маршрутов используют ту же конфигурацию сегментов маршрута, что и страницы и макеты, они поддерживают долгожданные функции, такие как универсальные статически перегенерированные обработчики маршрутов.
Вы можете использовать опцию конфигурации сегмента runtime для указания среды выполнения:
export const runtime = 'edge' // 'nodejs' is the default
Ответы, не связанные с пользовательским интерфейсом
Вы можете использовать обработчики маршрутов для возврата содержимого, не связанного с пользовательским интерфейсом. Обратите внимание, что sitemap.xml, robots.txt, app icons и изображения open graph все имеют встроенную поддержку.
export const dynamic = 'force-dynamic' // defaults to auto
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>`,
{
headers: {
'Content-Type': 'text/xml',
},
}
)
}Опции конфигурации сегмента
Обработчики маршрутов используют ту же конфигурацию сегментов маршрута, что и страницы и макеты.
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.
© 2024 Vercel, Inc.
Licensed under the MIT License.
https://nextjs.org/docs/app/building-your-application/routing/route-handlers