純粋なHTMLファイルで、余計なヘッダーやMETAタグを付けていなければ一定期間、ブラウザ上にあるキャッシュを見させると言うことは出来たりします。
これって、PHPででも出来るのかなとふと思い検証してみました。
(特にそれで困ったことがあったわけではないのですが)
で、結論から言えばApacheの設定やヘッダーによる制御で、PHPを意図的にローカル(ブラウザ)のキャッシュを利用させるということは出来ませんでした。
キャッシュされているか否かでいえばキャッシュされているようなんですが、要は(あえてHTTステータスコードを返すようなことを除いて)ヘッダーやMETAタグだけの制御により、サーバーから304レスポンス返してブラウザにあるキャッシュを意図的に見せたい、ってことができない。
キャッシュ制御に関するおさらい
純粋にクライアント-サーバーのシステム構成で、間にプロキシサーバーなど余計なものを介在しなければ、キャッシュが働く場所は、クライアント(ブラウザ)とアプリケーション(Web)サーバーになります。
今回、アプリケーションサーバー上にはキャッシュの機構は特に用意していません。
ブラウザ上のキャッシュを”利用させたくない”場合、HTTPヘッダーやMETAタグに下記のように記載しておきます。
// PHPの場合 header("Cache-Control: no-cache"); // METAタグに入れる場合 <META HTTP-EQUIV="Cache-control" CONTENT="no-cache" />
// PHPの場合 header("Pragma: no-cache"); // METAタグに入れる場合 <META HTTP-EQUIV="Pragma" CONTENT="no-cache" />
※ HTTP/1.0用のため古い制御の仕方
// PHPの場合 header("Expires: -1"); // METAタグに入れる場合 <META HTTP-EQUIV="Expires" CONTENT="-1" />
ただ、純粋なHTMLファイルの場合、METAタグを正しく入れてもブラウザのキャッシュが利用されたりします。
一方で、キャッシュを”させたい”場合というのは、上記のヘッダーやMETAタグを入れないか、唯一制御できるCache-Controlを使用します。
<META HTTP-EQUIV="Cache-control" CONTENT="private, max-age=3600" />
その他にも、ApacheでExpiresを設定し強制的にキャッシュさせるようにすることも可能です。
詳細は、Apacheのドキュメント を参照。
ExpiresActive On ExpiresByType text/html "access plus 1 hours"
PHPに対してローカルキャッシュを利用させる試行錯誤
と言うことで本題。
まず、PHPとHTMLとで中身としては同意なファイルを作り、それぞれに2度アクセスしてみます。
<html> <head> <META HTTP-EQUIV="Cache-control" CONTENT="private, max-age=3600" /> </head> <body> hello </body> </html>
<?php echo " <html> <head> <META HTTP-EQUIV='Cache-control' CONTENT='private, max-age=3600' /> </head> <body> hello </body> </html> ";
上記のファイルへのアクセスした際のHTTPヘッダをLive HTTP Headers で見てみます。
http://www.example.com/hoge.html GET /hoge.html HTTP/1.1 Host: www.example.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.2) Gecko/20100115 Firefox/3.6 (.NET CLR 3.5.30729) Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json Accept-Language: ja,en-us;q=0.7,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7 Keep-Alive: 115 Connection: keep-alive If-Modified-Since: Wed, 09 Jun 2010 15:21:04 GMT Cache-Control: max-age=0 HTTP/1.1 200 OK Date: Wed, 09 Jun 2010 15:34:26 GMT Server: Apache/2.2.3 (CentOS) Last-Modified: Wed, 09 Jun 2010 15:29:59 GMT Accept-Ranges: bytes Content-Length: 119 Connection: close Content-Type: text/html ---------------------------------------------------------- http://www.example.com/hoge.html GET /hoge.html HTTP/1.1 Host: www.example.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.2) Gecko/20100115 Firefox/3.6 (.NET CLR 3.5.30729) Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json Accept-Language: ja,en-us;q=0.7,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7 Keep-Alive: 115 Connection: keep-alive If-Modified-Since: Wed, 09 Jun 2010 15:29:59 GMT Cache-Control: max-age=0 HTTP/1.1 304 Not Modified Date: Wed, 09 Jun 2010 15:34:31 GMT Server: Apache/2.2.3 (CentOS) Connection: close User-Agent
2度目のアクセス時には、304ステータスコードが返ってきてローカルキャッシュが使われていることがわかります。
次に、PHPの場合
http://www.example.com/hoge.php GET /hoge.php HTTP/1.1 Host: www.example.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.2) Gecko/20100115 Firefox/3.6 (.NET CLR 3.5.30729) Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json Accept-Language: ja,en-us;q=0.7,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7 Keep-Alive: 115 Connection: keep-alive Cache-Control: max-age=0 HTTP/1.1 200 OK Date: Wed, 09 Jun 2010 15:38:21 GMT Server: Apache/2.2.3 (CentOS) X-Powered-By: PHP/5.1.6 Content-Length: 120 Connection: close Content-Type: text/html ---------------------------------------------------------- http://www.example.com/hoge.php GET /hoge.php HTTP/1.1 Host: www.example.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.2) Gecko/20100115 Firefox/3.6 (.NET CLR 3.5.30729) Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json Accept-Language: ja,en-us;q=0.7,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7 Keep-Alive: 115 Connection: keep-alive Cache-Control: max-age=0 HTTP/1.1 200 OK Date: Wed, 09 Jun 2010 15:38:23 GMT Server: Apache/2.2.3 (CentOS) X-Powered-By: PHP/5.1.6 Content-Length: 120 Connection: close Content-Type: text/html
2度目も200のステータスコードが返され、キャッシュを利用していません。
header()を使ってCache-controlを指定してもダメです。
HTTP/1.1 200 OK Date: Wed, 09 Jun 2010 15:48:36 GMT Server: Apache/2.2.3 (CentOS) X-Powered-By: PHP/5.1.6 Cache-Control: private,max-age=3600 Content-Length: 120 Connection: close Content-Type: text/html
レスポンスヘッダ内にしっかりCache-Controlの指定がされているのですが、何回リロードしてもキャッシュを利用してくれません。
他にも、Apacheの設定ファイル内で
# ETagを使用しない FileETag None # Expiresを指定 ExpiresByType text/html "access plus 1 hours"
みたいな事もやってみましたが効果なし。
結局、全て200ステータスコードを返してきます。
ちなみに、304のステータスコードを強制的に返してやるとキャッシュを使ってくれます。
HTTP/1.1 304 Not Modified Date: Wed, 09 Jun 2010 15:58:41 GMT Server: Apache/2.2.3 (CentOS) Connection: close Expires: Wed, 09 Jun 2010 16:58:41 GMT Cache-Control: max-age=3600
PHP側でレスポンスヘッダを制御する方法は、下記のエントリが参考になります。
304 Not Modifiedをhttpレスポンスヘッダで制御する方法(If-Modified-Since偏) @ pblo
このことからもPHPのファイルとはいえ、ブラウザ内にキャッシュはされていると言うことがわかります。
実際、PHPから出力しているHTMLの一部を変更してリロードしても古い情報が引き続き表示されたりします。
予断ですが、PHP側で304を常に返すようにしておいて、ブラウザのキャッシュをクリアしたらどうなるかって実験をしたら、きちんと最新のページを読んできました。
これは、矛盾していることではあるんですがApacheのログを見ても
192.168.0.100 - [10/Jun/2010:01:05:24 +0900] "GET /hoge.php HTTP/1.1" 304 305 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.2) Gecko/20100115 Firefox/3.6 (.NET CLR 3.5.30729)"
とか出ていて、ステータスコードとかって当てに出来ないんだなとか思ったり。
最後に、PHPを複数の拡張子で動作できるようにしている場合があったりしますが、それについてもキャッシュが有効に働いてくれないようです。
AddType application/x-httpd-php .php .htm
上記のような場合、.htmファイルでもPHPが動くようになります。
ただ、純粋なHTMLファイルとしても動くわけなのですが、PHPの処理を一切書いていない、下記のようなファイルであってもキャッシュが働いてくれませんでした。
- hoge.htm(PHPは動作可能だが、処理を一切書かずにHTMLのみにしたファイル)
<html> <head> <META HTTP-EQUIV='Cache-control' CONTENT='private, max-age=3600' /> </head> <body> hello </body> </html>
http://www.example.com/hoge.htm GET /hoge.htm HTTP/1.1 Host: www.example.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.2) Gecko/20100115 Firefox/3.6 (.NET CLR 3.5.30729) Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json Accept-Language: ja,en-us;q=0.7,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7 Keep-Alive: 115 Connection: keep-alive Cache-Control: max-age=0 HTTP/1.1 200 OK Date: Wed, 09 Jun 2010 16:33:15 GMT Server: Apache/2.2.3 (CentOS) X-Powered-By: PHP/5.1.6 Content-Length: 119 Connection: close Content-Type: text/html
こう考えると、わざわざPHPにする必要の無いほぼHTMLのようなファイルや、PHPでも動作可能な拡張子のファイルってローカルキャッシュが上手く働いてくれずに無駄な処理が行われてしまうのかな。
[PR]
[PR]
関連記事
APC+jQuery UIを使ってファイルアップロード時にプログレスバーを表示する
Apache Tikaを使ってドキュメントの中身を取り出すPHPプログラム
PHPのセッションアダプションによって任意のセッションIDが受入れられる
Apacheから強制的にキャッシュを使わせないようにする方法
Apacheの404用ページが全然ステータスコード404を返していなかった
不要なApacheやPHPの拡張モジュールを削除するとどれくらい効果があるか調べてみる
ApacheのプロセスがどのPHPプログラムの処理をしているか調べる方法
mod_actionsを使ってドキュメントや画像、Flashファイルを保護する