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

Используйте FallbackResource, даже если каталог существует

Я установил свой виртуальный хост на Apache 2.4.7 с очень простой конфигурацией:

<VirtualHost *:80>
  ServerName foo.example.com
  DocumentRoot /var/www/html

  DirectoryIndex index.php
  FallbackResource /index.php
</VirtualHost>

Под корнем документа у меня есть следующая структура:

/index.php
/help/readme.txt

Когда я делаю запросы, я получаю следующие результаты:

/bla     -> 200 OK
/help/   -> 404 Not Found
/help/a  -> 200 OK

Кажется, что существование /help/ каталог заставляет Apache вернуться 404 потому что нет index.php там, но я ожидаю, что все запросы будут вызывать /index.php и таким образом получить 200 OK ответ.

Я не помню, чтобы это было проблемой при использовании mod_rewrite, но я предпочитаю использовать FallbackResource если возможно. Есть способ исправить это?

Обновить

Работает, если я удалю DirectoryIndex директива, но она страдает от проблемы с пятисекундной задержкой.

Обновление 3

Я использую следующую тестовую среду; структура каталогов следующая:

./htdocs
   index.html
   test/
      bla.txt
./conf
   httpd.conf
./logs

Содержание httpd.conf является:

ServerName apache-bug.local
Listen 8085

DirectoryIndex disabled
DirectorySlash Off

<VirtualHost *:8085>
DocumentRoot /home/user/apache-bug/htdocs

FallbackResource /index.html
</VirtualHost>

Мой config.nice содержит:

"./configure" \
"--enable-debugger-mode" \
"--with-apr=/usr/local/apr/bin/apr-1-config" \
"--enable-dir=static" \
"--with-mpm=prefork" \
"--enable-unixd=static" \
"--enable-authn-core=static" \
"--enable-authz-core=static" \
"$@"

Для запуска сервера:

httpd -X -d /home/user/work/apache-bug/

Я тоже на это отвечаю, потому что уверен, что проблема связана с тем, как mod_dir.c работает внутри и я думаю это Жук.

Если ресурс не может быть сопоставлен с локальной файловой системой, функция fixup_dflt() будет работать, используя FallbackResource чтобы определить, какой документ следует загрузить вместо этого.

Однако когда ресурс жестяная банка быть сопоставленным с локальной файловой системой и каталогом, он попытается разрешить документ, запустив fixup_dir(); эта функция выполняет итерацию по списку DirectoryIndex значений, пока не будет найден первый подходящий документ.

В моем случае в конфигурации есть пустой список DirectoryIndex ценности, поэтому fixup_dir() завершится ошибкой, и будет возвращено 404.

У меня работает следующий патч (PR):

static int dir_fixups(request_rec *r)
{
    if (r->finfo.filetype == APR_DIR) {
-        return fixup_dir(r);
+        if (fixup_dir(r) != OK) {
+           /* use fallback */
+           return fixup_dflt(r);
+        }
+
+        return OK;
    }
    else if ((r->finfo.filetype == APR_NOFILE) && (r->handler == NULL)) {
        /* No handler and nothing in the filesystem - use fallback */
        return fixup_dflt(r);
    }
    return DECLINED;
}

Это в основном пытается fixup_dflt() после fixup_dir() не смогли.

Обновление 2015-04-21

А исправить внесен в проект, запланированный на 2.5; он также может быть перенесен на 2.4.

Обновление 2015-05-18

Исправление было вернулся так как:

[...] это [по крайней мере] вызывает FallBackResource забить раньше mod_autoindex мог бы сработать.

Я все еще пытаюсь понять, как избежать такой ситуации.

Ваша конфигурация должна быть правильной.

Проблема, как ни странно, кажется mod_deflate.

После успешного воспроизведения вашей конфигурации здесь (не получение 404), я также получил 5-секундную задержку. Однако я заметил, что когда UA пропускает gzip из заголовков Accept-Headers страница отображается / принимается мгновенно. Вы можете проверить это сами с помощью wget.

Интересно, что дальнейшая отладка с strace показывает, что apache отправляет содержимое вашего FallbackResource в розетку вашего клиента без заметной разницы в задержке для обе случаи. Это также очевидно на проводе, где пакет ответа отправляется с сервера клиенту после HTTP-запроса без какой-либо заметной задержки.1.

Похоже, что при использовании mod_deflate в этом случае, однако, UA не знает, когда данные, отправленные сервером, заканчиваются, и, таким образом, ничего не отображает до истечения времени ожидания TCP-соединения.2 и принудительно закрывается сервером. Это соответствует HTTP / 1.0, где закрытое соединение означает конец содержимого.

Для HTTP / 1.1, на сервере есть другие средства, доступные для сигнализации о конце содержимого - но ничего из этого, похоже, здесь не происходит.

Однако, если ошибка скрывается в mod_dir или mod_deflate, сейчас мое время выходит за рамки моего свободного времени. Я заставил его работать безупречно, отключив сжатие gzip; в качестве временного решения, пока проблема не будет окончательно решена, вы можете выборочно отключить gzip.

1) Это говорит нам о том, что проблема не в не очищенных буферах на сервере.
2) По умолчанию тайм-аут составляет 5 секунд с apache - отсюда ваши 5 секунд.