Spec-Zone.ru › Next.js

Обработчики маршрутов

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

Route.js Special FileRoute.js Special File

Важно знать: Обработчики маршрутов доступны только внутри каталога 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API