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, um eine öffentliche API mit Next.js zu erstellen.

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 Größe Ihres clientseitigen Bundles.

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!' })
}

Gut zu wissen:

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 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
  }
}

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 von content-type geparsten Body oder null, 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 eines 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. Standardwert 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 Geschwindigkeit bei 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 bestimmten Pfad oder einer URL weiter. status muss ein gültiger HTTP-Statuscode sein. Wenn nicht angegeben, wird status standardmäßig auf "307" ("Temporary redirect") gesetzt.
  • res.revalidate(urlPath) - Revalidiert eine Seite bei Bedarf 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 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!' })
}

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 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 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' })
  }
}

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' })
  }
}

Weiterleitung zu einem bestimmten Pfad oder einer URL

Nehmen wir ein Formular als Beispiel: Möglicherweise möchten Sie Ihren Client 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:

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' })
  }
}

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 ist any, da der Client beliebige Daten 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}`)
}

Jetzt wird ein Request an /api/post/abc mit dem Text Post: abc beantwortet.

Catch-all-API-Routen

API-Routen können erweitert werden, um alle Pfade abzufangen, indem drei Punkte (...) in die Klammern gesetzt 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].

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(', ')}`)
}

Jetzt wird ein Request an /api/post/a/b/c mit dem Text Post: a, b, c beantwortet.

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)

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 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

Streaming-Antworten

Während der Pages-Router Streaming-Antworten mit API-Routen unterstützt, empfehlen wir die schrittweise Einführung des App-Routers und die Verwendung von Route Handlers, wenn Sie Next.js 14+ verwenden.

Hier ist ein Beispiel, wie Sie eine Response von einer API-Route mit writeHead streamen können:

pages/api/hello.js
import { NextApiRequest, NextApiResponse } from 'next'

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': "no-store",
  })
  let i = 0
  while (i < 10) {
    res.write(`data: ${i}\n\n`)
    i++
    await new Promise((resolve) => setTimeout(resolve, 1000))
  }
  res.end()
}