HTTP ETag

ETag（エンティティタグ）は、HTTPにおけるレスポンスヘッダの1つである。これは、HTTPにおけるキャッシュの有効性確認の手段の1つであり、ETagを利用してクライアントから条件付きのリクエストを行うことができる。そうすることで、コンテンツが変わらなければレスポンスをすべて返す必要がなくなるので、キャッシュを効率化し、回線帯域を節約できるようになる。ETagは複数人が同時にリソースを上書きしてしまうことへの対策となる、楽観的並行性制御に使うこともできる。

ETagはあるURLから得られる、ある特定のバージョンのリソースに対する、明確でない識別子である。そのURLにあるリソースに何かしらの変化があれば、ETagも新しい値となる。このように設定されたETagは、一種のフィンガープリントとなり、2つのリソースが同じかどうかを容易に判定できるようになる。あるETagは特定のURLに対してのみ意味を持つものであり、他のURLから得られたリソースのETagと比較しても何ら有意な結果は得られない。

使用例 
典型的な場合、ETag値はWebサーバがレスポンスを送信するときに、リソースとセットとなるHTTPヘッダのETagフィールドに、以下のような形でセットされる。

 ETag: "686897696a7c876b7e"

クライアントがこのリソースをETagとともにキャッシュしたとすると、後で同じURLへリクエストを行う場合に、先ほど受け取ったETag値をIf-None-Matchに入れてリクエストを行う。

 If-None-Match: "686897696a7c876b7e"

このリクエストを受け取ると、サーバはリソースのETag値と送られてきたETag値の比較を行う。もしETag値が一致すれば、リソースは変わっていないということになるので、サーバは304 Not Modifiedという、リソース本体を含まないレスポンスを返す。この304というステータスコードのレスポンスは、キャッシュはまだ最新のものなのでそれを使うべきだということを表している。

一方、ETagが一致しなければ、If-None-Matchのないリクエストと同様、リソースを含んだレスポンスを返すこととなる。

また、If-Rangeという、範囲リクエストとETagの確認を同時に行うためのフィールドも存在する。

ETagは、Webページの更新監視にも使うことができる。ただ、WebページにETagを設定していないサイトについては、ETagだけをチェックするという効率的な手法は使えず、ドキュメントすべてをダウンロードして比較するという、サーバ側・クライアント側ともに負荷のかかる手法を使うほかない。

強いETag値と弱いETag値 
ETagには強いETag値と弱いETag値が存在する。表記としては、頭に「W/」が付くものが弱いETag値、付かないものが強いETag値である。

 "123456789"   -- 強いETag値
 W/"123456789"  -- 弱いETag値

強いETag値が一致すれば、2つのリソースが1バイトも変わらず、またContent-Languageなどのヘッダも変わっていないことを示す。強いETagはキャッシュや部分リクエストにも使いうる。

弱いETag値が一致した場合、2つのリソースは意味合いとして同じ、つまり実用的にはキャッシュされたものを代用できる、ということを示している。ただ、1バイトも変わらず同じであることは保証されず、部分リクエストのバリデーションには使えない。これは、Webページを動的に生成する場合など、強いETagをサーバで生成することが現実的でない場合に使うことができる。

ETagの生成 
ETagの生成はHTTPにおいて必須ではなく、またETagの生成方法については特に規定がない。

一般には、リソースの内容に対して、衝突耐性のあるハッシュ関数を使う、最終更新日時のハッシュを取るなどの手法が取られる。

古いキャッシュを再利用してしまうという問題を起こさないようにするには、ETagの値が一意であること（少なくとも、重複が無視しうる程度であること）を保証する必要があるが、
CRCのような単純なチェックサム関数を使うと、衝突が起こってしまいETagによるキャッシュの判定が正常に行われない危険性がある。

また、サーバの実装によっては、ディスク上のinodeなど、環境依存の値をETagに使うケースも存在する。この場合、Webサーバをクラスターとしている、あるいは複数のサーバを使っていると、1つのサーバから返されたETagが次のリクエストの際に別なサーバで照合すると一致しない、ということとなり、キャッシュの効率性が損なわれる結果となる。

ETagによる追跡 
Cookieがプライバシーに敏感な利用者によって削除されていっているが、ETagをユーザーの追跡に使うことも可能である。2011年7月には、Ashkan Soltaniとカリフォルニア大学バークレー校の研究者が、利用者追跡のためにETagを使うWebサイトについて報告を行っている。

ETagはブラウザにキャッシュされて、リクエストのたびに送り返されるものであり、追跡サーバが同じETagを返し続けることで、永続的にユーザーを追跡することができる。

なお、ブラウザによって細かな点は異なるが、キャッシュをクリアすればETagも消去できる。

脚注

参考文献 
RFC 9110 HTTP Semantics 8.8.3. ETag: HTTPにおけるETagの定義
Concerning Etags and Datestamps by Lars R. Clausen (2004)

外部リンク 
Apache HTTP Server Documentation - FileETag Directive
Editing the Web: Detecting the Lost Update Problem Using Unreserved Checkout, W3C Note, 10 May 1999.
Old SQUID Development projects - ETag support (completed in 2001)
Using ETags to Reduce Bandwidth & Workload with Spring & Hibernate
ETagを使ってSpringとHibernateの転送量と負荷を削減する

ETag