Encabezados (headers)

Los encabezados le permiten establecer encabezados HTTP personalizados en la respuesta a una solicitud entrante en una ruta determinada.

Para establecer encabezados HTTP personalizados, puede usar la clave headers en next.config.js:

next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/about',
        headers: [
          {
            key: 'x-custom-header',
            value: 'mi valor de encabezado personalizado',
          },
          {
            key: 'x-another-custom-header',
            value: 'mi otro valor de encabezado personalizado',
          },
        ],
      },
    ]
  },
}

headers es una función asíncrona que espera que se devuelva un array conteniendo objetos con propiedades source y headers:

  • source: patrón de ruta de la solicitud entrante.
  • headers: array de objetos de encabezado de respuesta, con propiedades key y value.
  • basePath: false o undefined - si es false, el basePath no se incluirá al hacer coincidencias, solo se puede usar para reescrituras externas.
  • locale: false o undefined - indica si no se debe incluir la configuración regional al hacer coincidencias.
  • has: array de objetos has con propiedades type, key y value.
  • missing: array de objetos missing con propiedades type, key y value.

Los encabezados se verifican antes del sistema de archivos, que incluye páginas y archivos en /public.

Comportamiento de Sobreescritura de Encabezados

Si dos encabezados coinciden con la misma ruta y establecen la misma clave de encabezado, la última clave de encabezado sobrescribirá la primera. Usando los siguientes encabezados, la ruta /hello resultará en que el encabezado x-hello sea world debido a que el último valor establecido es world.

next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'x-hello',
            value: 'there',
          },
        ],
      },
      {
        source: '/hello',
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
      },
    ]
  },
}

Coincidencia de Rutas

Se permiten coincidencias de rutas, por ejemplo /blog/:slug coincidirá con /blog/hello-world (sin rutas anidadas):

next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/blog/:slug',
        headers: [
          {
            key: 'x-slug',
            value: ':slug', // Los parámetros coincidentes pueden usarse en el valor
          },
          {
            key: 'x-slug-:slug', // Los parámetros coincidentes pueden usarse en la clave
            value: 'mi otro valor de encabezado personalizado',
          },
        ],
      },
    ]
  },
}

Coincidencia de Rutas con Comodín

Para coincidir con una ruta comodín puede usar * después de un parámetro, por ejemplo /blog/:slug* coincidirá con /blog/a/b/c/d/hello-world:

next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/blog/:slug*',
        headers: [
          {
            key: 'x-slug',
            value: ':slug*', // Los parámetros coincidentes pueden usarse en el valor
          },
          {
            key: 'x-slug-:slug*', // Los parámetros coincidentes pueden usarse en la clave
            value: 'mi otro valor de encabezado personalizado',
          },
        ],
      },
    ]
  },
}

Coincidencia de Rutas con Expresiones Regulares

Para coincidir con una ruta de expresión regular puede envolver la regex entre paréntesis después de un parámetro, por ejemplo /blog/:slug(\\d{1,}) coincidirá con /blog/123 pero no con /blog/abc:

next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/blog/:post(\\d{1,})',
        headers: [
          {
            key: 'x-post',
            value: ':post',
          },
        ],
      },
    ]
  },
}

Los siguientes caracteres (, ), {, }, :, *, +, ? se usan para coincidencia de rutas con regex, por lo que cuando se usan en source como valores no especiales deben escaparse agregando \\ antes de ellos:

next.config.js
module.exports = {
  async headers() {
    return [
      {
        // esto coincidirá con `/english(default)/something` cuando se solicite
        source: '/english\\(default\\)/:slug',
        headers: [
          {
            key: 'x-header',
            value: 'value',
          },
        ],
      },
    ]
  },
}

Coincidencia de Encabezados, Cookies y Queries

Para aplicar un encabezado solo cuando los valores de encabezado, cookie o query también coincidan, se puede usar el campo has o no coincidan con el campo missing. Tanto source como todos los items has deben coincidir y todos los items missing no deben coincidir para que se aplique el encabezado.

