読者です 読者をやめる 読者になる 読者になる

7億円当てるまで書き続けるブログ

石油王のみなさーん! お知恵拝借!

ApacheのLast-Modifiedに関する動作とSSIについてのメモ

メモとか

発売日未定、タイトル未定の漫画を楽しみにしているとして、その発売が待ちきれないときのオタクを考えましょう。

発売日もタイトルもわからないので、オタクがその漫画を買うには、本屋さんの在庫の一覧から探すほかありません。贔屓にしている本屋さんの在庫リストは、その本屋さんに行って店員さんに聞くと手に入れることができます。

よわオタクは記憶力も堪え性もないので、毎日本屋さんに行って在庫の一覧を見せてもらいます。オタクが「在庫の一覧みせて」と店員さんに尋ねると、店員さんは毎回毎回在庫リストを書いて、オタクに渡します。このような毎日を繰り返すことで、店員さんは腱鞘炎になり、世界は外れ、紅世の炎に包まれます。

一方で、つよオタクは記憶力を持っているので、店員さんともう少し高度なコミュニケーションをとることができます。オタクが「昨日から在庫の追加あった?」と店員さんに尋ねると、在庫が追加されていない場合、店員さんは「ない」と書いて渡すだけでいいのです。在庫が追加されていた場合は、あきらめて在庫リストを書いてもらいます。

インターネットも、これと同じです。

  • Q: ブラウザ「このページxx時xx分xx秒以降に更新あった?」
  • A: サーバ「ないよ」
poncan:~ kiyooka$ telnet ai.ly 80
Trying 160.16.215.64...
Connected to ai.ly.
Escape character is '^]'.
GET / HTTP/1.1
Host: ai.ly
If-Modified-Since: Sun, 22 Jan 2017 15:30:00 GMT

HTTP/1.1 304 Not Modified
Date: Sun, 12 Mar 2017 14:41:47 GMT
Server: Apache
ETag: "7606fd-4e8-546b08e677715"

このようにやりとりすることで、トラフィックなどが少なく済み、インターネットの世界は平和に保たれています。Last-Modifiedの情報は、このようなやりとりのためだけでなく、ブラウザやロボットがコンテンツの最終更新日を記録しておく等、便利に扱うことができます。

ここで注意したいのは、条件によってはサーバ(ここではApacheについて記載)がレスポンスヘッダにLast-Modifiedを付加しない場合があることです。その一つが、コンテンツが動的に生成されている場合です。

ただのHTMLファイルやPNGファイルなどの静的なコンテンツをApacheが扱う場合、「コンテンツの最終更新日」は、そのファイルの最終更新日であると推測できます*1。なので、Apacheはそのファイルの最終更新日をLast-Modifiedに付加する情報とします。

しかし、CGIやSSIが有効なHTMLファイルなど、コンテンツがそのファイルから動的に生成されるコンテンツは、「コンテンツの最終更新日」がそのファイルの最終更新日とは限らないので、ApacheはレスポンスヘッダにLast-Modifiedを付加しません。

ここで、「SSIが有効なHTMLファイル」というのは、SSIが使われる可能性のあるすべてのファイルです。なので、Apacheに.htmlファイルでSSIを有効にするという設定をしている場合、すべての.htmlファイルでApacheはレスポンスヘッダにLast-Modifiedを付加しなくなります。

これが困る場合、Apacheの設定でSSILastModifiedをonにしておけば、「SSIが有効なHTMLファイル」でもApacheはLast-Modifiedを付加するようになります。

mod_include - Apache HTTP Server Version 2.4

AddType text/html .html
AddOutputFilter INCLUDES .html
<Directory "*">
SSILastModified on
</Directory>

なお、このようにしてLast-ModifiedとIf-Modified-Sinceがそれぞれのヘッダに付加された場合でも、Apacheはそれを利用して304 Not Modifiedを返すことをしません。

poncan:~ kiyooka$ telnet ai.ly 80
Trying 160.16.215.64...
Connected to ai.ly.
Escape character is '^]'.
GET / HTTP/1.1
Host: ai.ly
If-Modified-Since: Sun, 22 Jan 2017 15:30:00 GMT

HTTP/1.1 200 OK
Date: Sun, 12 Mar 2017 15:17:44 GMT
Server: Apache
Last-Modified: Sun, 22 Jan 2017 15:30:00 GMT
Accept-Ranges: bytes
Content-Length: 1256
Content-Type: text/html; charset=UTF-8

<!DOCTYPE html>
(以下略)

ですので、きちんとLast-ModifiedとIf-Modified-Sinceがやりとりされたとしても、トラフィックなどが減ることはなく、むしろこのヘッダが付加される分すこし増えてしまいます。世界は紅世の炎に包まれます。

トラフィックをできるだけ抑えるためにも、またApacheの無駄な処理を抑えるためにも、SSIを使うときには、.html全体でSSIを有効にすることは避け、.shtmlに限定する、あるいは特定のディレクトリに限定するようにしたいところです。封絶のようなものですね。

”紅世の徒”による『世界の歪み』を防ぐためにも、SSIを使うときにはよく考えようという話でした。今更SSIを使う場面も、あんまりないとは思いますが。

*1:もちろん、そのコンテンツの公開日≠ファイルの最終更新日となる場合も多々あります。