Назад | Перейти на главную страницу

Почему apache возвращает ответ 404 для существующего файла?

У меня есть сервер apache, основная цель которого - обрабатывать запросы RPC. Все такие запросы попадают на URL-адрес, который начинается с фиксированного префикса (например, /rpc) Я использую Location директива для установки обработчика для этого URL (например, <Location /rpc>...</Location>).

Теперь я бы хотел, чтобы этот сервер также обслуживал статические файлы. Я поставил index.html файл в его DocumentRoot но не могу заставить apache обслуживать его мне. Вместо этого я получаю 404 ответа. Журнал доступа показывает это:

127.0.0.1 - - [18/Aug/2010:11:41:52 -0400] "GET /index.html HTTP/1.1" 404 208

Журнал ошибок показывает следующее:

[...] [error] [client 127.0.0.1] File does not exist: /www/htdocs/index.html

Это сообщение об ошибке - грязная ложь. Я могу скопировать и вставить этот путь и запустить ls /www/htdocs/index.html и убедитесь, что файл действительно существует.

То, что я пробовал до сих пор:

У меня заканчиваются идеи. Что еще мне попробовать?

(Я использую apache 2.2.12 в Mac OS X 10.5.8 и apache 2.2.3 в CentOS 5.4.)

Оказалось, что ответ зависит от части информации, которой нет в моем вопросе, но dtruss вывод должен был быть большой подсказкой!

у меня есть PerlMapToStorageHandler Apache2::Const::OK директива в моей конфигурации apache согласно предложение в документации mod_perl. Это параметр для всего хоста, и он предотвращает вызов apache ap_directory_walk() и stat()загружает кучу файлов каждый раз, когда получает запрос. Это желательно, когда все ваши URI являются «виртуальными» (т.е. не соответствуют реальным файлам на диске), но это также означает, что вы не можете обслуживать статические файлы!

Мое решение состояло в том, чтобы создать собственный PerlMapToStorageHandler рутина, которая избегает stat() вызывает каждый файл, кроме того, который я хочу обслуживать:

package MyMapToStorageHandler;

use strict;  
use Apache2::RequestRec();
use Apache2::Const -compile => qw(DECLINED OK M_TRACE);

sub handler {
    my $r = shift;

    # Fall through to the default handling for TRACE requests and requests
    # for the index.html file.
    if ($r->method_number == Apache2::Const::M_TRACE || $r->uri eq '/index.html') {
        return Apache2::Const::DECLINED;
    }

    # Skip ap_directory_walk stat() calls by just returning OK
    return Apache2::Const::OK;
}

1;

Затем в моем httpd.conf файл я заменил существующий PerlMapToStorageHandler Apache2::Const::OK директива с этим:

PerlLoadModule MyMapToStorageHandler
...
PerlMapToStorageHandler MyMapToStorageHandler

Это сработало.