Writing a custom error responses with a little device

HOME > Articles > Apacheのエラーレスポンスをちょっと工夫して書く方法
 [Search]  [Site Map]

Apacheのエラーレスポンスをちょっと工夫して書く方法をご紹介します。

カスタムエラーレスポンス

Apacheでは、サーバでエラーが発生した場合に表示されるレスポンス(以下、エラーレスポンス)をカスタマイズする手段が提供されています。たとえば、ユーザが存在しないURLを指定したり、デッドリンクをたどって来た場合などに表示される"404 Not Found"というメッセージは、エラーレスポンスの1つです。

Apacheでは、ユーザがカスタマイズしたエラーレスポンスを「カスタムエラーレスポンス」と呼んでいます。カスタムエラーレスポンスの提供手段としては、以下の3つが用意されています:

  1. テキスト
  2. ローカルのURLへのリダイレクト
  3. 外部のURLへのリダイレクト

これら、カスタムエラーレスポンスの設定方法については、apache.orgのカスタムエラーレスポンスに関するドキュメントが参考になります。

しかし、apache.orgのドキュメントだけでは、実際に設定するのに有用そうな情報が得られませんでした。そこで、ここでは、motchie.comで採用している方法をご紹介します。

ここでご紹介する設定を使うと、以下のような機能を備えたエラーレスポンスを生成できます:

  1. エラーの元になったURLをビジターに示すことができる
  2. ビジターの使用言語にあわせてエラーレスポンスの言語を切り替えられる

以下に、ここでご紹介した機能を用いたエラーレスポンスの例を示します:

英語を使用するビジター用のエラーレスポンス

図1: 英語を使用するビジター用のエラーレスポンス

日本語を使用するビジター用のエラーレスポンス

図2: 日本語を使用するビジター用のエラーレスポンス

.htaccessの設定

以下に、"404 Not Found"を例に手順をご紹介します。まず、DocumentRoot(public_htmlなど)となるディレクトリに、.htaccessファイルを作成し、以下のディレクティブを追加します(既にDocumentRootに.htaccessファイルがある場合は以下の記述を追加します。また、ファイル名はApacheの管理者の設定により.htaccessではない場合があります)。

ErrorDocument  404  /errordocs/404.shtml

ここで、/errordocs/404.shtml というのは、エラーレスポンスを記述する.shtmlファイルへのパスです。パスは、DocumentRootからの相対パスで指定します。例えば、この指定がmotchie.comのものだったとしたら、http://www.motchie.com/errordocs/404.shtmlというURLでブラウザからアクセス可能になるようなパス、ということになります。

また、今回ご紹介するエラーレスポンスは、SSI ( Server Side Include )を用いているので、少なくとも /errordocs ディレクトリでSSIが有効になる必要があります。また、SSIの解析対象となる拡張子が、.shtmlではない場合も考えられます。

エラーの元になったURLの表示

エラーの元になったURLは、SSI用の環境変数と、カスタムエラーレスポンス用の環境変数から取得することができます。

まず、エラーの元になったURLのうちサーバのFQDNの部分については、SSIのSERVER_NAME環境変数で取得することができます。また、パス名の部分はカスタムエラーレスポンス用のREDIRECT_URL環境変数から取得することができます。また、スキーム名の部分は自分で書く必要があります。

以上より、例えば、「http://www.motchie.com/foo/は存在しないURLです。」と出力しようとすると、

http://<!-- #echo var="SERVER_NAME" --><!-- #echo var="REDIRECT_URL" -->は存在しないURLです。

ビジターの使用言語にあわせてエラーレスポンスの言語を切り替える

実は、このトピックスに関しては、apache.orgに"Using XSSI and ErrorDocument to configure customized international server error responses"があり、以下でご紹介するよりも高機能だと思われますが、ここでは簡易版ともいえる方法をご紹介しています(簡易版とは言いながら、以下でご紹介する機能は、"MultiViews"ディレクティブが無効だったり、type-mapハンドラが用意されていなくても動くという利点があります)。

ブラウザは一般に、閲覧したい言語を指定することができます。

Internet Explorer5.5で使用する言語を指定するダイアログ

図3: Internet Explorer5.5で使用する言語を指定するダイアログ

Netscape Communicatorで使用する言語を指定するダイアログ

図4: Netscape Communicatorで使用する言語を指定するダイアログ

Netscape 6で使用する言語を指定するダイアログ

図5: Netscape 6で使用する言語を指定するダイアログ

Webサイト側の設定

ここで設定した内容は、ブラウザがWebサイトに接続する際に、Webサイト側にACCEPT_LANGUAGE環境変数として渡されます。例えば、ブラウザで日本語を優先順位で1番、次に英語を指定すると、Webサイト側にはACCEPT_LANGUAGE環境変数の内容として"ja,en"が渡されます。

SSIでこの環境変数を受け取り、さらにその内容がjaから始まっている場合は日本語のエラーレスポンスを、それ以外は英語のエラーレスポンスを返すようにするには、Apacheに備わっているSSIベースの条件分岐を用います。

SSIベースの条件分岐については、やはりapache.orgのmod_includeモジュールに関するドキュメントが参考になります。

今までのことから、ACCEPT_LANGUAGE環境変数の内容による条件分岐は以下のようになります:

<!--#if expr="$HTTP_ACCEPT_LANGUAGE = /^ja,*/" -->
<p>日本語のメッセージ</p>
<!--#else -->
<p>Messages in English.</p>
<!--#endif -->

結論

結果的に、作成するカスタムエラーレスポンス用の.shtmlファイルは、以下のようになります。


<html>

<head><title>404 Not Found.</title></head>

<body><h1>404 Not Found.</h1>

<!--#if expr="$HTTP_ACCEPT_LANGUAGE = /^ja,*/" -->

<p>要求されたページ:
http://<!--#echo var="SERVER_NAME" --><!--#echo var="REDIRECT_URL" -->
は見つかりません。</p>

<!--#else -->

<p>The URL path in your request:
http://<!--#echo var="SERVER_NAME" --><!--#echo var="REDIRECT_URL" -->
doesn't match anything we have available.</p>
<!--#endif -->

</body></html>

このページの内容は、完全に無保証です。全ての環境において、この記事の内容が正しいことを保証するものでもありません。また、この記事の内容について、みなさまがどのような損害/不利益を被られても、私はそれらに対して何らの賠償などを行うものでもありません。しかし、これらの記事についての訂正、質問、苦情、その他ご意見は歓迎いたします。それらに対しては、ぼくのできる範囲で対応させていただきたいと思います。

 [GO! Sophisticated Page!]  [Valid HTML 4.01!]  [Valid CSS!]