• Vary headerは同じURLで内容を出し分けるときにだけ使いcacheの条件を明らかにする

Vary headerは同じURLで内容を出し分けるときにだけ使いcacheの条件を明らかにする

公開日: 執筆:佐藤

Vary headerは、同じURLでもrequest headerによって応答を変えるとき、cacheにどの条件を見て保存済みの応答を選ぶか伝えるために使います。日本語と英語を別URLに置くsiteや、PC用とmobile用を別URLに置くsiteでは、URLの違いだけで内容を選べるなら、出し分けのためにVaryを足す必要はありません。まず、同じURLが本当に複数の内容を返しているかを確かめます。

サイトを速くするためにcacheを有効にすると、同じURLの応答は次のrequestで再利用されます。このときserverがrequestごとに内容を変えるのに、その違いをcacheへ伝えなければ、ある利用者向けの応答を別の利用者へ返すおそれがあります。Varyは見た目を変える設定ではなく、保存済みの応答を使ってよい条件を決めるheaderです。

HTTP/1.1のRFC 7231は、Varyを、request headerのどの項目が応答の選択に影響するかを示すresponse headerとして定義しています。cacheはVaryに挙がったheaderの値を比べ、条件が合わない応答を別のrequestへ使わないようにします。設定名だけを覚えるより、同じURLが誰に何を返すかを先に整理する方が確実です。

URLで分けるpageとheaderで分ける応答は別である

最初に、利用者が開くURLそのものが違うのか、URLは同じでbrowserから送られる情報によって内容が違うのかを分けます。前者ならcacheはURLごとに別の応答として扱えます。後者では、URL以外の条件をVaryで示す必要が出ます。

場面 応答を分ける主な条件 確認すること
/ja/service/と/en/service/を置く URL それぞれのURLが正しい言語のpageを返すか
同じURLでbrowserの言語設定により文面を変える Accept-Language languageごとの応答をcacheが取り違えないか
同じCSS fileを圧縮形式によって変える Accept-Encoding 圧縮されたfileと通常のfileを正しく返せるか
loginした人だけに個別内容を返す cookieや認証情報 shared cacheへ保存してよい応答か

たとえば、https://example.jp/service/を開いたとき、browserのAccept-Languageによって日本語または英語の説明を返す仕組みを考えます。URLは一つでも、返る本文は同じではありません。この場合、最初に日本語の応答を保存したcacheが、英語を希望する利用者へそのまま返すと、利用者は希望と違う言語のpageを見ることになります。serverがこのheaderを選択条件に使うなら、Vary: Accept-Languageでその条件を示します。

一方で、/ja/と/en/を別々に運用しているなら、言語の違いはURLに現れています。Accept-Languageを見て表示内容を変えない限り、同じ理由でVaryを追加する必要はありません。URLを分けているのにheaderの出し分けまで重ねると、利用者、制作者、cacheのどれにとっても、どの条件で内容が変わるか追いにくくなります。

圧縮の設定は本文の内容と分けて確認する

Varyでよく見るのがAccept-Encodingです。browserはrequest headerで、gzipなど受け取れる圧縮形式をserverへ伝えられます。serverがこの値を見て同じJavaScript、CSS、HTMLを圧縮版または非圧縮版として返すなら、応答は符号化の形式が異なります。本文の意味が同じでも、cacheが返すdataは同じではありません。

このとき確認すべきことは、圧縮を有効にしたかだけではありません。まず同じasset URLへrequestし、responseのContent-EncodingとVaryを確認します。次に、圧縮を受け取るbrowserと受け取らないclientで、それぞれが読める応答になるかを確認します。最後に、proxy cacheやCDNを使うなら、そのserviceがresponse headerを保ったまま配信するかを確認します。server側だけで正常に見えても、途中のcacheで条件が失われれば、利用者側の表示は別です。

圧縮を確認するとき、HTML、CSS、JavaScript、画像を一括で同じ設定として扱わない方がよい場合があります。実際に圧縮の対象になるfile、除外するfile、配信を担当するserverまたはCDNを分けて書き出します。file形式や配信経路が違えば、同じheaderが付かないことがあります。設定を変えた日時と対象URLを残せば、表示不良が起きたときにどの変更を戻すか判断できます。

個別のpageはVaryだけで守らない

Varyは、どのrequest headerが応答の選択に関わるかをcacheへ伝えるものです。個別の見積り、管理画面、login後の情報のように、利用者ごとに内容が違うpageをshared cacheへ置いてよいかどうかまで決めるものではありません。

たとえば、login中の利用者だけに表示する注文内容を、cookieの有無で同じURLから返すsiteを考えます。cookieをVaryへ入れれば安全になる、と単純には言えません。cookieには利用者ごとに異なる値が入るため、cacheの保存単位が細かくなりすぎることがあります。何より、その応答を第三者と共有できるcacheへ保存してよいかを先に決める必要があります。

個別情報を返すpageでは、認証、session、cache-controlの方針をまとめて確認します。誰に見せる情報か、URLを知るだけで開けないか、serverが認証を確かめているか、browserや中継cacheに保存してよいかを分けます。Varyはこの中の一項目であり、認証や公開範囲の代わりにはなりません。

制作を外部へ頼む場合も、「cacheを入れた」「表示が速くなった」という報告だけでは運用できません。どのURLで、どのheaderを条件にして、どこがcacheを担当し、設定を変更できるaccountを誰が持つかを残します。作業を任せることと、設定の内容を確認できることは別です。引継ぎのときにserver、CDN、WordPress pluginのどこでheaderを足しているか分からなければ、不具合の切り分けに時間がかかります。

変更前後は同じURLと異なる条件を組にして見る

Varyを追加または変更するときは、pageを一度開いて終わりにしません。同じURLへ条件を変えたrequestを送り、response headerと本文を組で確認します。確認する順序を決めておくと、内容の出し分けとcacheの動きを混同せずに済みます。

  1. 対象URLを一つ選び、通常のbrowserで返るstatus、本文、Vary、Content-Encodingを記録する。
  2. serverが選択に使うheaderを一つだけ変え、本文または符号化が変わるかを確認する。
  3. 変わるなら、responseのVaryにそのheaderが含まれるかを確認する。変わらないなら、なぜそのheaderをVaryへ足すのかを見直す。
  4. cacheやCDNを経由するURLでは、保存済みの応答を消した直後と時間を置いた後で、同じ確認を行う。
  5. 変更した場所、対象URL、確認日時、戻す方法を記録する。

この手順は、すべてのURLへVaryを付けるためのものではありません。出し分けがないURLまで条件を増やすと、cacheの再利用が減り、設定を読む人も迷います。反対に、出し分けがあるのに条件を示さなければ、見た目だけでは再現しにくい表示違いが起きます。最初の一手は、同じURLで応答が変わるpageを一つ選び、何を見てserverが内容を選んでいるかを書くことです。

戻る