Los items has y missing pueden tener los siguientes campos:

  • type: String - debe ser header, cookie, host o query.
  • key: String - la clave del tipo seleccionado para comparar.
  • value: String o undefined - el valor a verificar, si es undefined cualquier valor coincidirá. Se puede usar una cadena tipo regex para capturar una parte específica del valor, ej. si se usa el valor first-(?<paramName>.*) para first-second entonces second se podrá usar en el destino con :paramName.
next.config.js
module.exports = {
  async headers() {
    return [
      // si el encabezado `x-add-header` está presente,
      // se aplicará el encabezado `x-another-header`
      {
        source: '/:path*',
        has: [
          {
            type: 'header',
            key: 'x-add-header',
          },
        ],
        headers: [
          {
            key: 'x-another-header',
            value: 'hello',
          },
        ],
      },
      // si el encabezado `x-no-header` no está presente,
      // se aplicará el encabezado `x-another-header`
      {
        source: '/:path*',
        missing: [
          {
            type: 'header',
            key: 'x-no-header',
          },
        ],
        headers: [
          {
            key: 'x-another-header',
            value: 'hello',
          },
        ],
      },
      // si coinciden source, query y cookie,
      // se aplicará el encabezado `x-authorized`
      {
        source: '/specific/:path*',
        has: [
          {
            type: 'query',
            key: 'page',
            // el valor page no estará disponible en las
            // claves/valores del encabezado ya que se provee value
            // y no usa un grupo de captura nombrado ej. (?<page>home)
            value: 'home',
          },
          {
            type: 'cookie',
            key: 'authorized',
            value: 'true',
          },
        ],
        headers: [
          {
            key: 'x-authorized',
            value: ':authorized',
          },
        ],
      },
      // si el encabezado `x-authorized` está presente y
      // contiene un valor coincidente, se aplicará `x-another-header`
      {
        source: '/:path*',
        has: [
          {
            type: 'header',
            key: 'x-authorized',
            value: '(?<authorized>yes|true)',
          },
        ],
        headers: [
          {
            key: 'x-another-header',
            value: ':authorized',
          },
        ],
      },
      // si el host es `example.com`,
      // se aplicará este encabezado
      {
        source: '/:path*',
        has: [
          {
            type: 'host',
            value: 'example.com',
          },
        ],
        headers: [
          {
            key: 'x-another-header',
            value: ':authorized',
          },
        ],
      },
    ]
  },
}

Encabezados con soporte para basePath

Cuando se usa basePath con encabezados, cada source se prefija automáticamente con el basePath a menos que agregue basePath: false al encabezado:

next.config.js
module.exports = {
  basePath: '/docs',

  async headers() {
    return [
      {
        source: '/with-basePath', // se convierte en /docs/with-basePath
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
      },
      {
        source: '/without-basePath', // no se modifica ya que se establece basePath: false
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
        basePath: false,
      },
    ]
  },
}

Encabezados con soporte para i18n

Cuando se usa i18n con encabezados, cada source se prefija automáticamente para manejar los locales configurados a menos que agregue locale: false al encabezado. Si se usa locale: false, debe prefijar el source con un locale para que coincida correctamente.

next.config.js
module.exports = {
  i18n: {
    locales: ['en', 'fr', 'de'],
    defaultLocale: 'en',
  },

  async headers() {
    return [
      {
        source: '/with-locale', // maneja automáticamente todos los locales
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
      },
      {
        // no maneja locales automáticamente ya que se establece locale: false
        source: '/nl/with-locale-manual',
        locale: false,
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
      },
      {
        // esto coincide con '/' ya que `en` es el defaultLocale
        source: '/en',
        locale: false,
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
      },
      {
        // esto se convierte a /(en|fr|de)/(.*) por lo que no coincidirá con
        // las rutas de nivel superior `/` o `/fr` como lo haría /:path*
        source: '/(.*)',
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
      },
    ]
  },
}

Cache-Control

