API-Routen
Beispiele
Gut zu wissen: Wenn Sie den App Router verwenden, können Sie Server Components oder Route Handlers anstelle von API-Routen nutzen.
API-Routen bieten eine Lösung zum Erstellen einer öffentlichen API mit Next.js.
Jede Datei im Ordner pages/api
wird auf /api/*
gemappt und als API-Endpunkt behandelt, nicht als page
. Sie sind nur serverseitige Bundles und erhöhen nicht die clientseitige Bundle-Größe.
Beispielsweise gibt die folgende API-Route eine JSON-Antwort mit dem Statuscode 200
zurück:
import type { NextApiRequest, NextApiResponse } from 'next'
type ResponseData = {
message: string
}
export default function handler(
req: NextApiRequest,
res: NextApiResponse<ResponseData>
) {
res.status(200).json({ message: 'Hello from Next.js!' })
}
export default function handler(req, res) {
res.status(200).json({ message: 'Hello from Next.js!' })
}
Gut zu wissen:
- API-Routen legen keine CORS-Header fest, was bedeutet, dass sie standardmäßig nur same-origin sind. Sie können dieses Verhalten anpassen, indem Sie den Request-Handler mit den CORS Request-Helpern wrappen.
- API-Routen können nicht mit statischen Exports verwendet werden. Allerdings können Route Handlers im App Router dies.
- API-Routen werden durch die
pageExtensions
-Konfiguration innext.config.js
beeinflusst.
Parameter
export default function handler(req: NextApiRequest, res: NextApiResponse) {
// ...
}
req
: Eine Instanz von http.IncomingMessage, plus einige vordefinierte Middlewaresres
: Eine Instanz von http.ServerResponse, plus einige Helper-Funktionen
HTTP-Methoden
Um verschiedene HTTP-Methoden in einer API-Route zu handhaben, können Sie req.method
in Ihrem Request-Handler verwenden, wie folgt:
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'POST') {
// Verarbeite einen POST-Request
} else {
// Behandle jede andere HTTP-Methode
}
}
export default function handler(req, res) {
if (req.method === 'POST') {
// Verarbeite einen POST-Request
} else {
// Behandle jede andere HTTP-Methode
}
}
Request-Helper
API-Routen bieten eingebaute Request-Helper, die den eingehenden Request (req
) parsen:
req.cookies
- Ein Objekt mit den vom Request gesendeten Cookies. Standardmäßig{}
req.query
- Ein Objekt mit der Query-String. Standardmäßig{}
req.body
- Ein Objekt mit dem voncontent-type
geparsten Body odernull
, wenn kein Body gesendet wurde
Benutzerdefinierte Konfiguration
Jede API-Route kann ein config
-Objekt exportieren, um die Standardkonfiguration zu ändern, die wie folgt lautet:
export const config = {
api: {
bodyParser: {
sizeLimit: '1mb',
},
},
// Gibt die maximal erlaubte Ausführungsdauer für diese Funktion an (in Sekunden)
maxDuration: 5,
}
bodyParser
ist automatisch aktiviert. Wenn Sie den Body als Stream
oder mit raw-body
verarbeiten möchten, können Sie dies auf false
setzen.
Ein Anwendungsfall für das Deaktivieren des automatischen bodyParsing
ist die Überprüfung des rohen Bodys eines Webhook-Requests, z.B. von GitHub.
export const config = {
api: {
bodyParser: false,
},
}
bodyParser.sizeLimit
ist die maximal erlaubte Größe für den geparsten Body in jedem von bytes unterstützten Format, wie folgt:
export const config = {
api: {
bodyParser: {
sizeLimit: '500kb',
},
},
}
externalResolver
ist ein explizites Flag, das dem Server mitteilt, dass diese Route von einem externen Resolver wie express oder connect behandelt wird. Das Aktivieren dieser Option deaktiviert Warnungen für ungelöste Requests.
export const config = {
api: {
externalResolver: true,
},
}
responseLimit
ist automatisch aktiviert und warnt, wenn der Response-Body einer API-Route größer als 4MB ist.
Wenn Sie Next.js nicht in einer serverlosen Umgebung verwenden und die Leistungsauswirkungen der Nichtverwendung eines CDN oder dedizierten Media-Hosts verstehen, können Sie dieses Limit auf false
setzen.
export const config = {
api: {
responseLimit: false,
},
}
responseLimit
kann auch die Anzahl der Bytes oder ein beliebiges von bytes
unterstütztes String-Format annehmen, z.B. 1000
, '500kb'
oder '3mb'
.
Dieser Wert ist die maximale Response-Größe, bevor eine Warnung angezeigt wird. Standard ist 4MB (siehe oben).
export const config = {
api: {
responseLimit: '8mb',
},
}
Response-Helper
Das Server Response-Objekt (oft als res
abgekürzt) enthält eine Reihe von Express.js-ähnlichen Helper-Methoden, um die Entwicklererfahrung zu verbessern und die Erstellung neuer API-Endpunkte zu beschleunigen.
Die enthaltenen Helfer sind:
res.status(code)
- Eine Funktion zum Setzen des Statuscodes.code
muss ein gültiger HTTP-Statuscode seinres.json(body)
- Sendet eine JSON-Antwort.body
muss ein serialisierbares Objekt seinres.send(body)
- Sendet die HTTP-Antwort.body
kann einstring
, einobject
oder einBuffer
seinres.redirect([status,] path)
- Leitet zu einem bestimmten Pfad oder einer URL weiter.status
muss ein gültiger HTTP-Statuscode sein. Wenn nicht angegeben, wirdstatus
standardmäßig auf "307" ("Temporary redirect") gesetzt.res.revalidate(urlPath)
- Revalidiert eine Seite bei Bedarf mitgetStaticProps
.urlPath
muss einstring
sein.
Setzen des Statuscodes einer Antwort
Beim Senden einer Antwort an den Client können Sie den Statuscode der Antwort setzen.
Das folgende Beispiel setzt den Statuscode der Antwort auf 200
(OK
) und gibt eine message
-Eigenschaft mit dem Wert Hello from Next.js!
als JSON-Antwort zurück:
import type { NextApiRequest, NextApiResponse } from 'next'
type ResponseData = {
message: string
}
export default function handler(
req: NextApiRequest,
res: NextApiResponse<ResponseData>
) {
res.status(200).json({ message: 'Hello from Next.js!' })
}
export default function handler(req, res) {
res.status(200).json({ message: 'Hello from Next.js!' })
}
Senden einer JSON-Antwort
Beim Senden einer Antwort an den Client können Sie eine JSON-Antwort senden, dies muss ein serialisierbares Objekt sein. In einer realen Anwendung möchten Sie den Client möglicherweise über den Status des Requests informieren, abhängig vom Ergebnis des angeforderten Endpunkts.
Das folgende Beispiel sendet eine JSON-Antwort mit dem Statuscode 200
(OK
) und dem Ergebnis der asynchronen Operation. Es ist in einem try-catch-Block enthalten, um eventuelle Fehler abzufangen, mit dem entsprechenden Statuscode und der Fehlermeldung, die an den Client zurückgesendet wird:
import type { NextApiRequest, NextApiResponse } from 'next'
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
try {
const result = await someAsyncOperation()
res.status(200).json({ result })
} catch (err) {
res.status(500).json({ error: 'failed to load data' })
}
}
export default async function handler(req, res) {
try {
const result = await someAsyncOperation()
res.status(200).json({ result })
} catch (err) {
res.status(500).json({ error: 'failed to load data' })
}
}
Senden einer HTTP-Antwort
Das Senden einer HTTP-Antwort funktioniert genauso wie das Senden einer JSON-Antwort. Der einzige Unterschied besteht darin, dass der Response-Body ein string
, ein object
oder ein Buffer
sein kann.
Das folgende Beispiel sendet eine HTTP-Antwort mit dem Statuscode 200
(OK
) und dem Ergebnis der asynchronen Operation.
import type { NextApiRequest, NextApiResponse } from 'next'
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
try {
const result = await someAsyncOperation()
res.status(200).send({ result })
} catch (err) {
res.status(500).send({ error: 'failed to fetch data' })
}
}
export default async function handler(req, res) {
try {
const result = await someAsyncOperation()
res.status(200).send({ result })
} catch (err) {
res.status(500).send({ error: 'failed to fetch data' })
}
}
Weiterleitung zu einem bestimmten Pfad oder einer URL
Nehmen wir ein Formular als Beispiel. Möglicherweise möchten Sie Ihren Client nach erfolgreicher Übermittlung des Formulars zu einem bestimmten Pfad oder einer URL weiterleiten.
Das folgende Beispiel leitet den Client zum Pfad /
weiter, wenn das Formular erfolgreich übermittelt wurde:
import type { NextApiRequest, NextApiResponse } from 'next'
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const { name, message } = req.body
try {
await handleFormInputAsync({ name, message })
res.redirect(307, '/')
} catch (err) {
res.status(500).send({ error: 'Failed to fetch data' })
}
}
export default async function handler(req, res) {
const { name, message } = req.body
try {
await handleFormInputAsync({ name, message })
res.redirect(307, '/')
} catch (err) {
res.status(500).send({ error: 'failed to fetch data' })
}
}
Hinzufügen von TypeScript-Typen
Sie können Ihre API-Routen typsicher machen, indem Sie die Typen NextApiRequest
und NextApiResponse
aus next
importieren. Zusätzlich können Sie auch Ihre Response-Daten typisieren:
import type { NextApiRequest, NextApiResponse } from 'next'
type ResponseData = {
message: string
}
export default function handler(
req: NextApiRequest,
res: NextApiResponse<ResponseData>
) {
res.status(200).json({ message: 'Hello from Next.js!' })
}
Gut zu wissen: Der Body von
NextApiRequest
istany
, da der Client beliebige Payloads enthalten kann. Sie sollten den Typ/die Form des Bodys zur Laufzeit validieren, bevor Sie ihn verwenden.
Dynamische API-Routen
API-Routen unterstützen dynamische Routen und folgen den gleichen Dateibenennungsregeln wie pages/
.
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) {
const { pid } = req.query
res.end(`Post: ${pid}`)
}
export default function handler(req, res) {
const { pid } = req.query
res.end(`Post: ${pid}`)
}
Nun wird ein Request an /api/post/abc
mit dem Text antworten: Post: abc
.
Catch-all-API-Routen
API-Routen können durch Hinzufügen von drei Punkten (...
) in den Klammern erweitert werden, um alle Pfade abzufangen. Zum Beispiel:
pages/api/post/[...slug].js
matcht/api/post/a
, aber auch/api/post/a/b
,/api/post/a/b/c
und so weiter.
Gut zu wissen: Sie können andere Namen als
slug
verwenden, z.B.[...param]
Gematchte Parameter werden als Query-Parameter (slug
im Beispiel) an die Seite gesendet und sind immer ein Array. Der Pfad /api/post/a
hat also das folgende query
-Objekt:
{ "slug": ["a"] }
Und im Fall von /api/post/a/b
und jedem anderen passenden Pfad werden neue Parameter zum Array hinzugefügt, wie folgt:
{ "slug": ["a", "b"] }
Beispiel:
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) {
const { slug } = req.query
res.end(`Post: ${slug.join(', ')}`)
}
export default function handler(req, res) {
const { slug } = req.query
res.end(`Post: ${slug.join(', ')}`)
}
Nun wird ein Request an /api/post/a/b/c
mit dem Text antworten: Post: a, b, c
.
Optionale Catch-all-API-Routen
Catch-all-Routen können optional gemacht werden, indem der Parameter in doppelte Klammern gesetzt wird ([[...slug]]
).
Zum Beispiel matcht pages/api/post/[[...slug]].js
/api/post
, /api/post/a
, /api/post/a/b
und so weiter.
Der Hauptunterschied zwischen Catch-all- und optionalen Catch-all-Routen besteht darin, dass bei optionalen Routen auch der Pfad ohne Parameter gematcht wird (/api/post
im obigen Beispiel).
Die query
-Objekte sehen wie folgt aus:
{ } // GET `/api/post` (leeres Objekt)
{ "slug": ["a"] } // `GET /api/post/a` (Array mit einem Element)
{ "slug": ["a", "b"] } // `GET /api/post/a/b` (Array mit mehreren Elementen)
Einschränkungen
- Vordefinierte API-Routen haben Vorrang vor dynamischen API-Routen, und dynamische API-Routen haben Vorrang vor Catch-all-API-Routen. Schauen Sie sich die folgenden Beispiele an:
pages/api/post/create.js
- Matcht/api/post/create
pages/api/post/[pid].js
- Matcht/api/post/1
,/api/post/abc
, etc. Aber nicht/api/post/create
pages/api/post/[...slug].js
- Matcht/api/post/1/2
,/api/post/a/b/c
, etc. Aber nicht/api/post/create
,/api/post/abc
Edge-API-Routen
Wenn Sie API-Routen mit der Edge Runtime verwenden möchten, empfehlen wir die schrittweise Einführung des App Routers und die Verwendung von Route Handlers anstelle von API-Routen.
Die Funktionssignatur von Route Handlern ist isomorph, was bedeutet, dass Sie dieselbe Funktion für sowohl Edge- als auch Node.js-Runtimes verwenden können.