Routes API
Exemples
Bon à savoir : Si vous utilisez le routeur App, vous pouvez utiliser les Composants Serveur ou les Gestionnaires de Route à la place des routes API.
Les routes API offrent une solution pour construire une API publique avec Next.js.
Tout fichier dans le dossier pages/api
est mappé vers /api/*
et sera traité comme un point de terminaison API plutôt qu'une page
. Ce sont des bundles côté serveur uniquement et n'augmenteront pas la taille de votre bundle côté client.
Par exemple, la route API suivante renvoie une réponse JSON avec un code de statut 200
:
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!' })
}
Bon à savoir :
- Les routes API ne spécifient pas d'en-têtes CORS, ce qui signifie qu'elles sont same-origin only par défaut. Vous pouvez personnaliser ce comportement en enveloppant le gestionnaire de requête avec les helpers de requête CORS.
- Les routes API ne peuvent pas être utilisées avec les exports statiques. Cependant, les Gestionnaires de Route dans le routeur App le peuvent.
- Les routes API seront affectées par la configuration
pageExtensions
dansnext.config.js
.
Paramètres
export default function handler(req: NextApiRequest, res: NextApiResponse) {
// ...
}
req
: Une instance de http.IncomingMessage, plus quelques middlewares pré-construitsres
: Une instance de http.ServerResponse, plus quelques fonctions helpers
Méthodes HTTP
Pour gérer différentes méthodes HTTP dans une route API, vous pouvez utiliser req.method
dans votre gestionnaire de requête, comme ceci :
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'POST') {
// Traiter une requête POST
} else {
// Gérer toute autre méthode HTTP
}
}
export default function handler(req, res) {
if (req.method === 'POST') {
// Traiter une requête POST
} else {
// Gérer toute autre méthode HTTP
}
}
Helpers de Requête
Les routes API fournissent des helpers de requête intégrés qui analysent la requête entrante (req
) :
req.cookies
- Un objet contenant les cookies envoyés par la requête. Par défaut{}
req.query
- Un objet contenant la chaîne de requête. Par défaut{}
req.body
- Un objet contenant le corps analysé parcontent-type
, ounull
si aucun corps n'a été envoyé
Configuration personnalisée
Chaque route API peut exporter un objet config
pour modifier la configuration par défaut, qui est la suivante :
export const config = {
api: {
bodyParser: {
sizeLimit: '1mb',
},
},
// Spécifie la durée maximale autorisée pour l'exécution de cette fonction (en secondes)
maxDuration: 5,
}
bodyParser
est activé automatiquement. Si vous souhaitez consommer le corps comme un Stream
ou avec raw-body
, vous pouvez le désactiver en le mettant à false
.
Un cas d'utilisation pour désactiver le bodyParsing
automatique est de vous permettre de vérifier le corps brut d'une requête webhook, par exemple depuis GitHub.
export const config = {
api: {
bodyParser: false,
},
}
bodyParser.sizeLimit
est la taille maximale autorisée pour le corps analysé, dans n'importe quel format pris en charge par bytes, comme ceci :
export const config = {
api: {
bodyParser: {
sizeLimit: '500kb',
},
},
}
externalResolver
est un drapeau explicite qui indique au serveur que cette route est gérée par un résolveur externe comme express ou connect. Activer cette option désactive les avertissements pour les requêtes non résolues.
export const config = {
api: {
externalResolver: true,
},
}
responseLimit
est activé automatiquement, avertissant lorsque le corps de la réponse d'une route API dépasse 4Mo.
Si vous n'utilisez pas Next.js dans un environnement serverless, et que vous comprenez les implications en termes de performance de ne pas utiliser un CDN ou un hébergement média dédié, vous pouvez désactiver cette limite en la mettant à false
.
export const config = {
api: {
responseLimit: false,
},
}
responseLimit
peut aussi prendre un nombre d'octets ou n'importe quelle chaîne de format prise en charge par bytes
, par exemple 1000
, '500kb'
ou '3mb'
.
Cette valeur sera la taille maximale de la réponse avant qu'un avertissement ne soit affiché. Par défaut 4Mo (voir ci-dessus).
export const config = {
api: {
responseLimit: '8mb',
},
}
Helpers de Réponse
L'objet Server Response, (souvent abrégé en res
) inclut un ensemble de méthodes helpers de type Express.js pour améliorer l'expérience développeur et accélérer la création de nouveaux points de terminaison API.
Les helpers inclus sont :
res.status(code)
- Une fonction pour définir le code de statut.code
doit être un code de statut HTTP valideres.json(body)
- Envoie une réponse JSON.body
doit être un objet sérialisableres.send(body)
- Envoie la réponse HTTP.body
peut être unestring
, unobject
ou unBuffer
res.redirect([status,] path)
- Redirige vers un chemin ou une URL spécifiée.status
doit être un code de statut HTTP valide. Si non spécifié,status
est par défaut "307" "Redirection temporaire".res.revalidate(urlPath)
- Revalider une page à la demande en utilisantgetStaticProps
.urlPath
doit être unestring
.
Définir le code de statut d'une réponse
Lors de l'envoi d'une réponse au client, vous pouvez définir le code de statut de la réponse.
L'exemple suivant définit le code de statut de la réponse à 200
(OK
) et renvoie une propriété message
avec la valeur Hello from Next.js!
comme réponse JSON :
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!' })
}
Envoyer une réponse JSON
Lors de l'envoi d'une réponse au client, vous pouvez envoyer une réponse JSON, qui doit être un objet sérialisable. Dans une application réelle, vous pourriez vouloir informer le client du statut de la requête en fonction du résultat du point de terminaison demandé.
L'exemple suivant envoie une réponse JSON avec le code de statut 200
(OK
) et le résultat de l'opération asynchrone. Il est contenu dans un bloc try catch pour gérer les erreurs qui pourraient survenir, avec le code de statut et le message d'erreur appropriés capturés et renvoyés au client :
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' })
}
}
Envoyer une réponse HTTP
L'envoi d'une réponse HTTP fonctionne de la même manière que l'envoi d'une réponse JSON. La seule différence est que le corps de la réponse peut être une string
, un object
ou un Buffer
.
L'exemple suivant envoie une réponse HTTP avec le code de statut 200
(OK
) et le résultat de l'opération asynchrone.
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' })
}
}
Rediriger vers un chemin ou une URL spécifié
Prenant un formulaire comme exemple, vous pourriez vouloir rediriger votre client vers un chemin ou une URL spécifié une fois qu'il a soumis le formulaire.
L'exemple suivant redirige le client vers le chemin /
si le formulaire est soumis avec succès :
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' })
}
}
Ajouter des types TypeScript
Vous pouvez rendre vos routes API plus type-safe en important les types NextApiRequest
et NextApiResponse
de next
, en plus de ceux-ci, vous pouvez aussi typer vos données de réponse :
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!' })
}
Bon à savoir : Le corps de
NextApiRequest
estany
car le client peut inclure n'importe quelle charge utile. Vous devriez valider le type/la forme du corps à l'exécution avant de l'utiliser.
Routes API Dynamiques
Les routes API prennent en charge les routes dynamiques, et suivent les mêmes règles de nommage de fichiers que pour 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}`)
}
Maintenant, une requête vers /api/post/abc
répondra avec le texte : Post: abc
.
Routes API catch all
Les routes API peuvent être étendues pour capturer tous les chemins en ajoutant trois points (...
) à l'intérieur des crochets. Par exemple :
pages/api/post/[...slug].js
correspondra à/api/post/a
, mais aussi à/api/post/a/b
,/api/post/a/b/c
, etc.
Bon à savoir : Vous pouvez utiliser d'autres noms que
slug
, comme :[...param]
Les paramètres correspondants seront envoyés comme paramètre de requête (slug
dans l'exemple) à la page, et ce sera toujours un tableau, donc, le chemin /api/post/a
aura l'objet query
suivant :
{ "slug": ["a"] }
Et dans le cas de /api/post/a/b
, et tout autre chemin correspondant, de nouveaux paramètres seront ajoutés au tableau, comme ceci :
{ "slug": ["a", "b"] }
Par exemple :
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(', ')}`)
}
Maintenant, une requête vers /api/post/a/b/c
répondra avec le texte : Post: a, b, c
.
Routes API catch all optionnelles
Les routes catch all peuvent être rendues optionnelles en incluant le paramètre dans des doubles crochets ([[...slug]]
).
Par exemple, pages/api/post/[[...slug]].js
correspondra à /api/post
, /api/post/a
, /api/post/a/b
, etc.
La principale différence entre les routes catch all et catch all optionnelles est qu'avec les optionnelles, la route sans le paramètre est aussi correspondante (/api/post
dans l'exemple ci-dessus).
Les objets query
sont les suivants :
{ } // GET `/api/post` (objet vide)
{ "slug": ["a"] } // `GET /api/post/a` (tableau à un élément)
{ "slug": ["a", "b"] } // `GET /api/post/a/b` (tableau à plusieurs éléments)
Mises en garde
- Les routes API prédéfinies prennent le pas sur les routes API dynamiques, et les routes API dynamiques prennent le pas sur les routes API catch all. Regardez les exemples suivants :
pages/api/post/create.js
- Correspondra à/api/post/create
pages/api/post/[pid].js
- Correspondra à/api/post/1
,/api/post/abc
, etc. Mais pas à/api/post/create
pages/api/post/[...slug].js
- Correspondra à/api/post/1/2
,/api/post/a/b/c
, etc. Mais pas à/api/post/create
,/api/post/abc
Routes API Edge
Si vous souhaitez utiliser les routes API avec le runtime Edge, nous recommandons d'adopter progressivement le routeur App et d'utiliser les Gestionnaires de Route à la place.
La signature de fonction des Gestionnaires de Route est isomorphe, ce qui signifie que vous pouvez utiliser la même fonction pour les runtimes Edge et Node.js.