キャッシュ期限切れが出る問題を調査してみる修行

調査依頼。情報の検索をし、結果の一覧からひとつを選んで詳細ページが見られる、というよくあるサイト。メニューから情報検索のページに行ったときは、検索条件なしでの検索結果が出る。すなわち全データが一覧される。このサイトにおいて、詳細ページを見た後、ブラウザの「戻る」ボタンで戻った際に、普通に検索画面に戻れるケースと、「キャッシュが無効です」的ページになってしまうケースがある。
いろいろ試してみると、

  1. [メニュー] -> [検索ページ] -> (一覧された全データの一つを) [詳細表示] -> [ブラウザの戻るボタン]
  2. [メニュー] -> [検索ページ] -> [検索条件をつけて検索] -> (一覧されたデータの一つを) [詳細表示] -> [ブラウザの戻るボタン]

で動作が違う。すなわち、1. では普通に検索画面に戻り、2. では「キャッシュが無効」画面になる。

HTTP レスポンスヘッダでキャッシュさせない設定にしているから、というのはすぐわかる。1. と 2. では何が違うのか、というと、ブラウザのボタンで戻る先のページのリクエストメソッドが GET か POST か、という違い。1. はメニューからのリンクなので GET リクエストされたもの、2 は検索条件を POST で送っているので POST リクエストしたもの。両者ともキャッシュを禁止されているので、ブラウザはキャッシュを使わない。
GET の場合は単にもう一度リクエストを飛ばし、戻ってきたものをレンダリングする。つまり、ブラウザの戻るボタンで戻ったときにも再リクエストが飛んでいることになる。
一方、POST は勝手に再 POST するわけにはいかないので、「キャッシュが無効」画面を出すことになる。

ちなみにこれは IE での動作。Firefox の場合 GET の動作は同じだが、POST の場合は「もう一回ポストしてもいい?」という確認画面になる。

解決策はいくつかあるが、まずはキャッシュのコントロールをちゃんとやること。PHP のキャッシュコントロールはよくわからないところがあったが、デフォルトの設定だと「ともかくキャッシュ禁止!」というレスポンスヘッダを送るようになっているようだ。そして、キャッシュコントロールのメソッドは、session とは直接関係ないのに session_cache_limiter() という関数でコントロールすることになっているらしい。
PHP とキャッシュコントロールの話は http://www.glamenv-septzen.net/pukiwiki/index.php?PHP%2F%A1%D6%A5%DA%A1%BC%A5%B8%A4%CE%CD%AD%B8%FA%B4%FC%B8%C2%C0%DA%A4%EC%A1%D7%C2%D0%BA%F6 によくまとめられている。

また、一般的に言えば、検索条件を POST で送る、という設計がよくない。検索条件はサイトに情報を POST するために送るのではなく、サイトから情報を GET するための条件として渡しているから。