web-dev-qa-db-ja.com

.htaccess ErrorDocumentディレクティブは、PHP http_response_code(404)によってトリガーされた404エラーをキャッチしません

Windows上のApache 2.4.10。安定したZend Framework 1 PHPアプリケーションがあります。 .htaccessErrorDocumentディレクティブを追加することにしました。 404で発生する3つの異なる動作に、それらがトリガーされる方法に応じて完全に困惑します。

私の.htaccessファイルには以下が含まれます:

ErrorDocument 404 "Page not found"
RedirectMatch 404 /uploads/(.*/)?private/

アドレスバーに存在しないページのURLを入力すると、Zend FrameworkのErrorControllerによって生成されたエラーページが表示されます。

/uploads/private/fooRedirectMatchと一致)を入力すると、期待どおりErrorDocument出力が得られます。

しかし、私のPHPコードで

http_response_code(404);
exit(0);

その後、ブラウザの標準エラーページが表示されます。これは私が完全に理解できないものです。 Chrome開発者ツールの[ネットワーク]タブを使用すると、3つのリクエストすべてが404ステータスになっていることがわかります。 Zend Frameworkのエラー処理セットアップは、存在しないURLをトラップし、ErrorDocument処理をバイパスしてそれを行うと想像できると思います。しかし、ステータスが404のPHPコードからの即時exitErrorDocumentをどのように通過するかはわかりません。

ErrorDocumentディレクティブをトリガーするには、どのPHPコードを記述できますか?

編集:

ティムファウンテン からの回答に基づいて、より多くのコンテキストを提供する必要があります。上記のように、ZF ErrorControllerページは希望どおりに設定されています-入力するとそのページが表示されます存在しないページのURL。この特定の状況では、実際にWordPress mu-pluginからコードを実行しています(WPはZF publicディレクトリの下にインストールされます)。 .htaccessファイルは、当然public以下の既存のファイルに対するリクエストをZFに送信しません。 public/wpの下にあるものに対するリクエストは、代わりにpublic/wp/index.php The mu-pluginブートストラップZFに移動し(ただし、ブートストラップのrun()メソッドを呼び出しません)、リクエストを調べます。許可されていない場合(ZFのAuthセッション変数による)、404(403ではなく)を指定します。以前は、実際には存在しないURLにリダイレクトすることでこれを行いましたが、ErrorControllerページは問題なく表示されましたが、アドレスバーには存在しないURLが表示されたままでした。 ErrorDocumentディレクティブを追加して、アドレスバーにユーザーが入力したURLが表示されるようにしました。私の実際のコードでは、ディレクティブに単純な文字列はありませんでしたが、このURLは/default/error/error?error_handler[type]=404です。問題を引き起こしているURLについて何かがないことを確認するために、単純な文字列に変更しました。 privateディレクトリ内でRedirectMatchをトリガーするURLを入力すると、ZF ErrorControllerページが表示されるため、URL自体には問題がないことがわかります。この投稿の複雑さを軽減したかっただけです。

ティムの答えは、私の問題のコードが空の404ページを直接ブラウザに送信しており、ブラウザがそれを説明テキストに変更していると言っています。それは明らかに起こっていることです!

header()は空のコンテンツを直接ブラウザに送信するため、長さがゼロでないページコンテンツを作成し、http_response_code()を使用してステータスを設定する必要があるということです。しかし、彼の答えで不明確なのは、ErrorDocumentディレクティブがバイパスされる理由です。

この動作を引き起こすリクエストURLはhttp://www.example.com/wp/fooです。 DocumentRoot.../publicです。これは、.htaccessによって書き換えられてZFに送られるのではなく、直接public/wp/index.phpに送られます。その場合、ErrorDocumentがトリガーされると思います...

編集2:

または、ティムのポイントは実際にはZFエラー処理に関するものではないかもしれませんが、Apacheの観点からは、(public/wp/index.phpに行きPHPを実行することで)着信リクエストが満たされたので、PHP次第ですコードを処理するために、ApacheのErrorDocumentに戻ることができません! ErrorDocumentがどのように機能するかについて、根本的な誤解があったと思います。 ErrorControllerコードを直接呼び出して、必要なページを404ステータスで表示する方法を見つける必要があります。ああ!

ティムの答えを受け入れると思いますが、ErrorDocument処理が開始されるタイミングについて、彼が自分のポイントを明確化/一般化したい場合、それはいいです:-)

編集3:

これをまとめるだけです。 Apache ErrorDocumentディレクティブがどのように機能するかについての基本的な誤解を明らかにしたので、私はティムの答えを受け入れました。しかし、Zend Frameworkのカスタムステータスページを使用して404ステータスを返すことを発見したため、発生している問題を解決する方法を直接示しませんでしたが、WordPressクエリで実行しましたブートストラップで実行されているMVCアプリケーションを開始せずにZFをブートストラップしました。 ZFフロントコントローラーをいじくり回した経験はありませんでしたが、ドキュメントを少し掘り下げた後、このソリューションを思い付きました。これは、旅行したかったErrorDocumentディレクティブとまったく同じ効果があります。

$error_url = $this->serverUrl() . '/default/error/error?error_handler[type]=404';
$request = new Zend_Controller_Request_Http($error_url);
$front = Zend_Controller_Front::getInstance();
$front->returnResponse(true);
$response = $front->dispatch($request);
$response->setRawHeader('HTTP/1.1 404 Not Found');
$response->sendResponse();
exit(0);
2
sootsnoot

おそらく、htaccessルールには、すべてのリクエストをZend Frameworkにルーティングするための書き換えルールもあります。この時点で、Apache(およびErrorDocument)は実際には見えません。リクエストをPHPで処理したいと言ったからです。

あなたがするとき:

http_response_code(404);
exit(0);

空の404ページをブラウザに送信しています。多くのブラウザは、サーバーから受信する404ページのサイズがXバイト未満の場合、独自の使いやすい404ページを表示するように設定されています。 (ユーザーエクスペリエンスを向上させるためだけです。)

Zend Frameworkはこれをキャッチし、where PHPコード(および場合によってはいくつかの構成オプションに基づく)に応じて独自のエラーページを使用する必要があります。

Zend Framework ErrorControllerページを更新して、希望どおりに表示することをお勧めします。リクエストの処理をApacheに返す方法があるとは思いません。

2
Tim Fountain