Użyj FallbackResource, nawet jeśli katalog istnieje

11

Skonfigurowałem mojego wirtualnego hosta na Apache 2.4.7 z bardzo podstawową konfiguracją:

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

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

Pod korzeniem dokumentu mam następującą strukturę:

/index.php
/help/readme.txt

Otrzymuję następujące wyniki podczas zgłaszania żądań:

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

Wygląda na to, że istnienie /help/katalogu powoduje powrót Apache, 404ponieważ nie ma go index.phptam, ale spodziewam się, że wszystkie żądania zostaną wywołane, /index.phpa zatem uzyskają 200 OKodpowiedź.

Nie pamiętam, aby był to problem podczas używania mod_rewrite, ale wolę używać, FallbackResourcejeśli to możliwe. Czy istnieje sposób, aby to naprawić?

Aktualizacja

Działa, jeśli usunę DirectoryIndexdyrektywę, ale cierpi to z powodu problemów z pięciosekundowym opóźnieniem .

Aktualizacja 3

Korzystam z następującego środowiska testowego; struktura katalogów jest następująca:

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

Zawartość httpd.confjest:

ServerName apache-bug.local
Listen 8085

DirectoryIndex disabled
DirectorySlash Off

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

FallbackResource /index.html
</VirtualHost>

Mój config.nicezawiera:

"./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" \
"$@"

Aby uruchomić serwer:

httpd -X -d /home/user/work/apache-bug/
Jacek
źródło
A po co jest ciało reagujące /bla?
zerkms
Nie jestem pewien, czy rozumiem problem: -S
zerkms
Dla pewności - na której wersji Apache używasz?
Jenny D.
@JennyD Korzystam z wersji 2.4.7.
Jack

Odpowiedzi:

8

Mam odpowiedzi na to sobie dobrze, bo jestem pewien, że problem jest związany z jak mod_dir.cdziała wewnętrznie i myślę, że to błąd .

Jeśli zasób nie może zostać zmapowany do lokalnego systemu plików, funkcja fixup_dflt()zostanie uruchomiona, używając FallbackResourcedo określenia, który dokument powinien zostać załadowany.

Jednak gdy zasób można zmapować do lokalnego systemu plików i jest to katalog, spróbuje rozwiązać dokument, uruchamiając go fixup_dir(); ta funkcja przechodzi przez listę DirectoryIndexwartości, aż znajdzie pierwszy odpowiedni dokument.

W moim przypadku konfiguracja ma pustą listę DirectoryIndexwartości, więc fixup_dir()zakończy się niepowodzeniem i zostanie zwrócone 404.

Następująca łatka działa dla mnie ( 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;
}

Zasadniczo próbuje fixup_dflt()po fixup_dir()nieudanym.

Aktualizacja 21.04.2015

Poprawka została złożona do projektu, zaplanowano na 2,5; może być również przeniesiony do wersji 2.4.

Aktualizacja 2015-05-18

Poprawka została cofnięta, ponieważ:

[...] to [przynajmniej] powoduje FallBackResourcekopnięcie, zanim mod_autoindexmogło zostać wprowadzone.

Wciąż próbuję wymyślić, jak uniknąć tego rodzaju sytuacji.

Jacek
źródło
Powiedziałbym, że błąd polega na fixup_dir()ignorowaniu FallbackResource.
Ricky Beam
@RickyBeam Tak, ale technicznie fixup_dir()nie powinienem wiedzieć fixup_dflt(), więc imho lepiej to naprawić „wyżej” :)
Jack
7

Twoja konfiguracja powinna być poprawna.

Co dziwne, problemem wydaje się być mod_deflate .

Po pomyślnym odtworzeniu tutaj konfiguracji ( nie otrzymanie 404), otrzymałem również 5-sekundowe opóźnienie. Zauważyłem jednak, że gdy UA pomija gzipnagłówki Accept-Headers, strona jest wyświetlana / odbierana natychmiast. Możesz to sprawdzić samemu wget.

Co ciekawe, dalsze debugowanie stracepokazuje, że apache wysyła zawartość twojego FallbackResourcedo gniazda twojego klienta bez zauważalnej różnicy w opóźnieniu w obu przypadkach. Jest to również widoczne w sieci, w której pakiet odpowiedzi jest wysyłany z serwera do klienta po żądaniu HTTP bez zauważalnego opóźnienia 1 .

Wydaje się, że w tym przypadku podczas używania mod_deflate, UA nie wie, kiedy dane wysłane przez serwer się kończą, a zatem nie renderuje niczego przed upływem limitu czasu połączenia TCP 2 i jest siłą zamykane przez serwer. Jest to zgodne z HTTP / 1.0, gdzie zamknięte połączenie oznacza koniec treści.

W przypadku protokołu HTTP / 1.1 serwer ma inne dostępne środki do sygnalizowania końca zawartości - ale wydaje się, że żaden z nich tutaj się nie zdarza .

Jednak błąd, który czai się w mod_dir lub mod_deflate, jest obecnie poza moim dostępnym czasem. Sprawiłem, że działał bezbłędnie, wyłączając kompresję gzip; Aby obejść ten problem, dopóki problem nie zostanie rozwiązany na dobre, możesz selektywnie wyłączyć gzip.

1 ) Mówi nam to, że problem nie wynika z niewyłączonych buforów na serwerze.
2 ) Domyślnie limit czasu wynosi 5 sekund w przypadku apache - stąd te 5 sekund.

rzymski
źródło
Dzięki. Problem opóźnienia 5s jest drugorzędny w stosunku do mojego głównego problemu, zaktualizowałem swoje pytanie o to, jak odtworzyć problem lokalnie.
Jack