ヘッダー

ヘッダーを使用すると、特定のパスへのリクエストに対するレスポンスにカスタムHTTPヘッダーを設定できます。

カスタムHTTPヘッダーを設定するには、next.config.jsheadersキーを使用します:

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プロパティを持つ)
  • basePath: falseまたはundefined - falseの場合、マッチング時にbasePathが含まれません(外部リライトのみに使用可能)
  • locale: falseまたはundefined - マッチング時にロケールを含めるかどうか
  • has: hasオブジェクトの配列(typekeyvalueプロパティを持つ)
  • missing: missingオブジェクトの配列(typekeyvalueプロパティを持つ)

ヘッダーは、ページや/publicファイルを含むファイルシステムよりも前にチェックされます。

ヘッダーの上書き動作

同じパスにマッチする2つのヘッダーが同じヘッダーキーを設定している場合、最後のヘッダーキーが最初のものを上書きします。以下のヘッダーを使用すると、パス/helloでは最後に設定された値worldにより、ヘッダーx-helloworldになります。

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フィールドにマッチしない場合にのみヘッダーを適用するには、hasフィールドまたはmissingフィールドを使用できます。ヘッダーが適用されるには、sourceとすべてのhas項目がマッチし、すべてのmissing項目がマッチしない必要があります。

hasmissing項目には以下のフィールドがあります:

  • type: String - headercookiehost、またはqueryのいずれか
  • key: String - マッチ対象のキー
  • value: Stringまたはundefined - チェックする値(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ヘッダーを設定することはできません。これらのヘッダーは本番環境で上書きされ、レスポンスと静的アセットが効果的にキャッシュされるようにします。

静的生成されたページのキャッシュを再検証する必要がある場合、ページのgetStaticProps関数でrevalidateプロップを設定することで可能です。

API RoutesCache-Controlヘッダーを設定するには、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!' })
}

オプション

CORS

Cross-Origin Resource Sharing (CORS)は、どのサイトがリソースにアクセスできるかを制御するセキュリティ機能です。Access-Control-Allow-Originヘッダーを設定して、特定のオリジンがAPIエンドポイントにアクセスできるようにします。

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

このヘッダーは、HTTPではなくHTTPSを使用してのみアクセスする必要があることをブラウザに通知します。以下の設定を使用すると、すべての現在および将来のサブドメインが2年間(max-age)HTTPSを使用します。これにより、HTTPでのみ提供できるページやサブドメインへのアクセスがブロックされます。

Vercelにデプロイする場合、このヘッダーは不要です。next.config.jsheadersを宣言しない限り、すべてのデプロイメントに自動的に追加されます。

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

X-Frame-Options

このヘッダーは、サイトをiframe内に表示できるかどうかを示します。これにより、クリックジャッキング攻撃を防ぐことができます。

このヘッダーはCSPのframe-ancestorsオプションに置き換えられました。これは現代のブラウザでより良いサポートがあります(設定詳細はContent Security Policyを参照)。

{
  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

アプリケーションにContent Security Policyを追加する方法について詳しく学びます。

バージョン履歴

バージョン変更点
v13.3.0missing追加。
v10.2.0has追加。
v9.5.0ヘッダー機能追加。