Not Foundページを作る

4月20日のエントリで不正なURIをはじくRewriteルールを設定しました。このエントリで書いてあるhttp://www.hogehoge.com/404.htmlは、バックエンドには存在しないので、404ページが表示されます。

で、ちょっとイヤなのがせっかくApacheで不正URIって分かっているのにバックエンドへリクエストをプロクシしてしまっているところ。いらないリクエストですからフロントエンドで処置してしまいたい。

RewriteされたURLをApacheで処理

現行こうなっています。

RewriteCond     %{REQUEST_URI}  "^/hoge/(foo|baa)/"
RewriteCond     %{REQUEST_URI}  "!/hoge/(foo|baa)/.*\.(html|htm|xhtml)$"
RewriteRule     ^(.*)$    /404.html [P]

これはこのままにしておいて、リライトされた404.htmlをローカルで処理するように以下を追加。

ProxyPass    /404.html    !

でもって、DocumentRoot以下に404.htmlを配置。
うむ、これで大丈夫みたい。

でもレスポンスコードが200ですよ?

でも、これ存在するページを返すことになるのでレスポンスコードは200になってしまいます。うーむどうしよう。

mod_rewriteのRedirectを使う

さてどうしようと考えながらmod_rewriteとかmod_headerで何とかならんかとドキュメントをあさることしばし。mod_headerはヘッダはコントロールできるけど、レスポンスコードはヘッダじゃない。mod_rewriteのRフラグの説明にこんなのがありましたよ。

'redirect|R [=code]' (force redirect)
Prefix Substitution with http://thishost[:thisport]/ (which makes the new URL a URI) to force a 
external redirection. If no code is given, a HTTP response of 302 (MOVED TEMPORARILY) will be 
returned. If you want to use other response codes, simply specify the appropriate number or use
 one of the following symbolic names: temp (default), permanent, seeother. Use this for rules to
 canonicalize the URL and return it to the client - to translate ``/~'' into ``/u/'', or to 
always append a slash to /u/user, etc.
Note: When you use this flag, make sure that the substitution field is a valid URL! Otherwise,
 you will be redirecting to an invalid location. Remember that this flag on its own will only 
prepend http://thishost[:thisport]/ to the URL, and rewriting will continue. Usually, you will 
want to stop rewriting at this point, and redirect immediately. To stop rewriting, you should add 
the 'L' flag.

While this is typically used for redirects, any valid status code can be given here. If the 
status code is outside the redirect range (300-399), then the Substitution string is dropped and
 rewriting is stopped as if the L flag was used.

おお。[R=404]って書けば引っ掛けたURIのときにNot Foundを返してくれるみたい*1。ということでRewriteRuleを以下のように変更。

    RewriteRule     ^(.*)$    -     [R=404]

これで試してみると、Apacheのデフォルト404ページが表示されました。これはもう一息。

ErrorDocumentを指定

最後はErrorDocuemntを指定すればOK。

    ErrorDocument       404     /404.html

まとめ

ってことでまとめ。

#レスポンスコード404の時に表示するページを指定する。
    ErrorDocument       404     /404.html 
#私の環境ではすべてのリクエストをバックエンドへプロクシしているが、
#404.htmlはプロクシしない。
  ProxyPass           /404.html     ! 
  ProxyPass           /            http://somewhere/
#Rewriteルール
  RewriteCond     %{REQUEST_URI}  "!/hoge/(foo|baa)/.*\.(html|htm|xhtml)$"
  RewriteRule     ^(.*)$    -    [R=404]

*1:というより、任意のレスポンスコードを設定できるってことですね