Jak sprawdzić, który location wybrał nginx?
Wklej konfigurację i URI żądania do tego testera, żeby zobaczyć zwycięski blok i powód odpadnięcia każdego z pozostałych. Na działającym serwerze dodaj error_log /var/log/nginx/debug.log debug; i poszukaj wiersza using configuration, który nazywa wybrany location. Oba podejścia odpowiadają na inne pytania: log mówi, co zrobił działający serwer, a ta strona mówi, co zrobiłaby konfiguracja, której jeszcze nie wdrożyłeś.
Dlaczego moje wyrażenie regularne w location nie działa?
Zwykle z jednego z trzech powodów, a tabela decyzji wskazuje którego. Wcześniejszy regex już się dopasował, więc Twój nigdy nie ruszył — regexy sprawdzane są w kolejności z pliku i wygrywa pierwsze dopasowanie. Albo najdłuższy pasujący prefiks niesie ^~, co pomija fazę regexów w całości. Albo regex jest poprawny, tylko URI wygląda inaczej, niż Ci się wydaje: dopasowanie działa na znormalizowanej ścieżce, po dekodowaniu procentowym i rozwinięciu .., z odciętym query stringiem.
Dlaczego moje dopasowanie dokładne się nie uruchamia?
Location z = wymaga, żeby całe URI było równe wzorcowi, a nie żeby się od niego zaczynało. location = /a/ nie pasuje do /a, a location = /a nie pasuje do /a/b. Końcowe ukośniki są tu zwykłymi znakami, więc obie formy to różne ciągi. Gdy dokładny location faktycznie pasuje, wyszukiwanie kończy się natychmiast i nic więcej nie jest nawet porównywane.
Czy nginx dopasowuje query string w bloku location?
Nie. Query string jest odcinany podczas normalizacji, a wybór location działa na samej ścieżce. Dlatego location = /a pasuje do żądania /a?x=/b. Jeśli musisz rozgałęzić logikę po parametrze, odczytaj $arg_name lub $args wewnątrz bloku. Warto znać jeden niuans: %3F dekoduje się do dosłownego znaku zapytania, który zostaje w ścieżce, więc /a%3Fx=1 ma pusty query string i ścieżkę zawierającą ?.
Czy w location w nginx można używać składni regexów z JavaScriptu?
Nie — nginx używa PCRE, a różnice mają znaczenie. Ta strona działa w Twojej przeglądarce, gdzie istnieją wyłącznie wyrażenia regularne ECMAScript, więc konstrukcje dostępne tylko w PCRE są wykrywane i oznaczane, zamiast po cichu obliczane błędnie: grupy atomowe, kwantyfikatory zaborcze, modyfikatory wbudowane w rodzaju (?i), klasy POSIX w rodzaju [[:alpha:]] oraz sekwencje takie jak \A i \K, które JavaScript bez słowa czyta jako zwykłe litery. Gdy location zostanie oznaczony, pozostali kandydaci nadal są obliczani w kolejności nginx, ale werdykt tego bloku trzeba sprawdzić na prawdziwym serwerze. Jeśli dopiero piszesz sam wzorzec, tester wyrażeń regularnych omawia składnię ECMAScript dokładniej. Czy prefiksy w location w nginx rozróżniają wielkość liter?
Na Linuksie tak — location /Static/ nie pasuje do /static/x. Na systemach plików nierozróżniających wielkości liter, takich jak macOS czy Cygwin, nginx porównuje prefiksy bez rozróżniania wielkości i dodatkowo zmusza każdy location z regexem do zachowania jak ~*. Ta strona odwzorowuje zachowanie linuksowe, bo to ono działa na praktycznie wszystkich serwerach produkcyjnych. Jeśli programujesz na Macu, a wdrażasz na Linuksa, ta różnica potrafi ukryć zepsutą regułę aż do wdrożenia.
Czy try_files zmienia to, który blok location został wybrany?
Nie. Wybór location kończy się najpierw; try_files działa dopiero potem, wewnątrz bloku, który już wygrał. Jeśli żądanie nigdy nie dociera do bloku z Twoim try_files, dyrektywa jest bez znaczenia — zwykle winny jest regex ~ \.php$, który przejmuje żądanie, zanim blok prefiksowy z fallbackiem zdąży cokolwiek zrobić. Przekierowanie wewnętrzne wystawione później faktycznie restartuje dopasowanie, więc przepisane URI jest rozstrzygane na liście location od nowa, od góry.
Dlaczego nginx zwraca 301, gdy proszę o katalog bez ukośnika?
Odpowiadają za to dwa różne mechanizmy. Jeśli location, którego nazwa kończy się na /, niesie proxy_pass lub inną dyrektywę *_pass, żądanie o tę samą ścieżkę bez ukośnika dostaje 301 już na etapie wyboru location — zanim obliczone zostanie jakiekolwiek wyrażenie regularne. Osobno moduł plików statycznych zwraca 301, gdy ścieżka wskazuje na prawdziwy katalog na dysku. Pierwszy przypadek widać tutaj; drugi zależy od Twojego systemu plików. Dodanie location = /path wyłącza ten pierwszy.
Czy zagnieżdżone bloki location zmieniają wynik?
Tak, i to w sposób łatwy do przeoczenia. nginx schodzi w głąb zwycięskiego prefiksu i przeszukuje jego dzieci, więc zagnieżdżony regex sprawdzany jest przed regexami z poziomu nadrzędnego. ^~ na bloku zewnętrznym nie chroni go przed jego własnymi zagnieżdżonymi regexami, a zagnieżdżenie potrafi uczynić globalnie dłuższy prefiks nieosiągalnym, gdy pierwszy wygra sąsiad z poziomu zewnętrznego. Zagnieżdżone bloki są tu odwzorowane z tym samym wcięciem, jakie im nadałeś.
Czy moja konfiguracja nginx jest gdzieś wysyłana?
Nie. Parsowanie i dopasowywanie odbywa się lokalnie w Twojej przeglądarce, na zwykłych operacjach na ciągach znaków — nie ma żadnego wywołania serwera i nic nie jest przechowywane. Tutaj ma to większe znaczenie niż przy większości narzędzi, bo prawdziwy blok server zawiera nazwy hostów upstream, wewnętrzne porty, ścieżki do certyfikatów i reguły uwierzytelniania. Nie musisz wierzyć nam na słowo: otwórz narzędzia deweloperskie przeglądarki i popatrz, jak panel Network milczy, kiedy piszesz, albo odłącz się od sieci i testuj dalej. Brak jakiegokolwiek żądania zewnętrznego jest też pilnowany automatycznym testem kontraktowym przy każdym buildzie, więc nie zniknie po cichu.