| « Google Related Links | rel="tag"というMicroformat » |
コンテント ネゴシエーション経由でPHPにリクエストを渡すのをやめた
この間まで、PHPスクリプトをデフォルトの
AddType application/x-httpd-php .php
ではなく、
SetHandler php-script .php AddType text/html .php
と設定して、扱うようにしていた(過去の経緯については、p89参照)。
このブログのように、PHPスクリプト自体に.phpという拡張子が付いてるにも拘らず、それを含めないような形でアクセスさせるようにしている場合、接続クライアントが、
GET /blog/FreeBSD Accept: text/html,*/*
のようにアクセスして来れば問題ないけど、
GET /blog/FreeBSD Accept: text/html
とワイルドカードを含めず、Acceptタイプを限定してきた場合、サーバ側には、FreeBSD.phpは存在するけど、それのタイプは、application/x-httpd-phpであって、クライアントの要求するtext/htmlのタイプではない。他に代替するものがないと、
406 Not Acceptable
というエラーをサーバが返してしまうので、それを回避するため上記のような設定をした(ただし、ACCEPTヘッダにワイルドカードを付けずにリクエストを送信してくるクライアントは、Ask Jeeves/Theomaなど、ごく一部)。
通常、以上で問題ないはずなんだけど、b2evolutionには、静的なHTMLファイルを生成する機能があって、一番アクセス頻度が高いと予想されるトップ ページの部分を、予め静的なファイルとして、書き出しておくことが出来る(b2evolutionで静的なファイルを生成できない場合の回避策は、p88参照)。
問題は、同一のURLで、これらを使い分けようとすると生じて来る。
この場合、サーバ上には、同じタイプ(text/html)の
FreeBSD.phpFreeBSD.html
という2つのファイルが存在するようになって、
GET /blog/FreeBSD
とした場合、どれを選択していいのか判らなくなるからである。
mod_writeを使って、
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{PATH_INFO} ^$
RewriteRule ^blog/FreeBSD$ /blog/FreeBSD.html
と引数がない場合は、静的な方(FreeBSD.html)を表示しようとしても、なぜかPHPの方に横取りされてしまって、機能しなかった。
もっとも、静的なHTMLの方は、FreeBSD.htmlといった名前にしておく必要もないので、
static-FreeBSD.html
と改名し、ついでに、FreeBSD.phpの方も拡張子を取り除いて、FreeBSDとし、
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{PATH_INFO} ^$
RewirteRule ^blog/FreeBSD$ /blog/FreeBSD.html
RewirteRule ^blog/FreeBSD$ /blog/static-FreeBSD
<Files ~ ^FreeBSD$> SetHandler php-script AddType text/html </Files>
のように設定したら、とりあえず、意図した動作になった。
(これは要するに、コンテント ネゴシエーションで、リクエストをPHPに渡すのをやめたということだな…)
せっかく、Apacheに、コンテント ネゴシエーションの機能を導入しているので、静的なファイルの方を
static-FreeBSD.html.jastatic-FreeBSD.html.ja.gz
といろいろ作って、遊んでたけど、
Content-Type: application/x-gzip Content-Language: ja
なもの(上記の場合では、FreeBSD.html.ja.gz)は、ある種のプロキシ経由じゃ、閲覧できないみたい。
Trackback address for this post
Trackback URL (right click and copy shortcut/link location)
3 comments
現状、静的なHTMLの方は、微妙に動的に出力されるコンテンツの内容(リンクのURL等)が異なるので、それの利用は保留中です。
本文の方に、.htaccessを
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{PATH_INFO} ^$
RewirteRule ^blog/FreeBSD$ /blog/static-FreeBSD
のように書いてたけど、これだとログイン状態(クッキーにIDとパスワードのハッシュが保存される)の時でも、
GET /blog/FreeBSD
とした時に、静的に書き出したHTMLの方が表示されてしまう。
また、
http://www.xdelta.net/blog/FreeBSD
のURLを閲覧していた後、ログインフォームに入ると、IDとパスワードのPOST先が同じ
http://www.xdelta.net/blog/FreeBSD
というURLになってしまう(前見ていたページへPOSTで戻る)ので、メソッドによって分けなければならない(静的なHTMLにPOSTしてもしょうがないし、このURLからはログインできなくなる)。
したがって、該当する.htaccess
RewriteCond %{REQUEST_METHOD} ^(?:HEAD|GET)$ RewriteCond %{QUERY_STRING} ^$ RewriteCond %{PATH_INFO} ^/?$ RewriteCond %{HTTP_COOKIE} !cookieb2evouser= RewriteCond %{HTTP_COOKIE} !cookieb2evopass= RewriteRule ^blog/(all|FreeBSD|masken|links)/?$ /blog/cache-$1.html [L]
という具合に修正(ディレクトリと勘違いするユーザもいるので、スタブ ファイルの最後にスラッシュを付けてても良い事にしてる。また、静的なコンテンツの方でもネゴシエーションを使用しないことにするので、ファイル名を最後まで付ける)。
あと、クッキーの内容で表示するコンテンツを切替えるので、プロキシにキャッシュされないよう
<Files ~ "^cache-(?:all|FreeBSD|masken|links)\.html$"> Header append Vary "Cookie" Header set Cache-Control "private, must-revalidate, max-age=0" Header set Expires "-1" </Files>
も明示。
PHPの方にも、VaryヘッダにCookieを付け加えた方が良い(この辺は、b2evolutionの役割だと思うけど)。
しかし、ページを更新する度に、管理画面から手動で静的なHTMLを生成するのは、はっきりいって面倒(よって、また、静的なHTMLを生成することは却下…)。
先日、Apache 2.2にもしたことだし、cache_moduleの使用を試みてみたけど、preforkだと、disk_cache_moduleしかモジュールが生成されないみたいで、これだと余程速いディスクでない限り、却ってパフォーマンスが落ちてしまう気がする…。
そのうち、workerでも、試みてみようかな? mem_cache_moduleが使えると思うし。
This post has 107 feedbacks awaiting moderation...