メインコンテンツまでスキップ

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プロパティを持つレスポンスヘッダーオブジェクトの配列です
  • basePath: falseもしくはundefined - falseの場合、マッチする際にbasePathは含まれません。外部書き換えのみで使用できます
  • locale: falseもしくはundefined - ロケールがマッチに含まれないかを指定します
  • hasは、typekey、およびvalueプロパティを持つhasオブジェクトの配列です
  • missingは、typekey、およびvalueプロパティを持つmissingオブジェクトの配列です

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

ヘッダーの上書き動作

2つのヘッダーが同じパスにマッチし、同じヘッダーキーを設定する場合、最後のヘッダーキーが最初のヘッダーを上書きします。以下のヘッダーを使用する場合、パス/helloはヘッダーx-helloworldになります。これは最後に設定されたヘッダー値が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、またはクエリの値もhasフィールドにマッチするとき、またはマッチしない場合にヘッダーを適用するには、missingフィールドを使用できます。sourceとすべてのhasアイテムがマッチし、すべてのmissingアイテムがマッチしない場合にのみ、ヘッダーが適用されます。

hasmissingアイテムは、次のフィールドを持つことができます:

  • type: String - headercookiehost、またはqueryのいずれかである必要があります。
  • key: String - 一致させるために選択されたタイプからのキーです。
  • value: Stringまたは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を追加すると、マッチするためにロケールを持つ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)/(.*)に変換されるため、トップレベルや
// `fr`のようなルートにはマッチしません。`/:path*`のように。
source: '/(.*)',
headers: [
{
key: 'x-hello',
value: 'world',
},
],
},
]
},
}

Cache-Control

Next.jsは、完全に不変なアセットに対してpublic, max-age=31536000, immutableというCache-Controlヘッダーを設定します。これを上書きすることはできません。これらの不変ファイルにはSHAハッシュがファイル名に含まれているため、安全に無期限にキャッシュできます。例えば、静的画像インポートなどです。これらのアセット用にnext.config.js内でCache-Controlヘッダーを設定することはできません。

ただし、その他のレスポンスやデータに対してCache-Controlヘッダーを設定できます。

App Routerを使用したキャッシュについて詳しく学びましょう。

オプション

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

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

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

{
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ヘッダーが明示的に設定されていない場合に、ブラウザがコンテンツの種類を推測しようとするのを防ぎます。これは、ファイルのアップロードや共有を許可するWebサイトにおけるXSS攻撃の防止に役立ちます。

たとえば、画像をダウンロードしようとしたときに、それが別のContent-Type(たとえば実行可能ファイル)として扱われることを防ぎます。これにより、悪意のあるものになる可能性があります。このヘッダーはブラウザ拡張機能をダウンロードする際にも適用されます。このヘッダーの有効な値はnosniffのみです。

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

Referrer-Policy

このヘッダーは、現在のWebサイト(オリジン)から別のサイトに移動するときにブラウザがどのくらいの情報を含めるかを制御します。

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

Content-Security-Policy

アプリケーションにコンテンツセキュリティポリシーを追加する方法について詳しく学びましょう。

バージョン履歴

バージョン変更点
v13.3.0missingが追加されました
v10.2.0hasが追加されました
v9.5.0ヘッダーが追加されました