SOFTELメモ Developer's blog

会社概要 ブログ 調査依頼 採用情報 ...
てるてる動画

【php】phpでも304 Not Modified を返すことができる

問題

phpでもHTTPステータス304を返すことができるの?

答え

If-Modified-Since ヘッダが送られてきたら、HTTPステータスコード304を返すチャンス。

If-Modified-Since

If-Modified-Since リクエストヘッダフィールドは、メソッドを条件付きにするために使われる。もしリクエストされたバリアントがこのフィールドにて指定された時刻以降に更新されていなければ、サーバはエンティティを返す代わりに、304 (not modified) レスポンスをメッセージボディ無しで返すであろう。

If-Modified-Since = "If-Modified-Since" ":" HTTP-date

でも普通に動的なページを表示していると、If-Modified-Since が送られてくる場合はなかなかない。

以下、手順。

1、最初にアクセスされたら、コンテンツを返す。このとき、最終更新日時(Last-Modified)を送っておく。

header('Last-Modified: Fri Jan 01 2010 00:00:00 GMT');

最終更新日時が送ってあれば、2回目アクセスでは、If-Modified-Since が送られてくるはず!

2、2回目アクセスで If-Modified-Since が送られてきたかチェック。$_SERVERの中に発見!

......
......
  ["HTTP_HOST"]=>
  string(13) "192.168.......
......
  ["HTTP_IF_MODIFIED_SINCE"]=>
  string(28) "Fri Jan 01 2010 00:00:00 GMT"
  ["HTTP_CACHE_CONTROL"]=>
  string(9) "max-age=0"
......
......

$_SERVER は、ヘッダ、パス、スクリプトの位置のような 情報を有する配列です。この配列のエントリは、Web サーバにより 生成されます。全ての Web サーバがこれら全てを提供する保障はありません。 サーバは、これらのいくつかを省略したり、この一覧にない他のものを 定義する可能性があります。これらの変数の多くは、 » CGI/1.1 specification で定義されています。したがって、これらについては定義されていることを 期待することができます。

とのことだが、サーバー側もブラウザ側も期待した動きをしてくれたときにきちんと動作するので、細かいことは考えないことにする。

$_SERVERは信用できないなと思う人は、apache_request_headers()関数など環境に合った関数を使って取得するべし。

3、HTTPステータスコード304を返します!

header('HTTP/1.1 304 Not Modified');

サンプル

こんなスクリプトを試すことができる。

1回目アクセスで通常の200レスポンス(var_dump()の結果)。

2回目以降のアクセスは、ブラウザが賢いとキャッシュを使用するため、サーバーへのアクセスが発生しない。

そこでリロードボタンでわざとアクセスを発生させる。このとき、If-Modified-Since が送られたら、サーバー側は304を返し、304を受け取ったブラウザはキャッシュを使うという動きを確認できる。

さらに ctrl+F5を押すと、ブラウザは If-Modified-Since を送らないでコンテンツを改めて取得しようとし、サーバー側は通常通りコンテンツを返す。

<?php

header('Last-Modified: Fri Jan 01 2010 00:00:00 GMT');

if ($_SERVER['HTTP_IF_MODIFIED_SINCE']) {
	header('HTTP/1.1 304 Not Modified');
} else {
	var_dump($_SERVER);
}

関連するメモ

コメント