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 anstelle einer page
behandelt. Es handelt sich um serverseitige Bundles, die die clientseitige Bundle-Größe nicht erhöhen.
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 umschließen.
- 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.IncomingMessageres
: Eine Instanz von http.ServerResponse
HTTP-Methoden
Um verschiedene HTTP-Methoden in einer API-Route zu verarbeiten, können Sie req.method
in Ihrem Request-Handler verwenden:
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. Standardwert:{}
req.query
- Ein Objekt mit der Query-String. Standardwert:{}
req.body
- Ein Objekt mit dem durchcontent-type
geparsten Body odernull
, wenn kein Body gesendet wurde
Benutzerdefinierte Konfiguration
Jede API-Route kann ein config
-Objekt exportieren, um die Standardkonfiguration zu ändern:
export const config = {
api: {
bodyParser: {
sizeLimit: '1mb',
},
},
// Gibt die maximal erlaubte Ausführungsdauer für diese Funktion an (in Sekunden)
maxDuration: 5,
}
bodyParser
ist standardmäßig 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 Validierung des Roh-Bodys eines Webhook-Requests, z.B. von GitHub.
export const config = {
api: {
bodyParser: false,
},
}
bodyParser.sizeLimit
ist die maximale Größe des geparsten Bodys in einem von bytes unterstützten Format:
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 standardmäßig aktiviert und warnt, wenn der Response-Body einer API-Route 4MB überschreitet.
Wenn Sie Next.js nicht in einer serverlosen Umgebung verwenden und die Leistungsauswirkungen verstehen, können Sie dieses Limit auf false
setzen.
export const config = {
api: {
responseLimit: false,
},
}
responseLimit
kann auch eine Byte-Anzahl oder ein 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.
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 Hilfsfunktionen, die die Entwicklererfahrung verbessern und die Erstellung neuer API-Endpunkte 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 URL weiter.status
muss ein gültiger HTTP-Statuscode sein. Wenn nicht angegeben, ist der Standardwert "307" "Temporary redirect".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, die ein serialisierbares Objekt sein muss. In einer realen Anwendung möchten Sie möglicherweise den Client ü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 mögliche Fehler zu behandeln, 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 Antwort-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 URL
Nehmen wir ein Formular als Beispiel: Sie möchten Ihren Client nach erfolgreicher Übermittlung des Formulars zu einem bestimmten Pfad oder 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 Antwortdaten 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 Daten senden 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 denselben 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}`)
}
Eine Anfrage an /api/post/abc
antwortet nun mit dem Text: Post: abc
.
Catch-all-API-Routen
API-Routen können erweitert werden, um alle Pfade abzufangen, indem drei Punkte (...
) in den Klammern hinzugefügt werden. Beispiel:
pages/api/post/[...slug].js
matcht/api/post/a
, aber auch/api/post/a/b
,/api/post/a/b/c
usw.
Gut zu wissen: Sie können andere Namen als
slug
verwenden, z.B.[...param]
Die gematchten Parameter werden als Query-Parameter (slug
im Beispiel) an die Seite gesendet und sind immer ein Array. Der Pfad /api/post/a
hat also folgendes query
-Objekt:
{ "slug": ["a"] }
Und im Fall von /api/post/a/b
oder jedem anderen passenden Pfad werden neue Parameter zum Array hinzugefügt:
{ "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(', ')}`)
}
Eine Anfrage an /api/post/a/b/c
antwortet nun mit dem Text: 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]]
).
Beispiel: pages/api/post/[[...slug]].js
matcht /api/post
, /api/post/a
, /api/post/a/b
usw.
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)
Caveats
- Vordefinierte API-Routen haben Vorrang vor dynamischen API-Routen, und dynamische API-Routen haben Vorrang vor Catch-all-API-Routen. Beispiele:
pages/api/post/create.js
- Matcht/api/post/create
pages/api/post/[pid].js
- Matcht/api/post/1
,/api/post/abc
usw., aber nicht/api/post/create
pages/api/post/[...slug].js
- Matcht/api/post/1/2
,/api/post/a/b/c
usw., 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.