Route-Handler Route-Handler ermöglichen es Ihnen, benutzerdefinierte Request-Handler für eine bestimmte Route unter Verwendung der Web-APIs Request und Response zu erstellen.
Hinweis : Route-Handler sind nur innerhalb des app
-Verzeichnisses verfügbar. Sie entsprechen den API-Routen im pages
-Verzeichnis, was bedeutet, dass Sie keine API-Routen und Route-Handler zusammen verwenden müssen.
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 überall im app
-Verzeichnis verschachtelt werden, ähnlich wie page.js
und layout.js
. Es darf jedoch keine route.js
-Datei auf der gleichen Routensegmentebene wie page.js
geben.
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.
Zusätzlich zur Unterstützung der nativen Request - und Response -APIs erweitert Next.js diese mit NextRequest
und NextResponse
, um komfortable Hilfsmittel für fortgeschrittene Anwendungsfälle bereitzustellen.
Route-Handler werden standardmäßig nicht zwischengespeichert. Sie können jedoch das Caching für GET
-Methoden aktivieren. Andere unterstützte HTTP-Methoden werden nicht zwischengespeichert. Um eine GET
-Methode zu zwischenspeichern, verwenden Sie eine Route-Konfigurationsoption wie export const dynamic = 'force-static'
in Ihrer Route-Handler-Datei.
export const dynamic = ' force-static '
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 const dynamic = ' force-static '
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 })
}
Hinweis : Andere unterstützte HTTP-Methoden werden nicht zwischengespeichert, auch wenn sie zusammen mit einer zwischengespeicherten GET
-Methode in derselben Datei platziert sind.
Spezielle Route-Handler wie sitemap.ts
, opengraph-image.tsx
und icon.tsx
sowie andere Metadatendateien bleiben standardmäßig statisch, es sei denn, sie verwenden dynamische APIs oder dynamische Konfigurationsoptionen.
Sie können eine route
als die unterste Routing-Primitive betrachten.
Sie nehmen nicht an Layouts oder Client-seitigen Navigationen teil wie page
.
Es darf keine route.js
-Datei auf der gleichen Route wie page.js
geben.
Seite Route Ergebnis app/page.js
app/route.js
Konfliktapp/page.js
app/api/route.js
Gültigapp/[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 >Hallo, Next.js!</ h1 >
}
// ❌ Konflikt
// `app/route.js`
export async function POST (request) {}
Die folgenden Beispiele zeigen, wie Sie Route-Handler mit anderen Next.js-APIs und -Funktionen kombinieren können.
Sie können zwischengespeicherte Daten mithilfe von Incrementeller Statischer Regenerierung (ISR) neu laden :
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)
}
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)
}
Sie können Cookies mit cookies
aus next/headers
lesen oder setzen. Diese Serverfunktion kann direkt in einem Route-Handler oder geschachtelt in einer anderen Funktion aufgerufen werden.
Alternativ können Sie eine neue Response
mit dem Set-Cookie
-Header zurückgeben.
import { cookies } from ' next/headers '
export async function GET (request : Request ) {
const cookieStore = await cookies ()
const token = cookieStore . get ( ' token ' )
return new Response ( ' Hallo, Next.js! ' , {
status : 200 ,
headers : { ' Set-Cookie ' : ` token= ${ token .value } ` },
})
}
import { cookies } from ' next/headers '
export async function GET (request) {
const cookieStore = await cookies ()
const token = cookieStore . get ( ' token ' )
return new Response ( ' Hallo, Next.js! ' , {
status : 200 ,
headers : { ' Set-Cookie ' : ` token= ${ token } ` },
})
}
Sie können auch die zugrunde liegenden Web-APIs verwenden, um Cookies aus der Anfrage 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 ' )
}
Sie können Header mit headers
aus next/headers
lesen. Diese Serverfunktion kann direkt in einem Route-Handler oder geschachtelt in einer anderen Funktion aufgerufen werden.
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 = await headers ()
const referer = headersList . get ( ' referer ' )
return new Response ( ' Hallo, Next.js! ' , {
status : 200 ,
headers : { referer : referer },
})
}
import { headers } from ' next/headers '
export async function GET (request) {
const headersList = await headers ()
const referer = headersList . get ( ' referer ' )
return new Response ( ' Hallo, Next.js! ' , {
status : 200 ,
headers : { referer : referer },
})
}
Sie können auch die zugrunde liegenden Web-APIs verwenden, um Header aus der Anfrage 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)
}
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/ ' )
}
Wir empfehlen, die Seite Routen definieren zu lesen, bevor Sie fortfahren.
Route Handlers können Dynamische Segmente verwenden, um Anfrage-Handler aus dynamischen Daten zu erstellen.
export async function GET (
request : Request ,
{ params } : { params : Promise <{ slug : string }> }
) {
const slug = ( await params).slug // 'a', 'b' oder 'c'
}
export async function GET (request, { params }) {
const slug = ( await params).slug // 'a', 'b' oder 'c'
}
Route Beispiel-URL params
app/items/[slug]/route.js
/items/a
Promise<{ slug: 'a' }>
app/items/[slug]/route.js
/items/b
Promise<{ slug: 'b' }>
app/items/[slug]/route.js
/items/c
Promise<{ slug: 'c' }>
Das an den Route Handler übergebene Request-Objekt ist eine NextRequest
-Instanz, die einige zusätzliche Komfortmethoden hat, einschließlich einer einfacheren Handhabung von Abfrageparametern.
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 wird häufig in Kombination mit Large Language Models (LLMs) wie OpenAI für KI-generierte Inhalte verwendet. Erfahren Sie mehr über das AI SDK .
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 ())
}
import { openai } from ' @ai-sdk/openai '
import { StreamingTextResponse, streamText } from ' ai '
export async function POST (req) {
const { messages } = await req . json ()
const result = await streamText ({
model : openai ( ' gpt-4-turbo ' ),
messages,
})
return new StreamingTextResponse ( result . toAIStream ())
}
Diese Abstraktionen verwenden Web-APIs, um einen Stream zu erstellen. Sie können auch die zugrunde liegenden Web-APIs direkt verwenden.
// 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)
}
Sie können den Request
-Body mithilfe der Standard-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 })
}
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 allesamt Strings sind, empfiehlt sich zod-form-data
zur Validierung der Anfrage und Abholung der Daten im gewünschten Format (z.B. number
).
Sie können CORS-Header für einen bestimmten Route Handler mit Standard-Web-API-Methoden setzen:
export async function GET (request : Request ) {
return new Response ( ' Hallo, 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 ( ' Hallo, 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 ' ,
},
})
}
Hinweis :
Sie können einen Route Handler verwenden, um Webhooks von Drittanbieterdiensten zu empfangen:
export async function POST (request : Request ) {
try {
const text = await request . text ()
// Webhook-Payload verarbeiten
} catch (error) {
return new Response ( ` Webhook-Fehler: ${ error .message } ` , {
status : 400 ,
})
}
return new Response ( ' Erfolg! ' , {
status : 200 ,
})
}
export async function POST (request) {
try {
const text = await request . text ()
// Webhook-Payload verarbeiten
} catch (error) {
return new Response ( ` Webhook-Fehler: ${ error .message } ` , {
status : 400 ,
})
}
return new Response ( ' Erfolg! ' , {
status : 200 ,
})
}
Bemerkenswert ist, dass Sie im Gegensatz zu API-Routen mit dem Pages Router keine zusätzliche Konfiguration mit bodyParser
benötigen.
Sie können Route Handlers verwenden, um Nicht-UI-Inhalte zurückzugeben. Beachten Sie, dass sitemap.xml
, robots.txt
, App-Symbole
und Open Graph-Bilder bereits integrierte Unterstützung haben.
export async function GET () {
return new Response (
` <?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title>Next.js Dokumentation</title>
<link>https://nextjs.org/docs</link>
<description>Das React Framework für das Web</description>
</channel>
</rss> ` ,
{
headers : {
' Content-Type ' : ' text/xml ' ,
},
}
)
}
export async function GET () {
return new Response ( ` <?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title>Next.js Dokumentation</title>
<link>https://nextjs.org/docs</link>
<description>Das React Framework für das Web</description>
</channel>
</rss> ` )
}
Route Handlers verwenden dieselbe Routensegment-Konfiguration wie Seiten 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 .