Nginx - statyczne pomyłki w obsłudze plików z rootem i aliasem

473

Muszę udostępniać aplikację za pośrednictwem serwera aplikacji pod adresem 8080, a moje pliki statyczne z katalogu bez dotykania serwera aplikacji. Konfiguracja nginx, którą mam, jest mniej więcej taka ...

    # app server on port 8080
    # nginx listens on port 8123
    server {
            listen          8123;
            access_log      off;

            location /static/ {
                    # root /var/www/app/static/;
                    alias /var/www/app/static/;
                    autoindex off;
            }


            location / {
                    proxy_pass              http://127.0.0.1:8080;
                    proxy_set_header        Host             $host;
                    proxy_set_header        X-Real-IP        $remote_addr;
                    proxy_set_header        X-Forwarded-For  $proxy_add_x_forwarded_for;
            }
    }

Teraz przy tej konfiguracji wszystko działa dobrze. Należy zauważyć, że rootdyrektywa została skomentowana.

Jeśli aktywuję rooti dezaktywuję alias- przestanie działać. Jednak po usunięciu spływu /static/z rootniego zacznie ponownie działać.

Czy ktoś może wyjaśnić, co się dzieje. Również proszę wyjaśnić jasno plików i zgłasza jakie są różnice między rooti aliasoraz ich celów.

treecoder
źródło

Odpowiedzi:

1074

Znalazłem odpowiedzi na moje zamieszanie.

Jest to bardzo ważna różnica między roota aliasdyrektywami. Różnica istnieje w sposobie przetwarzania ścieżki określonej w rootlub alias.

W przypadku rootdyrektywy do katalogu głównego dołączana jest pełna ścieżka, w tym część lokalizacji , natomiast w przypadku aliasdyrektywy do aliasu dołączana jest tylko część ścieżki NIE zawierająca części lokalizacji .

Ilustrować:

Powiedzmy, że mamy konfigurację

location /static/ {
    root /var/www/app/static/;
    autoindex off;
}

W tym przypadku będzie to ostatnia ścieżka, którą wyprowadzi Nginx

/var/www/app/static/static

To wróci, 404ponieważ nie ma go static/w sobiestatic/

Jest tak, ponieważ część lokalizacji jest dołączana do ścieżki określonej w pliku root. Stąd, rootpoprawnym sposobem jest

location /static/ {
    root /var/www/app/;
    autoindex off;
}

Z drugiej strony, aliasczęść lokalizacji zostaje odrzucona . Tak dla konfiguracji

location /static/ {
    alias /var/www/app/static/;
    autoindex off;           ↑
}                            |
                             pay attention to this trailing slash

ostatnia ścieżka zostanie poprawnie utworzona jako

/var/www/app/static

Przypadek ukośnika końcowego dla aliasdyrektywy

Nie ma ostatecznych wytycznych dotyczących tego, czy końcowy ukośnik jest obowiązkowy w dokumentacji Nginx , ale wydaje się, że powszechna obserwacja ludzi tutaj i gdzie indziej wskazuje, że tak jest.

Kilka innych miejsc dyskutowało na ten temat, choć nie bez końca.

/server/376162/how-can-i-create-a-location-in-nginx-that-works-with-and-without-a-trailing-slas

/server/375602/why-is-my-nginx-alias-not-working

treecoder
źródło
97
Końcowy ukośnik na ścieżce aliasu jest niezbędny!
mafroza
2
To wszystko świetnie (pomogło mi naprawić problemy z konfiguracją), ale zastanawiam się, jakich ustawień rejestrowania ludzie mogliby użyć, aby zdiagnozować tego rodzaju problemy? Na przykład wszystko, co wypisuje do logów takie jak „otrzymano żądanie [...], dopasowane do bloku konfiguracji„ lokalizacja [...] ”, przeszukanie katalogu [...]”
Pistos
2
@Pistos: wstawiane log_format scripts '$document_root | $uri | > $request';do httpsekcji i access_log /var/log/nginx/scripts.log scripts;do serversekcji konfiguracji nginx ..
helvete
Dzięki! Rzeczywiście, ukośnik końcowy jest niezbędny dla aliasu, w przeciwnym razie mam nginx: [emerg] invalid number of arguments in "alias" directive, a serwer przestał działać podczas restartu.
FotisK
@mafrosis Dlaczego jest to konieczne?
Bruce Sun
104

