ヘッダー
ヘッダーを使用すると、特定のパスへの受信リクエストに対するレスポンスにカスタム HTTP ヘッダーを設定できます。
カスタム HTTP ヘッダーを設定するには、next.config.js
で headers
キーを使用します:
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
は、source
と headers
プロパティを持つオブジェクトを含む配列を返す非同期関数です:
source
は、受信リクエストのパスパターンです。headers
は、key
とvalue
プロパティを持つレスポンスヘッダーオブジェクトの配列です。basePath
:false
またはundefined
- false の場合、マッチング時にベースパスは含まれません。外部リライトにのみ使用できます。locale
:false
またはundefined
- ロケールをマッチング時に含めないかどうか。has
は、type
、key
、value
プロパティを持つhasオブジェクトの配列です。missing
は、type
、key
、value
プロパティを持つmissingオブジェクトの配列です。
ヘッダーは、ページや /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', // マッチしたパラメータを値で使用できます
},
{
key: 'x-slug-:slug', // マッチしたパラメータをキーで使用できます
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*', // マッチしたパラメータを値で使用できます
},
{
key: 'x-slug-:slug*', // マッチしたパラメータをキーで使用できます
value: 'my other custom header value',
},
],
},
]
},
}
正規表現パスの一致
正規表現パスを一致させるには、パラメータの後に括弧で正規表現を囲みます。例えば /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
フィールドに一致する場合、またはフィールドに一致しない missing
フィールドのみにヘッダーを適用できます。ヘッダーを適用するには、source
とすべての has
アイテムが一致し、すべての missing
アイテムが一致しない必要があります。
has
と missing
アイテムには、以下のフィールドを使用できます:
type
:String
-header
、cookie
、host
、またはquery
のいずれかである必要があります。key
:String
- 選択されたタイプから一致させるキー。value
:String
またはundefined
- チェックする値。未定義の場合、任意の値に一致します。値の特定の部分をキャプチャするために、正規表現のような文字列を使用できます。例えば、値first-(?<paramName>.*)
をfirst-second
に使用すると、:paramName
で宛先でsecond
を使用できます。
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',
},
],
},
// ソース、クエリ、クッキーが一致する場合、
// `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
サポートでヘッダーを活用する場合、basePath: false
を追加しない限り、各 source
は自動的に basePath
で接頭辞が付けられます:
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
を使用する場合、正しく一致させるためにはソースにロケールを接頭辞として付ける必要があります。
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` であるため、'/'に一致する
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.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年間HTTPSを使用します。これにより、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
ヘッダーが明示的に設定されていない場合、ブラウザがコンテンツの種類を推測しようとすることを防ぎます。これにより、ユーザーがファイルをアップロードおよび共有できる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.0 | missing が追加されました。 |
v10.2.0 | has が追加されました。 |
v9.5.0 | ヘッダーが追加されました。 |