🚀

【Next.js和訳】API Reference/next.config.js/Custom Headers

8 min read

この記事について

株式会社 UnReact はプロジェクトの一環としてNext.js ドキュメントの和訳を行っています。

この記事は、next.config.js/Custom Headersの記事を和訳したものです。

記事内で使用する画像は、公式ドキュメント内の画像を引用して使用させていただいております。

Headers

Version History
バージョン 変更点
v10.2.0 has を追加
v9.5.0 Headers を追加

Headers では、受信するリクエストパスにカスタム HTTP ヘッダーを設定することができます。

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

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 は、typekey、値のプロパティを持つhasオブジェクトの配列です。

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

ヘッダーのオーバーライド動作

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

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にマッチします(ネストしたパスはありません)。

module.exports = {
  async headers() {
    return [
      {
        source: '/blog/:slug',
        headers: [
          {
            key: 'x-slug',
            value: ':slug', // マッチしたパラメータはvalueに使用できます
          },
          {
            key: 'x-slug-:slug', // 一致するパラメータは、keyに使用できます
            value: 'my other custom header value',
          },
        ],
      },
    ],
  },
}

ワイルドカード・パス・マッチング

ワイルドカードのパスにマッチさせるには、パラメータの後に*を使います。例えば、/blog/:slug*は、/blog/a/b/c/d/hello-worldにマッチします。

module.exports = {
  async headers() {
    return [
      {
        source: '/blog/:slug*',
        headers: [
          {
            key: 'x-slug',
            value: ':slug*', // 一致したパラメータは、valueの中で使用できます
          },
          {
            key: 'x-slug-:slug*', // keyーにはマッチしたパラメーターが使用できます
            value: 'my other custom header value',
          },
        ],
      },
    ],
  },
}

Regex パスマッチング

例えば、/blog/:slug(\\d{1,})は、/blog/123にマッチしますが、/blog/abcにはマッチしません。

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

以下の文字 (, ) {, }:*+? は、正規表現のパスマッチングに使用されるため、source内で非特殊な値として使用する場合は、文字の前に\\を付けてエスケープする必要があります。

module.exports = {
  async headers() {
    return [
      {
        // これは、リクエストされた `/english(default)/something` にマッチします
        source: "/english\\(default\\)/:slug",
        headers: [
          {
            key: "x-header",
            value: "value",
          },
        ],
      },
    ]
  },
}

ヘッダー、クッキー、およびクエリのマッチング

ヘッダー、クッキー、クエリのいずれかの値が一致した場合にのみヘッダーを適用するには、hasフィールドを使用できます。ヘッダーが適用されるには、sourceとすべてのhasアイテムの両方が一致する必要があります。

hasアイテムには、以下のフィールドがあります。

  • type: String - headercookiehostqueryのいずれかでなければなりません。
  • key: String - 選択されたタイプの中で、照合するキーです。
  • value: Stringまたはundefined - チェックする値、undefined の場合、いずれかの値が一致します。文字列のような正規表現を使用して、値の特定の部分をキャプチャできます。first-(?<paramName>.*)という値がfirst-secondに使用されている場合、secondは宛先で:paramNameを使用して使用できます。
module.exports = {
  async headers() {
    return [
      // ヘッダー `x-add-header` がある場合は、要求された `/english(default)/something` に
      // x-another-header` というヘッダーが適用されます
      {
        source: "/:path*",
        has: [
          {
            type: "header",
            key: "x-add-header",
          },
        ],
        headers: [
          {
            key: "x-another-header",
            value: "hello",
          },
        ],
      },
      // ソース、クエリ、およびクッキーが一致した場合
      // `x-authorized`ヘッダが適用されます
      {
        source: "/specific/:path*",
        has: [
          {
            type: "query",
            key: "page",
            // ページの値は、ヘッダの key/values で利用できません。
            // 値が提供されているので、ヘッダーのキー/値を
            // (?<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",
          },
        ],
      },
      // if the host is `example.com`,
      // this header will be applied
      {
        source: "/:path*",
        has: [
          {
            type: "host",
            value: "example.com",
          },
        ],
        headers: [
          {
            key: "x-another-header",
            value: ":authorized",
          },
        ],
      },
    ]
  },
}

国際化に対応したヘッダー

ヘッダーで国際化サポートを利用する場合、ヘッダーに locale: false を追加しない限り、各sourceは設定されたlocalesを扱うように自動的にプレフィックスされます。locale: false を使用した場合、正しくマッチさせるためにはsourceの前にロケールを付ける必要があります。

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",
          },
        ],
      },
      {
        // ホストが `example.com` の場合。
        // このヘッダが適用されます
        source: "/(.*)",
        headers: [
          {
            key: "x-hello",
            value: "worlld",
          },
        ],
      },
    ]
  },
}

キャッシュ-コントロール

next.config.js で設定された Cache-Control ヘッダは、運用時には上書きされ、静的資産が効果的にキャッシュされるようになります。静的生成されたページのキャッシュを再検証する必要がある場合は、ページのgetStaticProps関数でrevalidateを設定することで可能となります。

関連

詳細については、以下のセクションをお勧めします。

セキュリティヘッダー

HTTP レスポンスヘッダーを追加することで、Next.js アプリケーションのセキュリティを向上させることができます。

https://nextjs.org/docs/advanced-features/security-headers

Discussion

ログインするとコメントできます