久しぶりにrewrite定義を追加してコンテンツのfailbackを考える機会がありました。
rewriteをすると、いつもproxyキャッシュやブラウザキャッシュでトラブルなぁと苦い思い出があります。
その際の対応として、キャッシュをさせない設定をHTMLに埋め込むのですが、毎回調べるので、
メモしておきます。
前置きとしてWEBのキャッシュとは。
ブラウザからWEBサイトにリクエストを発行すると、コンテンツがレスポンスされます。
この挙動によりWEBサイトを閲覧しているのですが、WEBサイトのコンテンツは大きいものから小さいものまであります。特に毎回大きいサイズのWEBコンテンツを表示するために通信を行うと、非効率です。
そのため、Proxy(プロキシ)やブラウザは、過去にアクセスしたWEBコンテンツを一時保存しておいて、アクセスするたびにコンテンツを要求しないようにして効率的に通信します。。これがWEBキャッシュ。
WEBキャッシュはhtmlや画像(gif、jpg等)、静的コンテンツと呼ばれる、毎回アクセスする度に変化が起きないものを一時保存します。
動的コンテンツ(asp、jsp、php等)は、毎回アクセスする度に変化が起きるためキャッシュされないようにアプリケーションサーバがキャッシュしない命令を埋め込んでくれています。
このようにキャッシュは便利に思えるのですが、一時的にコンテンツを置き換えた時など、キャッシュされてしまうと困ることもあります。
そのような場合、キャッシュをさせない方法があります。
HTTPヘッダーで制御する方式
キャッシュ制御の定義はRFC2616にて規定されています。
RFC2616に従うと、HTTP通信のリクエストヘッダー、および、レスポンスヘッダーに以下の定義を加えることでキャッシュをコントロールできます。
Cache-Control (HTTP/1.0では効果なし)
- public 共有のキャッシュとして使え
- private 非共有のキャッシュとして使え
- no-cache 再利用可能なキャッシュかどうか判断した上で使え(注意:キャッシュするなではない)
- no-store キャッシュするべからず
- max-age=? 指定した秒数がキャッシュの有効期限
- min-fresh=? 指定した秒数キャッシュが最新と判断する
- max-stale=? 指定した秒数は最新でなかろうと受け入れる
Pragma(HTTP/1.0でのみ効果)
- no-cache キャッシュを使うな
HTTPのMETAタグで制御する方式
(注意)
METAタグにて制御する方式は広くWEBで公開されているが、効果が確実なものではありません。
RFC2616によると、キャッシュの命令はレスポンスヘッダーにて定義するものと規定されているので、
ここから紹介するMETAタグ方式はブラウザやProxyが独自に取り入れているものと言えます。
つまり、この方式はブラウザやProxyに依存するもので、確実に効果があるとは言えません。
HTML4.xまでの書き方
<meta>
要素の http-equiv
属性に Pragma, Cache-Control, Expires などを指定して制御します。
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <!-- この設定でHTTP1.0プロトコルでProxyキャッシュさせない //--> <meta http-equiv="Pragma" content="no-cache"> <!-- この設定でHTTP1.1プロトコルでProxyキャッシュさせない //--> <meta http-equiv="Cache-Control" content="no-store"> <!-- この設定でキャッシュされたコンテンツの有効期限を即切れにする。ブラウザキャッシュ対応 //--> <meta http-equiv="Expires" content="0"> <title>page title here</title> </head> <body> ... </body> </html>
http-equiv="Pragma" はHTTP1.0プロトコルでしか判別できない古いProxyに対応するために記載する。値はno-cacheにすることで、キャッシュされない。
http-equiv="Cache-Control"はHTTP1.1プロトコルに対応したキャッシュ指定。値の候補は4種類あるが、キャッシュさせない設定はno-cacheとno-storeである。
no-cacheは間違えて紹介されているサイトが多いので注意が必要。キャッシュさせないのではなく、キャッシュされるが、If-Modified-Sinceをリクエストし、コンテンツが有効でない限りキャッシュを利用してはならないという意味である。
全くキャッシュさせないためにはno-storeを定義する。
http-equiv="Expires"はブラウザキャッシュに対応するために定義する。ブラウザのキャッシュの有効期限を0にすることで、即有効期限切れにするため、キャッシュしていない状態とほぼ同等になる。
ただし、これに対応されていないブラウザも存在するため、確実なものではない。
HTML5の書き方
<html>
要素の manifest
属性でキャッシュマニフェストファイルの URI を指定します。
manifest
属性は、キャッシュ対象にするすべてのページに指定する必要があります。 manifest
属性が含まれていないと、キャッシュマニフェストファイルで明示されていない限り、ブラウザはそのページをキャッシュしません。
<!DOCTYPE html> <html lang="ja" manifest="sample.appcache"> <head> <meta charset="UTF-8"> <title>page title here</title> </head> <body> ... </body> </html>
例)sample.appcashe
CACHE MANIFEST # version: 1.0.0 CACHE: sample.gif FALLBACK: /test.py /sorry.html NETWORK: *
この例では、 sample.gif というファイルはキャッシュされ、それ以外のリソースはキャッシュせずにサーバーから取得させるようにしています。
また、/test.py
が取得できない時は /sorry.html
をフォールバックリソースとして提供するようにしています。
CACHE MANIFEST
1行目の CACHE MANIFEST
はキーワードで、必ずこの文字列を1行目に記述する必要がある。
コメント
#
で始まる行はコメント。
キャッシュファイルを更新するようにブラウザに通知するには、マニフェストファイルが更新される必要がある ので、キーワードのすぐ後にバージョン番号等を入れる。
CACHE:
CACHE:
セクション(または CACHE MANIFEST
のすぐ下)に、キャッシングするリソースの URI を列挙する。
ワイルドカードは使用できない。
NETWORK:
NETWORK:
セクションには、サーバーへの接続を必要とするリソースの URI を列挙する。
こちらは、ワイルドカードを使用できる。
FALLBACK:
FALLBACK:
は、リソースにアクセス出来ない場合のフォールバックページを指定する。
ワイルドカードを使用ができる。
行の最初の URI は対象リソース(本丸)で、2つ目の URI がフォールバック(代替)。