ETagとは
キャッシュの有効性確認をするために使われる値です。
- データを返すときにETagという値をレスポンスヘッダーで返す
- 同じデータにアクセスするときキャッシュしているリクエストヘッダーにETagの値を付与します
- サーバーはクライアントから受け取ったETagの値とレスポンス時のETagの値を比較して、異なった場合はステータスコード200で通常通りデータ全てを返却、同じだった場合はステータスコード304(Not Modified)とだけ返します
これにより、304で返すときはデータを返さなくて良いのでダウンロード時間を減らせたり、サーバー側の帯域を減らすことができます。
利点と欠点
Cache-Controlヘッダーと比較した場合、サーバー側でキャッシュが制御できるという利点がありますが、毎回リクエストが飛んでしまうという欠点があります。
ETagを使用する場合
複数台のサーバーで運用する場合、同じファイルをデプロイしたときに各サーバー間で同じETagになるか確認しておく必要があります。
例えばCapistranoでのデプロイの場合下記の様になりました。
Capistranoでのデプロイ
Capistranoでデプロイした時のファイルを stat public/css/style.css
でETagに使われる情報を見てみたところ以下の様になりました。
Server1とServer2でSizeとModifyの値が同じなのでどちらのサーバーにアクセスが来ても同じETagを返すことが分かります。
Server1
File: ‘public/css/style.css’
Size: 16364 Blocks: 32 IO Block: 4096 regular file
Device: cxxxx/xxxxxd Inode: 1234567 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 505/ app) Gid: ( 505/ app)
Access: 2017-12-27 19:21:25.656951609 +0900
Modify: 2017-12-27 19:19:32.000000000 +0900
Change: 2017-12-27 19:21:25.656951609 +0900
Birth: -
Server2
File: ‘public/css/style.css’
Size: 16364 Blocks: 32 IO Block: 4096 regular file
Device: cxxxx/xxxxxd Inode: 7654321 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 505/ app) Gid: ( 505/ app)
Access: 2017-12-27 19:21:25.629318890 +0900
Modify: 2017-12-27 19:19:32.000000000 +0900
Change: 2017-12-27 19:21:25.629318890 +0900
Birth: -
Apacheの場合
inode番号を含めると脆弱性に繋がる場合があるのと、複数台運用の場合返すサーバーによって同じファイルでもETagの値が変わってしまうので外します。
OK
FileETag MTime Size
NG
FileETag INode MTime Size
FileETag ALL
Nginxの場合
NginxではETagの設定はon/offしかできないですが、変更日時とファイルサイズのみで決まる様なのでApacheのOKの設定と生成方法が同じになります。
ちなみに
AWSのS3から配信される場合のETagはファイルのハッシュ値になっている様です。おそらくこれがApacheやNginxでできたらベストだと思います。