Menu

API-Routen

Beispiele

Hinweis: Wenn Sie den App Router verwenden, können Sie stattdessen Server-Komponenten oder Route-Handler verwenden.

API-Routen bieten eine Lösung zum Aufbau einer öffentlichen API mit Next.js.

Jede Datei im Ordner pages/api wird zu /api/* zugeordnet und als API-Endpunkt behandelt, nicht als page. Sie sind serverseitige Bundles und erhöhen die Größe Ihres Client-seitigen Bundles nicht.

Zum Beispiel gibt die folgende API-Route eine JSON-Antwort mit einem Statuscode von 200 zurück:

pages/api/hello.ts
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!' })
}
pages/api/hello.js
export default function handler(req, res) {
  res.status(200).json({ message: 'Hello from Next.js!' })
}

Hinweis:

Parameter

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  // ...
}

HTTP-Methoden

Um verschiedene HTTP-Methoden in einer API-Route zu behandeln, können Sie req.method in Ihrem Anforderungshandler verwenden:

pages/api/hello.ts
import type { NextApiRequest, NextApiResponse } from 'next'
 
export default function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method === 'POST') {
    // POST-Anfrage verarbeiten
  } else {
    // Andere HTTP-Methode behandeln
  }
}
pages/api/hello.js
export default function handler(req, res) {
  if (req.method === 'POST') {
    // POST-Anfrage verarbeiten
  } else {
    // Andere HTTP-Methode behandeln
  }
}

Anfragenhilfen

API-Routen bieten integrierte Anfragenhilfen, die die eingehende Anfrage (req) analysieren:

  • req.cookies - Ein Objekt, das die von der Anfrage gesendeten Cookies enthält. Standard ist {}
  • req.query - Ein Objekt, das die Abfragezeichenfolge enthält. Standard ist {}
  • req.body - Ein Objekt, das den von content-type analysierten Body enthält, oder null, 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 maximale 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 konsumieren möchten, können Sie dies auf false setzen.

Ein Anwendungsfall für die Deaktivierung der automatischen bodyParsing ist die Überprüfung des Rohbodys einer Webhook-Anfrage, zum Beispiel von GitHub.

export const config = {
  api: {
    bodyParser: false,
  },
}

bodyParser.sizeLimit ist die maximal erlaubte Größe für den analysierten Body, in jedem 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 unaufgelöste Anfragen.

export const config = {
  api: {
    externalResolver: true,
  },
}

responseLimit ist standardmäßig aktiviert und warnt, wenn der Antwort-Body einer API-Route über 4 MB liegt.

Wenn Sie Next.js nicht in einer serverlosen Umgebung verwenden und die Leistungsauswirkungen verstehen, können Sie diesen Grenzwert auf false setzen.

export const config = {
  api: {
    responseLimit: false,
  },
}

responseLimit kann auch eine Anzahl von Bytes oder eine Zeichenfolge in einem von bytes unterstützten Format akzeptieren, z.B. 1000, '500kb' oder '3mb'. Dieser Wert wird die maximale Antwortgröße sein, bevor eine Warnung angezeigt wird. Standard ist 4 MB. (siehe oben)

export const config = {
  api: {
    responseLimit: '8mb',
  },
}

Antwortehelfer

Das Server-Antwortobjekt, (oft als res abgekürzt) enthält eine Reihe von Express.js-ähnlichen Hilfsmethoden, um die Entwicklererfahrung zu verbessern und die Geschwindigkeit der Erstellung neuer API-Endpunkte zu erhöhen.

Die enthaltenen Helfer sind:

  • res.status(code) - Eine Funktion zum Setzen des Statuscodes. code muss ein gültiger HTTP-Statuscode sein
  • res.json(body) - Sendet eine JSON-Antwort. body muss ein serialisierbares Objekt sein
  • res.send(body) - Sendet die HTTP-Antwort. body kann ein string, ein object oder ein Buffer sein
  • res.redirect([status,] path) - Leitet zu einem angegebenen Pfad oder einer URL weiter. status muss ein gültiger HTTP-Statuscode sein. Wenn nicht angegeben, ist status standardmäßig "307" "Temporäre Weiterleitung".
  • res.revalidate(urlPath) - Seite bei Bedarf neu validieren mit getStaticProps. urlPath muss ein string sein.

Setzen des Statuscodes einer Antwort

Beim Senden einer Antwort an den Client können Sie den Statuscode der Antwort festlegen.

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:

pages/api/hello.ts
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!' })
}
pages/api/hello.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 dem Client möglicherweise den Status der Anfrage mitteilen, 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 etwaige Fehler zu behandeln, wobei der entsprechende Statuscode und die Fehlermeldung abgefangen und an den Client zurückgesendet werden:

pages/api/hello.ts
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' })
  }
}
pages/api/hello.js
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 beim Senden einer JSON-Antwort. Der einzige Unterschied ist, dass der Antworttext eine Zeichenkette, ein Objekt oder ein Puffer sein kann.

Das folgende Beispiel sendet eine HTTP-Antwort mit dem Statuscode 200 (OK) und dem Ergebnis der asynchronen Operation.

pages/api/hello.ts
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' })
  }
}
pages/api/hello.js
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

Am Beispiel eines Formulars möchten Sie den Client möglicherweise nach dem Absenden des Formulars zu einem bestimmten Pfad oder einer URL weiterleiten.

Das folgende Beispiel leitet den Client zum /-Pfad weiter, wenn das Formular erfolgreich abgesendet wurde:

pages/api/hello.ts
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' })
  }
}
pages/api/hello.js
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 typsicherer machen, indem Sie die Typen NextApiRequest und NextApiResponse aus next importieren. Zusätzlich können Sie auch Ihre Antworddaten 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!' })
}

Hinweis: Der Body von NextApiRequest ist any, da der Client eine beliebige Payload einschließen kann. Sie sollten den Typ/die Form des Body zur Laufzeit validieren, bevor Sie ihn verwenden.

Dynamische API-Routen

API-Routen unterstützen dynamische Routen und folgen denselben Dateinamenregeln wie pages/.

pages/api/post/[pid].ts
import type { NextApiRequest, NextApiResponse } from 'next'
 
export default function handler(req: NextApiRequest, res: NextApiResponse) {
  const { pid } = req.query
  res.end(`Post: ${pid}`)
}
pages/api/post/[pid].js
export default function handler(req, res) {
  const { pid } = req.query
  res.end(`Post: ${pid}`)
}

Nun wird eine Anfrage an /api/post/abc mit dem Text: Post: abc antworten.

Catch-All API-Routen

API-Routen können erweitert werden, um alle Pfade zu erfassen, indem drei Punkte (...) in eckigen Klammern hinzugefügt werden. Beispielsweise:

  • pages/api/post/[...slug].js passt auf /api/post/a, aber auch auf /api/post/a/b, /api/post/a/b/c und so weiter.

Hinweis: Sie können andere Namen als slug verwenden, wie zum Beispiel: [...param]

Übereinstimmende Parameter werden als Abfrageparameter (slug im Beispiel) an die Seite gesendet und sind immer ein Array. Der Pfad /api/post/a wird also das folgende Abfrageobjekt haben:

{ "slug": ["a"] }

Und im Fall von /api/post/a/b und jedem anderen übereinstimmenden Pfad werden neue Parameter dem Array hinzugefügt:

{ "slug": ["a", "b"] }

Beispiel:

pages/api/post/[...slug].ts
import type { NextApiRequest, NextApiResponse } from 'next'
 
export default function handler(req: NextApiRequest, res: NextApiResponse) {
  const { slug } = req.query
  res.end(`Post: ${slug.join(', ')}`)
}
pages/api/post/[...slug].js
export default function handler(req, res) {
  const { slug } = req.query
  res.end(`Post: ${slug.join(', ')}`)
}

Nun wird eine Anfrage an /api/post/a/b/c mit dem Text: Post: a, b, c antworten.

Optionale Catch-All API-Routen

Catch-All-Routen können optional gemacht werden, indem der Parameter in doppelte eckige Klammern ([[...slug]]) gesetzt wird.

Beispielsweise wird pages/api/post/[[...slug]].js auf /api/post, /api/post/a, /api/post/a/b und so weiter passen.

Der Hauptunterschied zwischen Catch-All- und optionalen Catch-All-Routen besteht darin, dass bei optionalen Routen auch die Route ohne Parameter übereinstimmt (/api/post im obigen Beispiel).

Die Abfrageobjekte sehen wie folgt aus:

{ } // GET `/api/post` (leeres Objekt)
{ "slug": ["a"] } // `GET /api/post/a` (einelementiges Array)
{ "slug": ["a", "b"] } // `GET /api/post/a/b` (mehrelementiges Array)

Einschränkungen

  • Vordefinierte API-Routen haben Vorrang vor dynamischen API-Routen, und dynamische API-Routen vor Catch-All-API-Routen. Betrachten Sie die folgenden Beispiele:
    • pages/api/post/create.js - Wird /api/post/create zuordnen
    • pages/api/post/[pid].js - Wird /api/post/1, /api/post/abc usw. zuordnen, aber nicht /api/post/create
    • pages/api/post/[...slug].js - Wird /api/post/1/2, /api/post/a/b/c usw. zuordnen, aber nicht /api/post/create, /api/post/abc

Edge API-Routen

Wenn Sie API-Routen mit der Edge-Laufzeit verwenden möchten, empfehlen wir, schrittweise den App Router zu übernehmen und stattdessen Route-Handler zu verwenden.

Die Signatur der Route-Handler-Funktion ist isomorph, was bedeutet, dass Sie dieselbe Funktion für Edge- und Node.js-Laufzeiten verwenden können.