headers

標頭 (headers) 允許您在特定路徑的傳入請求回應中設置自訂 HTTP 標頭。

要設置自訂 HTTP 標頭,您可以在 next.config.js 中使用 headers 鍵:

next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/about',
        headers: [
          {
            key: 'x-custom-header',
            value: 'my custom header value',
          },
          {
            key: 'x-another-custom-header',
            value: 'my other custom header value',
          },
        ],
      },
    ]
  },
}

headers 是一個非同步函數,預期返回一個包含具有 sourceheaders 屬性的物件陣列:

  • source:傳入請求的路徑模式。
  • headers:回應標頭物件的陣列,具有 keyvalue 屬性。
  • basePathfalseundefined - 如果為 false,匹配時不會包含 basePath,僅可用於外部重寫。
  • localefalseundefined - 匹配時是否不包含語言環境。
  • has:具有 typekeyvalue 屬性的 has 物件 陣列。
  • missing:具有 typekeyvalue 屬性的 missing 物件 陣列。

標頭檢查優先於檔案系統,包括頁面和 /public 檔案。

標頭覆蓋行為

如果兩個標頭匹配相同路徑並設置相同的標頭鍵,最後一個標頭鍵將覆蓋第一個。使用以下標頭,路徑 /hello 將導致標頭 x-hello 的值為 world,因為最後設置的標頭值是 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',
          },
        ],
      },
    ]
  },
}

路徑匹配

允許路徑匹配,例如 /blog/:slug 將匹配 /blog/hello-world(不包含巢狀路徑):

next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/blog/:slug',
        headers: [
          {
            key: 'x-slug',
            value: ':slug', // 匹配的參數可用於值中
          },
          {
            key: 'x-slug-:slug', // 匹配的參數可用於鍵中
            value: 'my other custom header value',
          },
        ],
      },
    ]
  },
}

萬用字元路徑匹配

要匹配萬用字元路徑,您可以在參數後使用 *,例如 /blog/:slug* 將匹配 /blog/a/b/c/d/hello-world

next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/blog/:slug*',
        headers: [
          {
            key: 'x-slug',
            value: ':slug*', // 匹配的參數可用於值中
          },
          {
            key: 'x-slug-:slug*', // 匹配的參數可用於鍵中
            value: 'my other custom header value',
          },
        ],
      },
    ]
  },
}

正則表達式路徑匹配

要匹配正則表達式路徑,您可以將正則表達式包裹在參數後的括號中,例如 /blog/:slug(\\d{1,}) 將匹配 /blog/123 但不匹配 /blog/abc

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

以下字符 (){}:*+? 用於正則表達式路徑匹配,因此當在 source 中作為非特殊值使用時,必須在它們前面添加 \\ 進行轉義:

next.config.js
module.exports = {
  async headers() {
    return [
      {
        // 這將匹配請求的 `/english(default)/something`
        source: '/english\\(default\\)/:slug',
        headers: [
          {
            key: 'x-header',
            value: 'value',
          },
        ],
      },
    ]
  },
}

標頭、Cookie 和查詢匹配

僅當標頭、Cookie 或查詢值也匹配 has 欄位或不匹配 missing 欄位時,才應用標頭。source 和所有 has 項目必須匹配,且所有 missing 項目必須不匹配,標頭才會被應用。

hasmissing 項目可以具有以下欄位:

  • typeString - 必須是 headercookiehostquery 之一。
  • keyString - 要匹配的所選類型的鍵。
  • valueStringundefined - 要檢查的值,如果為 undefined,則任何值都將匹配。可以使用類似正則表達式的字符串來捕獲值的特定部分,例如,如果值 first-(?<paramName>.*) 用於 first-second,則 second 將在目標中使用 :paramName
next.config.js
module.exports = {
  async headers() {
    return [
      // 如果標頭 `x-add-header` 存在,
      // 將應用 `x-another-header` 標頭
      {
        source: '/:path*',
        has: [
          {
            type: 'header',
            key: 'x-add-header',
          },
        ],
        headers: [
          {
            key: 'x-another-header',
            value: 'hello',
          },
        ],
      },
      // 如果標頭 `x-no-header` 不存在,
      // 將應用 `x-another-header` 標頭
      {
        source: '/:path*',
        missing: [
          {
            type: 'header',
            key: 'x-no-header',
          },
        ],
        headers: [
          {
            key: 'x-another-header',
            value: 'hello',
          },
        ],
      },
      // 如果來源、查詢和 Cookie 都匹配,
      // 將應用 `x-authorized` 標頭
      {
        source: '/specific/:path*',
        has: [
          {
            type: 'query',
            key: 'page',
            // 由於提供了值且未使用命名捕獲組(例如 `(?<page>home)`),
            // 頁面值將不可用於標頭鍵/值
            value: 'home',
          },
          {
            type: 'cookie',
            key: 'authorized',
            value: 'true',
          },
        ],
        headers: [
          {
            key: 'x-authorized',
            value: ':authorized',
          },
        ],
      },
      // 如果標頭 `x-authorized` 存在且
      // 包含匹配的值,將應用 `x-another-header`
      {
        source: '/:path*',
        has: [
          {
            type: 'header',
            key: 'x-authorized',
            value: '(?<authorized>yes|true)',
          },
        ],
        headers: [
          {
            key: 'x-another-header',
            value: ':authorized',
          },
        ],
      },
      // 如果主機是 `example.com`,
      // 將應用此標頭
      {
        source: '/:path*',
        has: [
          {
            type: 'host',
            value: 'example.com',
          },
        ],
        headers: [
          {
            key: 'x-another-header',
            value: ':authorized',
          },
        ],
      },
    ]
  },
}

