En-têtes HTTP
Les en-têtes (headers) vous permettent de définir des en-têtes HTTP personnalisés dans la réponse à une requête entrante sur un chemin donné.
Pour définir des en-têtes HTTP personnalisés, vous pouvez utiliser la clé headers
dans next.config.js
:
module.exports = {
async headers() {
return [
{
source: '/about',
headers: [
{
key: 'x-custom-header',
value: 'ma valeur d\'en-tête personnalisée',
},
{
key: 'x-another-custom-header',
value: 'mon autre valeur d\'en-tête personnalisée',
},
],
},
]
},
}
headers
est une fonction asynchrone qui attend un tableau d'objets avec les propriétés source
et headers
:
source
: le modèle de chemin de la requête entrante.headers
: un tableau d'objets d'en-têtes de réponse, avec les propriétéskey
etvalue
.basePath
:false
ouundefined
- si false, le basePath ne sera pas inclus lors de la correspondance, peut être utilisé uniquement pour les réécritures externes.locale
:false
ouundefined
- indique si la locale ne doit pas être incluse lors de la correspondance.has
: un tableau d'objets has avec les propriétéstype
,key
etvalue
.missing
: un tableau d'objets missing avec les propriétéstype
,key
etvalue
.
Les en-têtes sont vérifiés avant le système de fichiers, qui inclut les pages et les fichiers /public
.
Comportement de substitution des en-têtes
Si deux en-têtes correspondent au même chemin et définissent la même clé d'en-tête, la dernière clé d'en-tête remplacera la première. Avec les en-têtes ci-dessous, le chemin /hello
entraînera l'en-tête x-hello
étant world
car la dernière valeur définie est world
.
module.exports = {
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'x-hello',
value: 'there',
},
],
},
{
source: '/hello',
headers: [
{
key: 'x-hello',
value: 'world',
},
],
},
]
},
}
Correspondance de chemin
Les correspondances de chemin sont autorisées, par exemple /blog/:slug
correspondra à /blog/hello-world
(pas de chemins imbriqués) :
module.exports = {
async headers() {
return [
{
source: '/blog/:slug',
headers: [
{
key: 'x-slug',
value: ':slug', // Les paramètres correspondants peuvent être utilisés dans la valeur
},
{
key: 'x-slug-:slug', // Les paramètres correspondants peuvent être utilisés dans la clé
value: 'mon autre valeur d\'en-tête personnalisée',
},
],
},
]
},
}
Correspondance de chemin avec joker
Pour correspondre à un chemin avec joker, vous pouvez utiliser *
après un paramètre, par exemple /blog/:slug*
correspondra à /blog/a/b/c/d/hello-world
:
module.exports = {
async headers() {
return [
{
source: '/blog/:slug*',
headers: [
{
key: 'x-slug',
value: ':slug*', // Les paramètres correspondants peuvent être utilisés dans la valeur
},
{
key: 'x-slug-:slug*', // Les paramètres correspondants peuvent être utilisés dans la clé
value: 'mon autre valeur d\'en-tête personnalisée',
},
],
},
]
},
}
Correspondance de chemin avec regex
Pour correspondre à un chemin avec regex, vous pouvez encapsuler la regex entre parenthèses après un paramètre, par exemple /blog/:slug(\\d{1,})
correspondra à /blog/123
mais pas à /blog/abc
:
module.exports = {
async headers() {
return [
{
source: '/blog/:post(\\d{1,})',
headers: [
{
key: 'x-post',
value: ':post',
},
],
},
]
},
}
Les caractères suivants (
, )
, {
, }
, :
, *
, +
, ?
sont utilisés pour la correspondance de chemin avec regex, donc lorsqu'ils sont utilisés dans source
comme valeurs non spéciales, ils doivent être échappés en ajoutant \\
avant eux :
module.exports = {
async headers() {
return [
{
// cela correspondra à `/english(default)/something` demandé
source: '/english\\(default\\)/:slug',
headers: [
{
key: 'x-header',
value: 'value',
},
],
},
]
},
}
Correspondance d'en-tête, de cookie et de requête
Pour appliquer un en-tête uniquement lorsque les valeurs d'en-tête, de cookie ou de requête correspondent également au champ has
ou ne correspondent pas au champ missing
, vous pouvez utiliser ces champs. À la fois source
et tous les éléments has
doivent correspondre, et tous les éléments missing
ne doivent pas correspondre pour que l'en-tête soit appliqué.
Les éléments has
et missing
peuvent avoir les champs suivants :
type
:String
- doit être soitheader
,cookie
,host
, ouquery
.key
:String
- la clé du type sélectionné à comparer.value
:String
ouundefined
- la valeur à vérifier, si undefined n'importe quelle valeur correspondra. Une chaîne de type regex peut être utilisée pour capturer une partie spécifique de la valeur, par exemple si la valeurfirst-(?<paramName>.*)
est utilisée pourfirst-second
, alorssecond
sera utilisable dans la destination avec:paramName
.
module.exports = {
async headers() {
return [
// si l'en-tête `x-add-header` est présent,
// l'en-tête `x-another-header` sera appliqué
{
source: '/:path*',
has: [
{
type: 'header',
key: 'x-add-header',
},
],
headers: [
{
key: 'x-another-header',
value: 'hello',
},
],
},
// si l'en-tête `x-no-header` n'est pas présent,
// l'en-tête `x-another-header` sera appliqué
{
source: '/:path*',
missing: [
{
type: 'header',
key: 'x-no-header',
},
],
headers: [
{
key: 'x-another-header',
value: 'hello',
},
],
},
// si la source, la requête et le cookie correspondent,
// l'en-tête `x-authorized` sera appliqué
{
source: '/specific/:path*',
has: [
{
type: 'query',
key: 'page',
// la valeur de page ne sera pas disponible dans les
// clés/valeurs d'en-tête car value est fournie et
// n'utilise pas un groupe de capture nommé, par exemple (?<page>home)
value: 'home',
},
{
type: 'cookie',
key: 'authorized',
value: 'true',
},
],
headers: [
{
key: 'x-authorized',
value: ':authorized',
},
],
},
// si l'en-tête `x-authorized` est présent et
// contient une valeur correspondante, l'en-tête `x-another-header` sera appliqué
{
source: '/:path*',
has: [
{
type: 'header',
key: 'x-authorized',
value: '(?<authorized>yes|true)',
},
],
headers: [
{
key: 'x-another-header',
value: ':authorized',
},
],
},
// si l'hôte est `example.com`,
// cet en-tête sera appliqué
{
source: '/:path*',
has: [
{
type: 'host',
value: 'example.com',
},
],
headers: [
{
key: 'x-another-header',
value: ':authorized',
},
],
},
]
},
}
En-têtes avec support de basePath
Lorsque vous utilisez le support de basePath
avec des en-têtes, chaque source
est automatiquement préfixé avec le basePath
sauf si vous ajoutez basePath: false
à l'en-tête :
module.exports = {
basePath: '/docs',
async headers() {
return [
{
source: '/with-basePath', // devient /docs/with-basePath
headers: [
{
key: 'x-hello',
value: 'world',
},
],
},
{
source: '/without-basePath', // n'est pas modifié car basePath: false est défini
headers: [
{
key: 'x-hello',
value: 'world',
},
],
basePath: false,
},
]
},
}
En-têtes avec support i18n
Lorsque vous utilisez le support i18n
avec des en-têtes, chaque source
est automatiquement préfixé pour gérer les locales
configurées, sauf si vous ajoutez locale: false
à l'en-tête. Si locale: false
est utilisé, vous devez préfixer la source
avec une locale pour qu'elle corresponde correctement.
module.exports = {
i18n: {
locales: ['en', 'fr', 'de'],
defaultLocale: 'en',
},
async headers() {
return [
{
source: '/with-locale', // gère automatiquement toutes les locales
headers: [
{
key: 'x-hello',
value: 'world',
},
],
},
{
// ne gère pas automatiquement les locales car locale: false est défini
source: '/nl/with-locale-manual',
locale: false,
headers: [
{
key: 'x-hello',
value: 'world',
},
],
},
{
// cela correspond à '/' car `en` est la defaultLocale
source: '/en',
locale: false,
headers: [
{
key: 'x-hello',
value: 'world',
},
],
},
{
// cela est converti en /(en|fr|de)/(.*) donc ne correspondra pas aux routes
// de niveau supérieur `/` ou `/fr` comme /:path* le ferait
source: '/(.*)',
headers: [
{
key: 'x-hello',
value: 'world',
},
],
},
]
},
}
Cache-Control
Vous ne pouvez pas définir les en-têtes Cache-Control
dans next.config.js
pour les pages ou les ressources, car ces en-têtes seront écrasés en production pour garantir que les réponses et les ressources statiques sont mises en cache efficacement.
Si vous avez besoin de revalider le cache d'une page qui a été générée statiquement, vous pouvez le faire en définissant la prop revalidate
dans la fonction getStaticProps
de la page.
Vous pouvez définir l'en-tête Cache-Control
dans vos routes API en utilisant la méthode res.setHeader
:
import type { NextApiRequest, NextApiResponse } from 'next'
type ResponseData = {
message: string
}
export default function handler(
req: NextApiRequest,
res: NextApiResponse<ResponseData>
) {
res.setHeader('Cache-Control', 's-maxage=86400')
res.status(200).json({ message: 'Hello from Next.js!' })
}
export default function handler(req, res) {
res.setHeader('Cache-Control', 's-maxage=86400')
res.status(200).json({ message: 'Hello from Next.js!' })
}
Options
CORS
Cross-Origin Resource Sharing (CORS) est une fonctionnalité de sécurité qui vous permet de contrôler quels sites peuvent accéder à vos ressources. Vous pouvez définir l'en-tête Access-Control-Allow-Origin
pour autoriser une origine spécifique à accéder à vos points de terminaison API.
async headers() {
return [
{
source: "/api/:path*",
headers: [
{
key: "Access-Control-Allow-Origin",
value: "*", // Définissez votre origine
},
{
key: "Access-Control-Allow-Methods",
value: "GET, POST, PUT, DELETE, OPTIONS",
},
{
key: "Access-Control-Allow-Headers",
value: "Content-Type, Authorization",
},
],
},
];
},
X-DNS-Prefetch-Control
Cet en-tête contrôle la pré-résolution DNS, permettant aux navigateurs d'effectuer proactivement la résolution de nom de domaine sur les liens externes, images, CSS, JavaScript, etc. Cette pré-résolution est effectuée en arrière-plan, donc le DNS est plus susceptible d'être résolu au moment où les éléments référencés sont nécessaires. Cela réduit la latence lorsque l'utilisateur clique sur un lien.
{
key: 'X-DNS-Prefetch-Control',
value: 'on'
}
Strict-Transport-Security
Cet en-tête informe les navigateurs qu'ils ne doivent accéder qu'en utilisant HTTPS, au lieu de HTTP. Avec la configuration ci-dessous, tous les sous-domaines présents et futurs utiliseront HTTPS pour une durée de max-age
de 2 ans. Cela bloque l'accès aux pages ou sous-domaines qui ne peuvent être servis qu'en HTTP.
Si vous déployez sur Vercel, cet en-tête n'est pas nécessaire car il est automatiquement ajouté à tous les déploiements sauf si vous déclarez headers
dans votre next.config.js
.
{
key: 'Strict-Transport-Security',
value: 'max-age=63072000; includeSubDomains; preload'
}
X-Frame-Options
Cet en-tête indique si le site doit être autorisé à être affiché dans un iframe
. Cela peut prévenir les attaques de clickjacking.
Cet en-tête a été remplacé par l'option frame-ancestors
de CSP, qui a un meilleur support dans les navigateurs modernes (voir Content Security Policy pour les détails de configuration).
{
key: 'X-Frame-Options',
value: 'SAMEORIGIN'
}
Permissions-Policy
Cet en-tête vous permet de contrôler quelles fonctionnalités et API peuvent être utilisées dans le navigateur. Il était précédemment nommé Feature-Policy
.
{
key: 'Permissions-Policy',
value: 'camera=(), microphone=(), geolocation=(), browsing-topics=()'
}
X-Content-Type-Options
Cet en-tête empêche le navigateur de tenter de deviner le type de contenu si l'en-tête Content-Type
n'est pas explicitement défini. Cela peut prévenir les exploits XSS pour les sites qui permettent aux utilisateurs de télécharger et partager des fichiers.
Par exemple, un utilisateur essayant de télécharger une image, mais celle-ci est traitée comme un autre Content-Type
comme un exécutable, qui pourrait être malveillant. Cet en-tête s'applique également au téléchargement d'extensions de navigateur. La seule valeur valide pour cet en-tête est nosniff
.
{
key: 'X-Content-Type-Options',
value: 'nosniff'
}
Referrer-Policy
Cet en-tête contrôle la quantité d'informations que le navigateur inclut lors de la navigation du site web actuel (origine) vers un autre.
{
key: 'Referrer-Policy',
value: 'origin-when-cross-origin'
}
Content-Security-Policy
Apprenez-en plus sur l'ajout d'une Content Security Policy à votre application.
Historique des versions
Version | Changements |
---|---|
v13.3.0 | missing ajouté. |
v10.2.0 | has ajouté. |
v9.5.0 | En-têtes ajoutés. |