Route Handler
Route Handler ermöglichen es Ihnen, benutzerdefinierte Request-Handler für eine bestimmte Route mit den Web-Request- und Response-APIs zu erstellen.

Wichtig zu wissen: Route Handler sind nur innerhalb des
app
-Verzeichnisses verfügbar. Sie sind das Äquivalent zu API Routes innerhalb despages
-Verzeichnisses, was bedeutet, dass Sie nicht API Routes und Route Handler zusammen verwenden müssen.
Konvention
Route Handler werden in einer route.js|ts
-Datei innerhalb des app
-Verzeichnisses definiert:
export async function GET(request: Request) {}
export async function GET(request) {}
Route Handler können, ähnlich wie page.js
und layout.js
, innerhalb des app
-Verzeichnisses verschachtelt werden. Es darf jedoch keine route.js
-Datei auf demselben Routen-Segment-Level wie page.js
geben.
Unterstützte HTTP-Methoden
Die folgenden HTTP-Methoden werden unterstützt: GET
, POST
, PUT
, PATCH
, DELETE
, HEAD
und OPTIONS
. Wenn eine nicht unterstützte Methode aufgerufen wird, gibt Next.js eine 405 Method Not Allowed
-Antwort zurück.
Erweiterte NextRequest
- und NextResponse
-APIs
Neben der Unterstützung der nativen Request- und Response-APIs erweitert Next.js diese mit
NextRequest
und NextResponse
, um praktische Hilfsmittel für fortgeschrittene Anwendungsfälle bereitzustellen.
Verhalten
Caching
Route Handler werden standardmäßig zwischengespeichert, wenn die GET
-Methode mit dem Response
-Objekt verwendet wird.
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 })
}
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-Warnung:
Response.json()
ist erst ab TypeScript 5.2 gültig. Wenn Sie eine niedrigere TypeScript-Version verwenden, können Sie stattdessenNextResponse.json()
für typisierte Antworten verwenden.
Opt-out vom Caching
Sie können das Caching deaktivieren durch:
- Verwendung des
Request
-Objekts mit derGET
-Methode. - Verwendung einer anderen HTTP-Methode.
- Verwendung von Dynamischen Funktionen wie
cookies
undheaders
. - Manuelle Angabe des dynamischen Modus durch die Segment Config Options.
Beispiel:
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 })
}
export async function GET(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 })
}
Ebenso führt die POST
-Methode dazu, dass der Route Handler dynamisch ausgewertet wird.
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)
}
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)
}
Wichtig zu wissen: Wie API Routes können Route Handler für Fälle wie die Verarbeitung von Formularübermittlungen verwendet werden. Eine neue Abstraktion für die Verarbeitung von Formularen und Mutationen, die tief mit React integriert ist, wird derzeit entwickelt.
Routen-Auflösung
Sie können sich einen route
als die grundlegendste Routing-Primitive vorstellen.
- Sie nehmen nicht an Layouts oder clientseitigen Navigationen wie
page
teil. - Es kann keine
route.js
-Datei auf derselben Route wiepage.js
geben.
Seite | Route | Ergebnis |
---|---|---|
app/page.js | app/route.js | Konflikt |
app/page.js | app/api/route.js | Gültig |
app/[user]/page.js | app/api/route.js | Gültig |
Jede route.js
- oder page.js
-Datei übernimmt alle HTTP-Verben für diese Route.
export default function Page() {
return <h1>Hello, Next.js!</h1>
}
// ❌ Konflikt
// `app/route.js`
export async function POST(request) {}
Beispiele
Die folgenden Beispiele zeigen, wie Route Handler mit anderen Next.js-APIs und Funktionen kombiniert werden können.
Revalidierung zwischengespeicherter Daten
Sie können zwischengespeicherte Daten revalidieren mit der next.revalidate
-Option:
export async function GET() {
const res = await fetch('https://data.mongodb-api.com/...', {
next: { revalidate: 60 }, // Alle 60 Sekunden revalidieren
})
const data = await res.json()
return Response.json(data)
}
export async function GET() {
const res = await fetch('https://data.mongodb-api.com/...', {
next: { revalidate: 60 }, // Alle 60 Sekunden revalidieren
})
const data = await res.json()
return Response.json(data)
}
Alternativ können Sie die revalidate
Segment Config Option verwenden:
export const revalidate = 60
Dynamische Funktionen
Route Handler können mit dynamischen Funktionen von Next.js verwendet werden, wie cookies
und headers
.
Cookies
Sie können Cookies mit cookies
aus next/headers
lesen. Diese Serverfunktion kann direkt in einem Route Handler aufgerufen werden oder in einer anderen Funktion verschachtelt sein.
Diese cookies
-Instanz ist schreibgeschützt. Um Cookies zu setzen, müssen Sie eine neue Response
mit dem Set-Cookie
-Header zurückgeben.
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}` },
})
}
import { cookies } from 'next/headers'
export async function GET(request) {
const cookieStore = cookies()
const token = cookieStore.get('token')
return new Response('Hello, Next.js!', {
status: 200,
headers: { 'Set-Cookie': `token=${token}` },
})
}
Alternativ können Sie Abstraktionen über den zugrunde liegenden Web-APIs verwenden, um Cookies zu lesen (NextRequest
):
import { type NextRequest } from 'next/server'
export async function GET(request: NextRequest) {
const token = request.cookies.get('token')
}
export async function GET(request) {
const token = request.cookies.get('token')
}
Headers
Sie können Header mit headers
aus next/headers
lesen. Diese Serverfunktion kann direkt in einem Route Handler aufgerufen werden oder in einer anderen Funktion verschachtelt sein.
Diese headers
-Instanz ist schreibgeschützt. Um Header zu setzen, müssen Sie eine neue Response
mit neuen headers
zurückgeben.
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 },
})
}
import { headers } from 'next/headers'
export async function GET(request) {
const headersList = headers()
const referer = headersList.get('referer')
return new Response('Hello, Next.js!', {
status: 200,
headers: { referer: referer },
})
}
Alternativ können Sie Abstraktionen über den zugrunde liegenden Web-APIs verwenden, um Header zu lesen (NextRequest
):
import { type NextRequest } from 'next/server'
export async function GET(request: NextRequest) {
const requestHeaders = new Headers(request.headers)
}
export async function GET(request) {
const requestHeaders = new Headers(request.headers)
}
Redirects
import { redirect } from 'next/navigation'
export async function GET(request: Request) {
redirect('https://nextjs.org/')
}
import { redirect } from 'next/navigation'
export async function GET(request) {
redirect('https://nextjs.org/')
}
Dynamische Routen-Segmente
Wir empfehlen, die Seite Defining Routes zu lesen, bevor Sie fortfahren.
Route Handler können Dynamische Segmente verwenden, um Request-Handler aus dynamischen Daten zu erstellen.
export async function GET(
request: Request,
{ params }: { params: { slug: string } }
) {
const slug = params.slug // 'a', 'b' oder 'c'
}
export async function GET(request, { params }) {
const slug = params.slug // 'a', 'b' oder 'c'
}
Route | Beispiel-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 Query-Parameter
Das Request-Objekt, das an den Route Handler übergeben wird, ist eine NextRequest
-Instanz, die einige zusätzliche Hilfsmethoden bietet, einschließlich der einfacheren Handhabung von Query-Parametern.
import { type NextRequest } from 'next/server'
export function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams
const query = searchParams.get('query')
// query ist "hello" für /api/search?query=hello
}
export function GET(request) {
const searchParams = request.nextUrl.searchParams
const query = searchParams.get('query')
// query ist "hello" für /api/search?query=hello
}
Streaming
Streaming wird häufig in Kombination mit großen Sprachmodellen (Large Language Models, LLMs) wie OpenAI für KI-generierte Inhalte verwendet. Weitere Informationen finden Sie im AI SDK.
import { Configuration, OpenAIApi } from 'openai-edge'
import { OpenAIStream, StreamingTextResponse } from 'ai'
export const runtime = 'edge'
const apiConfig = new Configuration({
apiKey: process.env.OPENAI_API_KEY!,
})
const openai = new OpenAIApi(apiConfig)
export async function POST(req: Request) {
// Extrahiere die `messages` aus dem Body der Anfrage
const { messages } = await req.json()
// Fordere die OpenAI-API für die Antwort basierend auf dem Prompt an
const response = await openai.createChatCompletion({
model: 'gpt-3.5-turbo',
stream: true,
messages: messages,
max_tokens: 500,
temperature: 0.7,
top_p: 1,
frequency_penalty: 1,
presence_penalty: 1,
})
// Konvertiere die Antwort in einen nutzerfreundlichen Text-Stream
const stream = OpenAIStream(response)
// Antworte mit dem Stream
return new StreamingTextResponse(stream)
}
import { Configuration, OpenAIApi } from 'openai-edge'
import { OpenAIStream, StreamingTextResponse } from 'ai'
export const runtime = 'edge'
const apiConfig = new Configuration({
apiKey: process.env.OPENAI_API_KEY,
})
const openai = new OpenAIApi(apiConfig)
export async function POST(req) {
// Extrahiere die `messages` aus dem Body der Anfrage
const { messages } = await req.json()
// Fordere die OpenAI-API für die Antwort basierend auf dem Prompt an
const response = await openai.createChatCompletion({
model: 'gpt-3.5-turbo',
stream: true,
messages: messages,
max_tokens: 500,
temperature: 0.7,
top_p: 1,
frequency_penalty: 1,
presence_penalty: 1,
})
// Konvertiere die Antwort in einen nutzerfreundlichen Text-Stream
const stream = OpenAIStream(response)
// Antworte mit dem Stream
return new StreamingTextResponse(stream)
}
Diese Abstraktionen verwenden die Web-APIs, um einen Stream zu erstellen. Sie können auch die zugrunde liegenden Web-APIs direkt nutzen.
// 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)
}
// https://developer.mozilla.org/docs/Web/API/ReadableStream#convert_async_iterator_to_stream
function iteratorToStream(iterator) {
return new ReadableStream({
async pull(controller) {
const { value, done } = await iterator.next()
if (done) {
controller.close()
} else {
controller.enqueue(value)
}
},
})
}
function sleep(time) {
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
Sie können den Request
-Body mit den standardmäßigen Web-API-Methoden lesen:
export async function POST(request: Request) {
const res = await request.json()
return Response.json({ res })
}
export async function POST(request) {
const res = await request.json()
return Response.json({ res })
}
Request Body FormData
Sie können FormData
mit der Funktion request.formData()
lesen:
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 })
}
export async function POST(request) {
const formData = await request.formData()
const name = formData.get('name')
const email = formData.get('email')
return Response.json({ name, email })
}
Da formData
-Daten alle als Zeichenketten vorliegen, können Sie zod-form-data
verwenden, um die Anfrage zu validieren und die Daten in dem gewünschten Format (z.B. number
) zu erhalten.
CORS
Sie können CORS-Header für eine Response
mit den standardmäßigen Web-API-Methoden setzen:
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',
},
})
}
export async function GET(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- und Node.js-Runtimes
Route Handler verfügen über eine isomorphe Web-API, um sowohl Edge- als auch Node.js-Runtimes nahtlos zu unterstützen, inklusive Streaming. Da Route Handler die gleiche Route Segment Configuration wie Pages und Layouts verwenden, unterstützen sie lang erwartete Funktionen wie allgemein nutzbare statisch regenerierte Route Handler.
Sie können die runtime
-Segmentkonfigurationsoption verwenden, um die Laufzeitumgebung anzugeben:
export const runtime = 'edge' // 'nodejs' ist der Standardwert
Nicht-UI-Antworten
Sie können Route Handler verwenden, um Nicht-UI-Inhalte zurückzugeben. Beachten Sie, dass sitemap.xml
, robots.txt
, App-Icons
und Open-Graph-Bilder bereits integrierte Unterstützung bieten.
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>`)
}
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>`)
}
Segmentkonfigurationsoptionen
Route Handler verwenden die gleiche Route Segment Configuration wie Pages und Layouts.
export const dynamic = 'auto'
export const dynamicParams = true
export const revalidate = false
export const fetchCache = 'auto'
export const runtime = 'nodejs'
export const preferredRegion = 'auto'
export const dynamic = 'auto'
export const dynamicParams = true
export const revalidate = false
export const fetchCache = 'auto'
export const runtime = 'nodejs'
export const preferredRegion = 'auto'
Weitere Details finden Sie in der API-Referenz.
Interceptierende Routen (Intercepting Routes)
Nutzen Sie interceptierende Routen, um eine neue Route innerhalb des aktuellen Layouts zu laden, während die Browser-URL maskiert wird. Nützlich für erweiterte Routing-Muster wie Modals.
Middleware
Erfahren Sie, wie Sie Middleware verwenden, um Code vor dem Abschluss einer Anfrage auszuführen.