支援 basePath 的標頭

當與標頭一起使用 basePath 支援 時,每個 source 會自動前綴 basePath,除非您在標頭中添加 basePath: false

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

  async headers() {
    return [
      {
        source: '/with-basePath', // 變為 /docs/with-basePath
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
      },
      {
        source: '/without-basePath', // 由於設置了 basePath: false,不會修改
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
        basePath: false,
      },
    ]
  },
}

支援 i18n 的標頭

當與標頭一起使用 i18n 支援 時,每個 source 會自動前綴以處理配置的 locales,除非您在標頭中添加 locale: false。如果使用 locale: false,您必須在 source 前添加語言環境才能正確匹配。

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

  async headers() {
    return [
      {
        source: '/with-locale', // 自動處理所有語言環境
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
      },
      {
        // 由於設置了 locale: false,不會自動處理語言環境
        source: '/nl/with-locale-manual',
        locale: false,
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
      },
      {
        // 這匹配 '/',因為 `en` 是 defaultLocale
        source: '/en',
        locale: false,
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
      },
      {
        // 這轉換為 /(en|fr|de)/(.*),因此不會像 /:path* 那樣
        // 匹配頂層 `/` 或 `/fr` 路由
        source: '/(.*)',
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
      },
    ]
  },
}

Cache-Control

您不能在 next.config.js 中為頁面或資源設置 Cache-Control 標頭,因為這些標頭在生產環境中會被覆蓋,以確保回應和靜態資源被有效緩存。

了解更多關於使用應用程式路由器的 快取

選項

CORS

跨來源資源共享 (CORS) 是一種安全功能,允許您控制哪些網站可以訪問您的資源。您可以設置 Access-Control-Allow-Origin 標頭以允許特定來源訪問您的 路由處理程序

async headers() {
    return [
      {
        source: "/api/:path*",
        headers: [
          {
            key: "Access-Control-Allow-Origin",
            value: "*", // 設置您的來源
          },
          {
            key: "Access-Control-Allow-Methods",
            value: "GET, POST, PUT, DELETE, OPTIONS",
          },
          {
            key: "Access-Control-Allow-Headers",
            value: "Content-Type, Authorization",
          },
        ],
      },
    ];
  },

X-DNS-Prefetch-Control

此標頭 控制 DNS 預取,允許瀏覽器主動對外部連結、圖片、CSS、JavaScript 等執行域名解析。此預取在後台執行,因此當需要引用項目時,DNS 更有可能已被解析。這減少了用戶點擊連結時的延遲。

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

Strict-Transport-Security

此標頭 通知瀏覽器應僅使用 HTTPS 訪問,而不是使用 HTTP。使用以下配置,所有當前和未來的子網域將使用 HTTPS,有效期為 2 年(max-age)。這會阻止訪問只能通過 HTTP 提供的頁面或子網域。

如果您部署到 Vercel,則不需要此標頭,因為除非您在 next.config.js 中聲明 headers,否則它會自動添加到所有部署中。

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

X-Frame-Options

此標頭 指示網站是否應允許在 iframe 中顯示。這可以防止點擊劫持攻擊。

此標頭已被 CSP 的 frame-ancestors 選項取代,現代瀏覽器對此有更好的支援(詳見 內容安全政策 的配置細節)。

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

Permissions-Policy

此標頭 允許您控制瀏覽器中可以使用哪些功能和 API。它以前稱為 Feature-Policy

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

X-Content-Type-Options

此標頭 防止瀏覽器在未明確設置 Content-Type 標頭時嘗試猜測內容類型。這可以防止允許用戶上傳和共享文件的網站遭受 XSS 攻擊。

例如,用戶嘗試下載圖片,但將其視為不同的 Content-Type(如可執行文件),這可能是惡意的。此標頭也適用於下載瀏覽器擴展。此標頭的唯一有效值是 nosniff

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

Referrer-Policy

此標頭 控制瀏覽器在從當前網站(來源)導航到另一個網站時包含多少信息。

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

Content-Security-Policy

了解更多關於為您的應用程式添加 內容安全政策 的信息。

版本歷史

版本變更
v13.3.0新增 missing
v10.2.0新增 has
v9.5.0新增標頭功能。