キャッシュの「神」を味方につける:VaryヘッダーでWeb APIの挙動を制御する技術
ネットワークの現場に長くいると、「キャッシュが効かない」という悲鳴よりも、「意図しないキャッシュが返ってきて事故った」という報告の方が、エンジニアの胃を痛めさせることを嫌というほど知ることになる。
HTTPにおいて、キャッシュはWeb高速化の要だが、現代の複雑なWebアプリケーションにおいて「何をキーにしてキャッシュを出し分けるか」という判断は、一筋縄ではいかない。ここで主役となるのが、HTTP/1.1の仕様で定義された `Vary` ヘッダーだ。
今日は、この「Vary」という、一見地味だが実はネットワークの深淵を制御する強力な武器について、現場の知見を交えて掘り下げていこう。
—
1. なぜVaryが必要なのか:キャッシュ汚染の正体
まず、根本的な問題を整理しよう。CDNやブラウザ、あるいはリバースプロキシ(Nginx等)は、URLをキーにしてキャッシュを保持する。しかし、Web APIの世界では、同じURLでも「リクエストヘッダーが異なれば、返すべきコンテンツも異なる」というケースが頻発する。
例えば、`Accept-Encoding: gzip` を送ったクライアントには圧縮されたデータを、そうでないクライアントにはプレーンテキストを返すAPIがあったとしよう。
もし、キャッシュサーバーがこの違いを認識できなければ、最初に `gzip` 非対応のクライアントがアクセスした際の「非圧縮データ」をキャッシュし、後から来た `gzip` 対応のクライアントに古いフォーマットを出し続ける……といった「キャッシュ汚染」が起きる。
ここで `Vary: Accept-Encoding` をレスポンスに含めると、キャッシュサーバーに対してこう命じることになる。
「このリクエストに対するキャッシュは、`Accept-Encoding` ヘッダーの内容も考慮して保持しろ」と。
—
2. 実務で遭遇するVaryの落とし穴:ワイルドカードの罠
設計者がよく陥る罠が、`Vary: ` の使用だ。
仕様上は「全てのリクエストヘッダーをキーにする」という意味だが、これはキャッシュサーバーにとって「このコンテンツはキャッシュ不可」という宣言と同義だ。CDNのキャッシュ効率を劇的に下げるため、原則として使用は避けるべきだ。
サーバー設定例:NginxでVaryを制御する
Nginx側で適切に `Vary` を付与する設定例を見てみよう。
location /api/v1/data {
# 圧縮の可否で出し分けることをキャッシュ側に伝える
add_header Vary “Accept-Encoding, Authorization”;
# 必要に応じて、User-Agentによる出し分けも定義するが、
# 種類が多すぎる(スマホ、タブレット、PC)とキャッシュ効率が激減するので注意
# add_header Vary “User-Agent”;
}
—
3. クライアントサイドでの検証手順
デバッグ時に、「本当にVaryが効いているか?」を確認するのは必須のスキルだ。`curl` を使って、ヘッダーの挙動を覗いてみよう。
圧縮対応を装ってリクエストし、Varyヘッダーを確認
curl -I -H “Accept-Encoding: gzip” https://api.example.com/data
もし、あなたがフロントエンドエンジニアなら、ブラウザのFetch APIでリクエストを送る際、`credentials: ‘include’` を指定した場合の `Vary: Authorization` の挙動に注意してほしい。認証ヘッダーをVaryに含めると、ユーザーごとにキャッシュが完全に分離されるため、共有キャッシュ(CDN)上では事実上キャッシュが無効化される。このトレードオフを理解しているかどうかが、プロの分かれ道だ。
—
4. シニアエンジニアからの「現場のTIPS」
最後に、運用現場で叩き込まれた教訓をいくつか授ける。
1. User-AgentをVaryに入れるな
`Vary: User-Agent` を設定すると、GooglebotからiPhone、Android、古いIEに至るまで、数千通りのバリエーションでキャッシュが作成される。CDNのヒット率が壊滅的に下がるため、デバイスごとの出し分けはレスポンシブデザインか、サーバーサイドでの動的なHTML生成に任せるのが鉄則だ。
2. Varyは「最小限」に絞れ
`Vary: Accept-Encoding, Authorization, X-Requested-With` のように増えれば増えるほど、キャッシュの粒度は細かくなる。「本当にそのヘッダーの値が変わればレスポンスが変わるのか?」を常に自問自答してほしい。
3. CDNの管理画面を過信しない
AWS CloudFrontやCloudflareなどのCDNは、`Vary` ヘッダーを無視したり、特定のヘッダーしか許可しなかったりする挙動がある。デバッグ時は、必ず `X-Cache: HIT/MISS` ヘッダーを確認し、期待通りのキャッシュキーで保存されているか、キャッシュサーバーのログを追跡すること。
—
まとめ
`Vary` ヘッダーは、HTTPの通信フローにおいて「キャッシュの多様性」を担保するための繊細なスイッチだ。適当に設定すればキャッシュ効率を殺し、正しく設定すればパーソナライズされた体験と高速なレスポンスを両立できる。
ネットワークアーキテクチャの基本は、常に「何が通信を識別するキーなのか」を意識することにある。今日からログを見る際は、ぜひレスポンスヘッダーの `Vary` に注目してみてほしい。そこには、Webサーバーの設計意図が隠されているはずだ。
コメント