No puede establecer encabezados Cache-Control en next.config.js para páginas o assets, ya que estos encabezados se sobrescribirán en producción para garantizar que las respuestas y assets estáticos se almacenen en caché de manera efectiva.

Si necesita revalidar la caché de una página que ha sido generada estáticamente, puede hacerlo estableciendo la prop revalidate en la función getStaticProps de la página.

Puede establecer el encabezado Cache-Control en sus Rutas API usando el método 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!' })
}

Opciones

CORS

Cross-Origin Resource Sharing (CORS) es una característica de seguridad que le permite controlar qué sitios pueden acceder a sus recursos. Puede establecer el encabezado Access-Control-Allow-Origin para permitir que un origen específico acceda a sus Endpoints API.

async headers() {
    return [
      {
        source: "/api/:path*",
        headers: [
          {
            key: "Access-Control-Allow-Origin",
            value: "*", // Establezca su origen
          },
          {
            key: "Access-Control-Allow-Methods",
            value: "GET, POST, PUT, DELETE, OPTIONS",
          },
          {
            key: "Access-Control-Allow-Headers",
            value: "Content-Type, Authorization",
          },
        ],
      },
    ];
  },

X-DNS-Prefetch-Control

Este encabezado controla la precarga de DNS, permitiendo que los navegadores realicen proactivamente la resolución de nombres de dominio en enlaces externos, imágenes, CSS, JavaScript y más. Esta precarga se realiza en segundo plano, por lo que es más probable que el DNS se resuelva cuando se necesiten los elementos referenciados. Esto reduce la latencia cuando el usuario hace clic en un enlace.

{
  key: 'X-DNS-Prefetch-Control',
  value: 'on'
}

Strict-Transport-Security

Este encabezado informa a los navegadores que solo debe accederse usando HTTPS, en lugar de HTTP. Usando la configuración a continuación, todos los subdominios presentes y futuros usarán HTTPS por un max-age de 2 años. Esto bloquea el acceso a páginas o subdominios que solo pueden servirse mediante HTTP.

Si está implementando en Vercel, este encabezado no es necesario ya que se agrega automáticamente a todas las implementaciones a menos que declare headers en su next.config.js.

{
  key: 'Strict-Transport-Security',
  value: 'max-age=63072000; includeSubDomains; preload'
}

X-Frame-Options

Este encabezado indica si el sitio debe permitirse mostrar dentro de un iframe. Esto puede prevenir ataques de clickjacking.

Este encabezado ha sido reemplazado por la opción frame-ancestors de CSP, que tiene mejor soporte en navegadores modernos (ver Content Security Policy para detalles de configuración).

{
  key: 'X-Frame-Options',
  value: 'SAMEORIGIN'
}

Permissions-Policy

Este encabezado le permite controlar qué características y APIs pueden usarse en el navegador. Anteriormente se llamaba Feature-Policy.

{
  key: 'Permissions-Policy',
  value: 'camera=(), microphone=(), geolocation=(), browsing-topics=()'
}

X-Content-Type-Options

Este encabezado evita que el navegador intente adivinar el tipo de contenido si el encabezado Content-Type no está explícitamente establecido. Esto puede prevenir exploits XSS para sitios web que permiten a los usuarios subir y compartir archivos.

Por ejemplo, un usuario que intenta descargar una imagen, pero que se trata como un Content-Type diferente como un ejecutable, que podría ser malicioso. Este encabezado también aplica a la descarga de extensiones de navegador. El único valor válido para este encabezado es nosniff.

{
  key: 'X-Content-Type-Options',
  value: 'nosniff'
}

Referrer-Policy

Este encabezado controla cuánta información incluye el navegador cuando navega desde el sitio web actual (origen) a otro.

{
  key: 'Referrer-Policy',
  value: 'origin-when-cross-origin'
}

Content-Security-Policy

Aprenda más sobre cómo agregar una Content Security Policy a su aplicación.

Historial de Versiones

VersiónCambios
v13.3.0Se agregó missing.
v10.2.0Se agregó has.
v9.5.0Se agregaron encabezados.