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

11

Я настроил свой виртуальный хост на 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/
Джек
источник
А для чего в теле ответа /bla?
zerkms
Я не уверен, что понимаю проблему тогда: -S
zerkms
Просто чтобы убедиться - на какой версии Apache вы работаете?
Дженни Д
@JennyD Я работаю на 2.4.7.
Джек,

Ответы:

8

Я тоже отвечаю на это, потому что я уверен, что проблема связана с тем, как 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возможно, пнул.

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

Джек
источник
Я бы сказал, что ошибка в fixup_dir()игнорировании FallbackResource.
Рики Бим
@RickyBeam Да, но технически fixup_dir()не должен знать об этом fixup_dflt(), поэтому imho лучше исправить это «выше» :)
Джек
7

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

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

После успешного воспроизведения вашей конфигурации здесь ( без получения 404) я также получил 5-секундную задержку. Тем не менее, я заметил, что когда UA исключает gzipсвои заголовки Accept, страница отображается / принимается мгновенно. Вы можете проверить это сами 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 секунд.

Роман
источник
Спасибо. Проблема с задержкой в ​​5 секунд является вторичной по отношению к моей основной проблеме, я обновил вопрос о том, как воспроизвести проблему локально.
Джек