headers

Los encabezados 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 con objetos que tengan las propiedades source y headers:

  • source: es el patrón de ruta de la solicitud entrante.
  • headers: es un 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 coincidir, solo se puede usar para reescrituras externas.
  • locale: false o undefined - indica si no se debe incluir la configuración regional al hacer coincidir.
  • has: es un array de objetos has con las propiedades type, key y value.
  • missing: es un array de objetos missing con las propiedades type, key y value.

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

Comportamiento de Sobrescritura 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 de encabezado 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 se pueden usar en el valor
          },
          {
            key: 'x-slug-:slug', // Los parámetros coincidentes se pueden usar en la clave
            value: 'mi otro valor de encabezado personalizado',
          },
        ],
      },
    ]
  },
}

Coincidencia de Rutas con Comodín

Para hacer coincidir una ruta con 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 se pueden usar en el valor
          },
          {
            key: 'x-slug-:slug*', // Los parámetros coincidentes se pueden usar en la clave
            value: 'mi otro valor de encabezado personalizado',
          },
        ],
      },
    ]
  },
}

Coincidencia de Rutas con Expresiones Regulares

Para hacer coincidir una ruta con expresión regular, puede envolver la expresión regular 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 coincidencias de rutas con expresiones regulares, 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 Consultas

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

Los elementos has y missing pueden tener los siguientes campos:

  • type: String - debe ser header, cookie, host o query.
  • key: String - la clave del tipo seleccionado con la que coincidir.
  • value: String o undefined - el valor a verificar, si es undefined, cualquier valor coincidirá. Se puede usar una cadena similar a regex para capturar una parte específica del valor, por ejemplo, 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 la fuente, la consulta y la cookie,
      // se aplicará el encabezado `x-authorized`
      {
        source: '/specific/:path*',
        has: [
          {
            type: 'query',
            key: 'page',
            // el valor de la página no estará disponible en las
            // claves/valores del encabezado ya que se proporciona un valor
            // y no se usa un grupo de captura con nombre, por ejemplo (?<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 soporte para 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 soporte para 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 los 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

Next.js establece el encabezado Cache-Control como public, max-age=31536000, immutable para recursos verdaderamente inmutables. Esto no se puede sobrescribir. Estos archivos inmutables contienen un hash SHA en el nombre del archivo, por lo que se pueden almacenar en caché indefinidamente de forma segura. Por ejemplo, Importación de imágenes estáticas. No puede establecer encabezados Cache-Control en next.config.js para estos recursos.

Sin embargo, puede establecer encabezados Cache-Control para otras respuestas o datos.

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

Para almacenar en caché la respuesta de una Ruta API, puede usar 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!' })
}

También puede usar encabezados de caché (Cache-Control) dentro de getServerSideProps para almacenar en caché respuestas dinámicas. Por ejemplo, usando stale-while-revalidate.

import { GetStaticProps, GetStaticPaths, GetServerSideProps } from 'next'

// Este valor se considera fresco durante diez segundos (s-maxage=10).
// Si se repite una solicitud dentro de los próximos 10 segundos, el valor
// previamente almacenado en caché seguirá siendo fresco. Si la solicitud se repite antes de 59 segundos,
// el valor en caché estará obsoleto pero aún se renderizará (stale-while-revalidate=59).
//
// En segundo plano, se realizará una solicitud de revalidación para actualizar la caché
// con un valor fresco. Si actualiza la página, verá el nuevo valor.
export const getServerSideProps = (async (context) => {
  context.res.setHeader(
    'Cache-Control',
    'public, s-maxage=10, stale-while-revalidate=59'
  )

  return {
    props: {},
  }
}) satisfies GetServerSideProps

Opciones

CORS

Intercambio de Recursos de Origen Cruzado (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 Puntos Finales 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 búsqueda previa 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 búsqueda previa 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 se debe acceder mediante HTTPS, en lugar de HTTP. Usando la configuración a continuación, todos los subdominios presentes y futuros usarán HTTPS durante un max-age de 2 años. Esto bloquea el acceso a páginas o subdominios que solo se pueden servir mediante HTTP.

{
  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 (consulte Política de Seguridad de Contenido para detalles de configuración).

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

Permissions-Policy (Política de Permisos)

Este encabezado permite controlar qué características y APIs pueden utilizarse 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á configurado explícitamente. Esto puede prevenir exploits XSS en sitios web que permiten a los usuarios subir y compartir archivos.

Por ejemplo, si un usuario intenta descargar una imagen pero esta es tratada como un tipo de Content-Type diferente, como un ejecutable, lo cual 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 (Política de Referencia)

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

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

Content-Security-Policy (Política de Seguridad de Contenido)

Obtenga más información sobre cómo agregar una Política de Seguridad de Contenido (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.