jak powiedzieć @treecoder

W przypadku root dyrektywy do katalogu głównego dołączana jest pełna ścieżka, w tym część lokalizacji, natomiast w przypadku aliasdyrektywy do aliasu dołączana jest tylko część ścieżki NIE zawierająca części lokalizacji.

Obraz jest wart tysiąca słów

dla root:

wprowadź opis zdjęcia tutaj

dla alias:

wprowadź opis zdjęcia tutaj

liuzhijun
źródło
11
Czy pierwsza strzałka na drugim obrazku powinna być „+”?
aioobe
35

W twoim przypadku możesz użyć rootdyrektywy, ponieważ $uriczęść locationdyrektywy jest taka sama jak ostatnia rootczęść dyrektywy.

Dokumentacja Nginx również to zaleca:
gdy lokalizacja odpowiada ostatniej części wartości dyrektywy:

location /images/ {
    alias /data/w3/images/;
}

lepiej jest zamiast tego użyć dyrektywy root:

location /images/ {
    root /data/w3;
}

a rootdyrektywa dołączy $urido ścieżki.

antonbormotov
źródło
2
Dlaczego to jest lepsze? Dokumenty też nie mówią.
HostedMetrics.com
Zaletą, którą widzę, jest unikanie powielania $ uri, / obrazów w podanym przykładzie, przy użyciu aliasu
antonbormotov
21

Szybki dodatek do bardzo pomocnej odpowiedzi @ good_computer. Chciałem zastąpić katalog główny adresu URL folderem, ale tylko wtedy, gdy pasował on do podfolderu zawierającego pliki statyczne (które chciałem zachować jako część ścieżki).

Na przykład jeśli żądany plik znajduje się w /app/jslub /app/css, sprawdź /app/location/public/[that folder].

Mam to do pracy przy użyciu wyrażenia regularnego.

 location ~ ^/app/((images/|stylesheets/|javascripts/).*)$ {
     alias /home/user/sites/app/public/$1;
     access_log off;
     expires max;
 }
meloncholia
źródło
2
Dziękuję za tę odpowiedź. Wiem, że to 3 lata później, ale czy ktoś mógłby wyjaśnić, czy istnieje kompromis między wydajnością i / lub bezpieczeństwem między używaniem aliasu a rootem?
Mina
1
@Mina Lepiej użyć roota, jeśli możesz. (W dokumentacji docs wiki.nginx.org/HttpCoreModule#alias )
Matthew Wilcoxson,
Właśnie po to tu przyjechałem 👍👏
alienfromouterspace
6

alias służy do zastąpienia ścieżki części lokalizacji (LPP) w ścieżce żądania, podczas gdy root poprzedza się ją ścieżką żądania.

Są dwa sposoby mapowania ścieżki żądania do końcowej ścieżki pliku.

aliasmoże być użyte tylko w bloku lokalizacji i zastąpi to na zewnątrz root.

aliasi rootnie można ich używać razem w bloku lokalizacji.

Yao Zhao
źródło
3
server {
    server_name xyz.com;
    root /home/ubuntu/project_folder/;

    client_max_body_size 10M;
    access_log  /var/log/nginx/project.access.log;
    error_log  /var/log/nginx/project.error.log;

    location /static {
        index index.html;
    }

    location /media {
        alias /home/ubuntu/project/media/;
    }
}

Blok serwera, aby uruchomić statyczną stronę na nginx.

Tapish
źródło
2

Innymi słowy: w skrócie: w przypadku rootpodanego argumentu lokalizacji należy do ścieżki systemu plików i identyfikatora URI . Z drugiej strony - dla aliasdyrektywy argument instrukcji lokalizacji jest tylko częścią URI

Więc, alias to inna nazwa, która odwzorowuje pewną URI do określonej ścieżki w systemie plików, natomiast rootDokleja lokalizacji argumentu do toru głównego podanego jako argument do rootdyrektywy.

Twissell
źródło