• ETagとLast-Modifiedは更新日時の表示に使わずcacheが同じ内容か確かめるために使う

ETagとLast-Modifiedは更新日時の表示に使わずcacheが同じ内容か確かめるために使う

公開日: 執筆:佐藤

ETagとLast-Modifiedは、browserやcacheが持っている内容をそのまま使えるかをserverへ確かめるHTTP headerです。記事の公開日、管理画面で更新した日時、読者へ見せる最終更新日を表すための表示項目ではありません。何の更新を確かめる値なのかを分けないと、pageを直したのに古いCSSが残る問題と、記事の日付を表示する問題を同じ設定で直そうとして混乱します。

RFC 7232は、ETagを選ばれたrepresentationを区別するためのentity-tagとして定義し、Last-Modifiedを更新時刻のvalidatorとして扱います。GETまたはHEADの成功responseでは、可能ならentity-tagとLast-Modifiedの両方を送ることが推奨されています。どちらか一方のheaderがあることと、利用者が常に新しい画面を見ることは別です。Cache-Control、CDN、serverの設定、更新の反映順も確認します。

ETagは内容の版を見分ける値である

ETagは、responseの内容を見分けるためにserverが付ける値です。"abc123"のような文字列が返りますが、その中身を読者や更新担当者が解釈するための番号ではありません。fileの名前、記事の公開日、WordPressの投稿IDと同じ意味にしません。

browserやcacheがETag付きのresponseを保存している場合、次に同じresourceを取りに行くとき、If-None-Matchに前のETagを入れてserverへ確認できます。server側の内容が変わっていなければ、本文を再送せず304 responseを返せます。内容が変わっていれば、新しい本文と新しいETagを含むresponseを返します。この仕組みは、毎回同じ画像やCSSを全部送り直さずにすむためのものです。

説明用の仮例として、/assets/site.cssにETag: "v17"が付いている場合を考えます。browserは最初にCSS本文とETagを保存します。次にpageを開いたとき、If-None-Match: "v17"を送ります。server側も同じCSSなら304を返し、browserは保存していたCSSを使います。CSSを直した後にserverがETag: "v18"を返せば、browserは新しいCSS本文を受け取ります。

この例で大切なのは、ETagの数字を手で増やすことではありません。どの層がETagを出しているかを知ることです。origin serverが出す場合もあれば、hosting、reverse proxy、CDNがresponseを加工する場合もあります。WordPress themeのCSS fileを直したのに表示が変わらないとき、WordPress本体だけを疑わず、response header、cacheの保存期間、CDN、読み込むfileのURLを分けて見ます。

Last-Modifiedは読者へ示す更新日ではない

Last-Modifiedは、responseのrepresentationが最後に変更された時刻をHTTP dateで示すheaderです。cacheがIf-Modified-Sinceを使うときのvalidatorになります。記事pageに「更新日:2017年5月10日」と表示するためのdateとは、用途が違います。

記事の画面へ見せる日付は、著者がその内容をいつ公開し、いつ改稿したかを読者へ伝える情報です。WordPressでは投稿日時、更新日時、編集方針に応じた基準日を持つことがあります。一方、Last-Modifiedはthemeが出力を変えた、pluginがHTMLを加えた、server側の処理が変わった場合にも変わり得ます。headerの値を記事本文の更新日として出すと、内容を直していないのに日付が動く、逆に内容を直したのに期待どおり動かない、といった誤解が起こります。

たとえば、記事本文を変えずにheaderのmenuを直したとします。page全体のHTMLが変われば、cache validationに使うrepresentationは変わるかもしれません。しかし、記事の著者が本文を改稿したわけではありません。読者へ見せる記事更新日まで変えるかは、サイトの編集方針として別に決めます。

反対に、本文中の料金や連絡先を直した場合は、読者へどの日付を見せるかを決めます。そのpageのHTMLが変わるためETagやLast-Modifiedにも影響する可能性がありますが、headerが変わるかどうかを記事の改稿判断に使いません。公開内容の変更、画面の日付、HTTP cacheのvalidatorを別に記録します。

確認したいこと 主に見るもの 混同しないこと
読者へ記事の公開日を伝える 記事のdate表示と編集記録 HTTP responseのLast-Modified
cacheが同じ内容を再利用できるか ETag、Last-Modified、conditional request 管理画面の更新日時
CSSや画像が更新されたか 読み込むURL、response header、画面表示 記事本文の更新日
pageが検索向けに更新されたか 本文、URL、meta data、内部link ETagの文字列

