ヘッダー
レスポンスヘッダーは、デプロイのルートに置く _headers ファイルに書きます。書式は、Netlify と Cloudflare Pages が読むものの一部です。
既定のヘッダー
すべてのレスポンスに、次の3つのヘッダーが付きます。ただし、ホスト名全体を正規ドメインへ転送するリダイレクトには、Location しか付きません。
X-Frame-Options: DENYX-Content-Type-Options: nosniffReferrer-Policy: strict-origin-when-cross-origin
HTML (拡張子のないパス、.html、.htm) には Cache-Control: public, max-age=600 が、それ以外には public, max-age=86400 が付きます。サイトのファイルには ETag と Last-Modified も付くので、再訪したブラウザは確認だけで304を受け取れます。範囲リクエストにも対応しています。
_headers では、パスを選んで、既定の3つのヘッダーを上書きまたは削除でき、Cache-Control を上書きできます。変えられないものが2つあります。Kamakiri 標準の「ページが見つかりません」画面には、必ず既定のヘッダーが付きます。4xxと5xxのレスポンスは、ブロックが Cache-Control に何を設定していても no-store で配信されます。リダイレクトはこの対象外で、キャッシュできます。
Strict-Transport-Security は付かず、追加することもできません。
ファイル
_headers はブロックを並べたものです。1つのブロックは、字下げせず / で始まるパスの行と、そのあとに続く字下げしたヘッダーの行でできています。
# a full-line comment starts with #
/path/*
X-Custom-Header: value
Cache-Control: public, max-age=3600
! X-Frame-Options
- 字下げは、1つ以上のスペースかタブです。
- 空行かファイルの末尾で、ブロックは終わります。コメントでは終わりません。
- ヘッダー名は大文字と小文字を区別しません。パスは区別します。
- ファイルはUTF-8で書きます。先頭のバイト順マークは無視され、改行は
\nと\r\nを受け付けます。
ヘッダーとして読まれるのは、デプロイのルートにある、名前がちょうど _headers のファイルだけで、このファイルは配信されません。_Headers や sub/_headers は、ふつうのファイルとして配信されます。
ブロック
- パス。
/aboutのような完全一致か、/assets/*のように末尾に*を1つだけ付けた形です。*はその前の部分に続くものすべてに、スラッシュも含めて一致するので、/blog/*は/blog/と/blog/2024/postに一致し、/blogには一致しません。 - ヘッダーを設定する。
Name: valueと書きます。名前は最初の:より前の部分です。値は前後の空白が取り除かれ、途中はそのまま残ります。値を空にはできません。 - 複数の値。 名前を繰り返すと、1行ずつ別のヘッダーとして送られます。
Cache-Controlは、繰り返した行をキャッシュやプロキシがまちまちに解釈するので、カンマでつないだ1行にしてください。 - ヘッダーを削除する。
! Nameは、ブロックのパスで既定のヘッダーを外します。既定でないヘッダーに対しては何もしません。 - 重なるブロック。 ブロックはファイルの順に適用されるので、一致する2つのブロックが同じヘッダーを設定していれば、あとのブロックが優先されます。
設定したヘッダーが既定のヘッダーを置き換えるのは、そのブロックのパスだけです。ほかのパスは既定のままです。
受け付けられない書き方
受け付けられない行が1つでもあると、デプロイ全体が行番号付きのエラーで失敗します。ディレクトリをデプロイするときは、kamakiri deploy がアップロードの前にファイルを検査します。アーカイブは、アップロードのあとにサービスが検査します。どちらの場合も、公開中のサイトは変わりません。
- 値のなかの、印字可能なASCII以外のバイト。 値に書けるのは
0x20から0x7eまでなので、タブ、改行、ASCII以外の文字は書けません。 - 単独の復帰文字とNULバイト。 ファイルのどこかに単独の
\rかNULがあると受け付けません。\r\nは改行として扱います。 - 値に含まれる
{と}。 値はすべて、そのままの文字列です。 - 正しくないヘッダー名。 名前は RFC 7230 のトークンでなければならないので、スペースを含められません。名前は最初のコロンで終わるので、
Na:me: vはヘッダーNaにme: vを設定します。 Set-Cookie。 大文字小文字を問いません。Strict-Transport-Security。 ブラウザは、削除したあともmax-ageが切れるまでこれを守り続けます。- パスのプレースホルダーと値への埋め込み。
:nameのセグメント、末尾の1つ以外の*、値のなかの:splatです。/a:bのようにセグメントのなかにあるコロンは、ふつうのパスです。 - 構造の誤り。 パスでもディレクティブでもコメントでもない行、ブロックの外で字下げされた行、ディレクティブのないブロック、同じブロックで設定と削除の両方をしたヘッダーです。
除外される名前
次の名前は、拒否ではなく除外されるので、Netlify や Cloudflare Pages から持ってきたファイルもそのままデプロイできます。ディレクトリをデプロイするときは、kamakiri deploy が除外した行ごとに警告を表示し、デプロイを続けます。アーカイブの場合は、警告なしに除外されます。
- 伝送とホップごとの名前。
Connection、Proxy-Connection、Keep-Alive、Transfer-Encoding、TE、Trailer、Upgrade、Content-Length。 - プラットフォームが設定する名前。
Content-Type(ファイルの拡張子で決まります)、Content-Encoding、Content-Range、Accept-Ranges、Host、Date、Server、Age、Alt-Svc、Allow、そしてLocation(_redirectsに書くものです)。
上限
どれかを超えたファイルは、切り詰められるのではなく、受け付けられません。
- ファイルサイズ。 64KBまでです。
- ブロック。 100までです。
- 1ブロックあたりのヘッダーの行。 64行までで、プラットフォームが除外する行も数えます。
- ヘッダーの合計バイト数。 32KBまでで、設定した名前と値、
! Nameの行の名前を数えます。プラットフォームが除外する行は数えません。 - 1行の長さ。 2,048バイトまでです。
他サービスとの互換性
完全一致のパス、/*、/assets/* のように末尾に * を1つ付けたパスのもとに Name: value の行を並べたブロックは、Kamakiri、Netlify、Cloudflare Pages のどれでも同じように動きます。Netlify は ! Name を無視するので、ヘッダーを削除するファイルが同じように動くのは Cloudflare Pages だけです。:placeholder やそれ以外の * を使ったファイルは、どちらのサービスのものでも、ここでは受け付けられません。
例
# A custom header on every response
/*
X-Custom-Header: hello
# Long-lived caching for hashed assets (one comma-separated line)
/assets/*
Cache-Control: public, max-age=31536000, immutable
# Override a default site-wide
/*
Referrer-Policy: no-referrer
# Drop a default for one path only; other paths keep X-Frame-Options: DENY
/embed/*
! X-Frame-Options