Please Sign In or Register

HTTP レスポンスヘッダ

Drupal-jBox.net で Google にサイトを登録する方法についての投稿があり、その内容に対してコメントを行なうために、サイトの登録(サイトの確認とサイトマップの登録)を再度テストした。

サイトマップの登録は至って簡単なのだが、Drupal サイトで HTML ファイルを使ったサイトの確認を行なったことがなかったので、以下のようなエラーが返されるとは思っていなかった。

404 (ファイルが見つかりません) エラー ページのヘッダーで 200 (成功しました) のステータスが返されました。

サイトの確認を行なうという目的を果たすためであれば、META タグを記述するという方法もあるので、Google へのサイト登録は解決するのだが、そもそも、ページが見つかっていない(404)にもかかわらず、ページが確認できた(202)というステータスを返しているということが問題なのではないのだろうかと感じ、Drupal の .htaccess ファイルの記述について確認を行なった。

ErrorDocument ディレクティブ

404 の場合に 200 が返されているという問題は .htaccess で ErrorDocument 404 の時に表示するファイルのパスを正しく設定すれば解決できることが多いようだ。

Drupal では 404 のエラードキュメントの指定は、以下のように記述されている。

ErrorDocument 404 /index.php

この設定であれば、通常は 404 が正しく返されるように思うのだが、実際には 200 が返されている。
そこで、確認のために err.html を作成し、以下のように記述を変更して試してみたが、それでも index.php へ転送されてしまった。どうやらこの設定は無視されているようだ。

ErrorDocument 404 /err.html

[参考]
Apache Core Features - ErrorDocument

mod_rewrite モジュール

Drupal には、他にも、クリーン URL を実現するために、mod_rewrite を利用した以下のような転送設定が記述されている。

  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

RewriteCond で条件を指定し、条件にマッチした場合には RewriteRule で指定された処理が行なわれる。

RewriteCond

TestString CondPattern
%{REQUEST_FILENAME} ! -f
リクエストされたファイルまでのパス マッチしない 存在するファイルまでのパス
%{REQUEST_FILENAME} ! -d
リクエストされたファイルまでのパス マッチしない 存在するディレクトリまでのパス

RewriteRule

Pattern Substitution[flags]
^(.*)$ index.php?q=$1 [L,QSA]
リクエストされたファイルまたはディレクトリ名 index.php?q=xxx(リクエストされたファイルまたはディレクトリ名)へ転送 以降に記述された書き換え処理を中止(L)
書き換えルールを通してデータベースから情報を参照(QSA)

つまり、リクエストされたパスが存在しないファイルやディレクトリだった場合には、index.php?q=xxx のようなリクエストを行なうということになる。
そのため、存在しないファイルの場合でも、err.html ではなく index.php へ転送されてしまうのだろう。

実際に、クリーン URL を無効にし、.htaccess の mod_rewrite による転送設定をコメントアウトした場合には err.html が表示されたので、おそらく間違いはないだろう。
また、その場合には、ErrorDocument の場合に表示するファイルが err.html でも index.php でも、またはその他のファイルでも、HTTP レスポンスヘッダに正しく 404 が返されていることもわかった。

[参考]
Apache Core Features - mod_rewrite
Apache module mod_rewrite
Apache module mod_rewrite - 日本語翻訳

mod_mime モジュール

これまでの動作はすべて XREA+ サーバで行なっていた。
他のサーバでの HTTP レスポンスヘッダの状況を確認するために、land.to サーバで Drupal のエラーページを確認すると、ここでは、正しい 404 ステータスが返された。

XREA では PHP の Safemode が ON になっているため、そのままではいろいろな制限を受けてしまう。
これを解決するために PHP を CGI として動作させる方法を追記している。
この部分だけが、land.to サーバの .htaccess ファイルの内容と異なっていることから、他の部分をデフォルトの状態に戻し、以下の部分のみをコメントアウトして確認を行なってみると、ステータスが正しく 404 と返された。

<Files index.php>
  AddHandler application/x-httpd-phpcgi .php
</Files>

[参考]
Apache module mod_mime - AddHandler

結論

これまでの結果から考えると、Drupal やサーバの問題ではなく、mod_rewrite で転送先として指定したファイルが CGI として動作しているために起こっていると思われる。

そこで、指定されたファイルが存在しない場合の処理と、HTTP レスポンスヘッダが返されるタイミングを考えてみた。

処理についての設定内容 HTTP レスポンスヘッダが返されるタイミング
mod_rewrite による転送を行なわない index.php へ転送される時
mod_rewrite による転送を行なう index.php へ転送された後

mod_rewrite による転送を行っている場合、転送後に HTTP レスポンスヘッダが返されるのだが、転送先となっている index.php が CGI として動作しているため、転送先がサーバサイドなどの別の場所にあると判断されているためではないだろうか?
余談だが、CGI など別の場所で処理を行なうプログラムで、リクエストは受け入れられたが処理は完了していないというような場合には、202 というステータスが返される。

HTTP レスポンスヘッダが 200 と返されてしまうことで、実際にどのような問題が起こっているのかを把握すれば、他の対処方法をとることもできるので(例えば、削除したページがクロールされることが問題なら、robots.txt で制御するなど)、そこまで神経質になる必要もないと感じるのだが、やはり、正い動作をするに越したことはないので、また時間のあるときにでも、もう少し調べて見たいと思う。

[参考]
ウェブマスター向けヘルプ センター - 存在しないページに対してサーバーから 200 (見つかりました) ステータスが返されました。
HTTPステータスコード - Wikipedia

トラックバック

トラックバックは承認後に表示されます。

URLから "-nospam" を削除してトラックバックを送信してください。

コメント

CGI モードの Drupal で、正しい HTTP レスポンスヘッダを返す方法

しばらくこの問題について忘れていましたが、解決方法のひとつを発見できましたので、PHP を CGI モードで動作させた場合に 404 Not Found ではなく 200 OK を返してしまう としてブックコンテンツを作成しました。

コメントの表示オプション

お好みの表示方法を選択し、「設定の保存」をクリックすると、表示方法を変更することができます。