たまには少しバイトでやってる Web アプリケーション作成の技術的な話を少し。同じネタですごく悩んでいる人がいたら少しは助けになるかもしれません。ネタはキャッシュの制御です。
Caching Tutorial for Web Authors and Webmasters
@IT:事例に学ぶWebシステム開発のワンポイント(12)
ブラウザキャッシュでパフォーマンス向上 ―負荷分散装置の落とし穴に注意-
よく Perl/CGI とか PHP、JSP、ASP などなど動的なページを表示させる時に困るのがブラウザキャッシュやプロキシでのキャッシュです。これがいたずらすると情報が更新されずに表示されてしまい新鮮なデータをユーザに提供することができません。
逆にキャッシュの利点としては静的な画像データや HTML ファイルを一時的に保存することでアクセス向上や Web サーバの負荷減少につながるわけです。
今回僕が直面した問題は、PHP で表示させているページがキャッシュにより新鮮な情報にならないということでした。ちなみにブラウザは i-mode(SH505i) でこの現象が起こりました。PHP ではセッションを用いたデータ管理をしていますが、携帯向けですので GET で PHPSESSID を引きまわす方法を取っています。
PC を対象としてキャッシュをさせないようにしたければ以下のようにしてあげればよいです。
Perl/CGI なら
print "Content-Type: text/html; charset=EUC-JP\n";
print "Expires: Sat, 01 Jan 2000 00:00:00 GMT\n";
print "Last-Modified: ". $gmtime\n";
print "Cache-Control: no-cache, must-revalidate\n";
print "Pragma: no-cache\n";
PHP なら
header("Content-Type: text/html; charset=EUC-JP");
header("Expires: Sat, 01 Jan 2000 00:00:00 GMT");
header("Last-Modified: ". gmdate("D, d M Y H:i:s"). " GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
という形にすればいいです。もちろんこれでキャッシュしないかどうかはクライアント側のブラウザの仕様にもよるわけです。
また、もちろんヘッダだけでなく META タグの中にも
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
といった記述は必要になるかと思います。
しかし上記の記述だけでは今回の携帯ではキャッシュが残ってしまいかなり悩みました。PHP で実装していましたので、apache_request_headers 関数やapache_response_headers 関数でヘッダの中身を見たのですがきちんと上記の header 関数で指定したものがサーバ側にリクエストされているようです。しかし実際のページは古い情報ですし、Apache のログを見てもステータスコードが 304(Not Modified)になっておりどうも具合が悪い...
# もちろんそのページをリロードすれば 200 コードで新鮮な情報が見れます。
セッション管理での session_cache_limiter や session_cache_expire といった関数で nocache や 0 といった値を与えても意味無しという状態でした...
で、色々試行錯誤していたのですが結論として、
header("Last-Modified: ". "Fri, 30 Oct 1998 14:19:41 GMT");
という一行だけを上記のずらずら並んだ header() の代わりに書いてあげるだけで対応できました!上記の header() では Last-Modified を gmdate() で取得していましたが、これをもっと古い日付にしてあげることでいいみたいですw
まだまだ勉強不足ですね... それとキャッシュを時間制御する場合はサーバ側の時間もきちんと正しいものに設定しましょう。
同じアプリケーションであっても別の環境だと session_cache_limiter 関数の設定ひとつで問題なく動作しているということもあって完全に環境依存な現象かもしれませんね。
ちなみに今回この現象が起きた環境は以下の通り。
Web サーバ : Apache 2.0.40
開発言語 : PHP 4.3.1
ブラウザ : 携帯電話 DoCoMo SH505i