表のように分けると、問題が出たときに確認する人も分かれます。記事の更新日が誤っているなら編集担当が確認します。CSSが古いならtheme、asset URL、CDNを確認します。cache responseが期待と違うならserverやhostingの担当が確認します。一つのdateやheaderで全てを直そうとしません。

304 responseは更新していないと断定する表示ではない

304 Not Modifiedは、conditional requestに対してserverが本文を再送しないresponseです。利用者の画面で「更新されていない」という意味を直接表示するものではありません。cacheがどのresponseを持ち、どの条件で確認し、serverが何を比較したかによって決まります。

RFC 7232は、304 responseにCache-Control、Content-Location、Date、ETag、Expires、Varyといったheaderを含めることを定めています。304にmessage bodyはありません。これを見て「serverが何もしていない」と考えず、cacheにあるrepresentationを再利用するためのresponseとして理解します。

説明用の仮例として、top pageに載せたlogo画像を差し替える場合を考えます。同じlogo.pngというURLでfileだけを入れ替える構成では、cacheが古い画像を持っている間、更新を確認しにくいことがあります。ETagやLast-Modifiedの更新が適切でも、Cache-Controlの保存期間、CDNのキャッシュ、browserの表示が関わります。原因を一つに決めず、まずresponse headerと実際に読み込んだfileを見ます。

CSSやJavaScriptでは、file名にversionを付けて新しいURLへ替える方法もあります。site.css?ver=20170510のようにURLを替えれば、cacheが前のURLとは別のresourceとして扱います。ただし、versionを毎回増やす運用は、どのtemplateがどのfileを読むかを把握できる場合にだけ行います。古いURLを参照するtemplateが残れば、pageごとに表示が違います。cacheを避けるためのURL変更と、assetの管理を分けないようにします。

WordPressとCDNでは出力元を確認する

WordPress siteでETagやLast-Modifiedを調べる場合、最初に公開URLのresponse headerを見ます。PHP fileにheaderを書く前に、既にhostingやCDNが値を出していないかを確認します。複数の層が同じ種類のheaderを扱うと、何を変えた結果なのか追えなくなります。

themeを直した直後に表示が古い場合は、次の順に確かめます。まず、公開pageのHTMLが更新済みのCSS URLを読んでいるかを見ます。次に、そのCSS URLのresponse headerを見ます。続けて、CDNやbrowserのcacheを経由しない確認方法を用意します。最後に、別のpageや別の画面幅でも同じfileを読んでいるかを見ます。WordPressの管理画面でfileを保存したことだけを、公開側の更新確認にしません。

CDNを使う場合は、cacheを消す権限と、消した結果を確認する人を決めます。公開担当が記事を更新しても、CDNの設定を変更する権限がなければ、緊急時に画面を直せません。逆に技術担当がcacheを消しても、記事の条件や画像が正しいかは判断できません。contentを更新する人、cacheを扱う人、公開画面を確認する人の役割を分けます。

外部へsite保守を頼むなら、ETagの設定値を受け取るだけで終えません。origin server、CDN、WordPress pluginのどこがcacheを扱うか、CSSや画像を更新したときの確認手順、headerを変更したときの戻し方を記録します。通信の高速化を任せても、公開した内容がいつ反映されたかを確かめる責任はsite側に残ります。

更新直後は画面とheaderを別に見る

cacheの設定を変えた後は、headerだけを見て終えません。更新したpageを実際に開き、本文、画像、CSS、form、linkを確認します。次に開発者向け画面やHTTP clientでresponse headerを見ます。画面が新しくてもcache設定が意図どおりとは限らず、headerが新しくても利用者が必要な操作をできるとは限らないためです。

確認するURLは一つに絞りません。top page、記事page、画像の多いpage、問い合わせpageを選びます。共通headerやfooterを直したなら、複数のpageに同じ変更が反映されているかを見ます。articleの本文だけを直したなら、記事pageの公開日や更新日の表示を編集方針どおりに確認します。HTTPのvalidatorを確認する作業と、内容を公開する作業を一つの「更新完了」にまとめません。

最初の一手は、更新が反映されないURLを一つ選び、HTML、CSSまたは画像のURL、ETag、Last-Modified、Cache-Controlを順に記録することです。その後で、どの層が古い内容を返しているかを分けて調べます。

戻る