Skip to content

Nginx Location Tester — dlaczego wygrywa ten blok

Który blok location w nginx wygrywa — i dlaczego przegrały pozostałe. Darmowy tester dla =, ^~, ~ i ~*, w całości w przeglądarce.

Bez śledzenia Działa w przeglądarce Bezpłatne
Twoja konfiguracja jest parsowana lokalnie w przeglądarce i nigdzie nie jest wysyłana. Konfiguracje serwera niosą nazwy hostów upstream i bloki uwierzytelniania, więc otwórz panel Network i popatrz, jak milczy — albo przejdź całkiem w tryb offline.
Wypróbuj prawdziwy błąd konfiguracji
Wybrany location
~* \.(gif|jpg|jpeg)$

Pierwszy pasujący regex w kolejności z konfiguracji. Długość nie ma znaczenia.

Co nginx faktycznie dopasowuje
Cel żądania
/documents/1.jpg
Znormalizowany $uri
/documents/1.jpg
Query string $args

Dopasowanie działa wyłącznie na znormalizowanej ścieżce. Query string jest odcinany na początku i nigdy w nim nie uczestniczy.

Dlaczego wygrał ten blok
Dlaczego wygrał ten blok
Wiersz location Etap Wynik Powód
2 = / Dokładne Brak dopasowania Location z = wymaga równości całego URI, a nie tego, żeby się od niego zaczynało.
3 / Prefiks Pasuje, ale krótszy Pasuje, ale inny prefiks dopasował więcej znaków.
4 /documents/ Prefiks Pasuje, ale krótszy Pasuje, ale inny prefiks dopasował więcej znaków.
5 ^~ /images/ Prefiks Brak dopasowania URI nie zaczyna się od tego prefiksu.
6 ~* \.(gif|jpg|jpeg)$ Regex Wybrany Pierwszy pasujący regex w kolejności z konfiguracji. Długość nie ma znaczenia.

Modyfikatory location w nginx: porównanie =, ^~, ~, ~*

Modyfikatory location w nginx: porównanie =, ^~, ~, ~*
Modyfikator Składnia Dopasowuje przez Kolejność Zatrzymuje regexy Typowe zastosowanie
= location = /path Równość 1 Tak Gorące ścieżki w rodzaju / — najszybsze możliwe dopasowanie.
^~ location ^~ /path Zaczyna się od 2 Tak Katalogi, których nigdy nie wolno oddać regexowi, na przykład uploady.
~ location ~ regex Regex PCRE 3 Nie Trasowanie po rozszerzeniu, gdy wielkość liter ma znaczenie.
~* location ~* regex Regex PCRE 3 Nie Trasowanie po rozszerzeniu, gdy wielkość liter nie ma znaczenia.
(brak) location /path Zaczyna się od 4 Nie Ogólne trasowanie po ścieżce.
@ location @name Tylko wewnętrznie Nie Fallbacki dla error_page i try_files.

Kolumna kolejności to nie jest prosty ranking. Location prefiksowy zatrzymuje obliczanie regexów tylko wtedy, gdy niesie ^~ i sam jest najdłuższym dopasowaniem — i właśnie dlatego blok ^~ czasem sprawia wrażenie, jakby nic nie robił.

Priorytet location w nginx: kolejność rozstrzygania

Priorytet location w nginx: kolejność rozstrzygania
# Etap Kończy wyszukiwanie Co się dzieje
1 Normalizacja Nie Dekodowanie procentowe, rozwinięcie . oraz .., zwinięcie powtórzonych ukośników. Query string jest tu odcinany i nigdy nie bierze udziału w dopasowaniu.
2 Dokładne Tak location = /path, porównywany na równość. Trafienie kończy wyszukiwanie natychmiast.
3 Auto-przekierowanie Tak Location proxy, którego nazwa to URI plus ukośnik. nginx odpowiada 301 i nigdy nie dociera do regexów.
4 Prefiks Nie Porównywany jest każdy pasujący prefiks, a zapamiętywany najdłuższy. Kolejność w konfiguracji jest ignorowana.
5 Zagnieżdżone Nie nginx schodzi w głąb zwycięskiego prefiksu. Zagnieżdżony regex sprawdzany jest przed poziomem nadrzędnym.
6 Regex Tak Regexy sprawdzane są w kolejności z konfiguracji i wygrywa pierwsze dopasowanie. Dłuższy lub bardziej szczegółowy regex zapisany później nie uruchomi się nigdy.
7 Fallback Tak Żaden regex nie pasuje, więc użyty zostaje prefiks zapamiętany wcześniej.
Kolejność dopasowania, zwarcie na ^~, schodzenie w zagnieżdżone location, zachowanie automatycznego przekierowania i normalizacja URI zostały skonfrontowane ze źródłami nginx i potwierdzone uruchomieniem tych konfiguracji na nginx 1.27.5. — Zespół inżynierów Go Tools · Jul 22, 2026

Reguły wyboru opisane na tej stronie sprawdziliśmy na działającym nginx 1.27.5, a nie przepisali z opracowań wtórnych; silnik pokrywają testy jednostkowe wyprowadzone z tych uruchomień.

Dopasowanie location w nginx: szybkie odpowiedzi

Czy nginx sprawdza wyrażenia regularne przed prefiksami?

Nie — prefiksy idą pierwsze, ale pasujący regex i tak wygrywa. nginx najpierw sprawdza wszystkie prefiksy i zapamiętuje najdłuższe dopasowanie, a dopiero potem oblicza location z wyrażeniami regularnymi w kolejności ich występowania w pliku. Wygrywa pierwsze pasujące. Jeśli nie pasuje żadne, użyty zostaje zapamiętany prefiks. Jedyny wyjątek to ^~: gdy najdłuższy pasujący prefiks go niesie, faza regexów jest pomijana w całości.

Czy kolejność bloków location ma w nginx znaczenie?

Tylko dla wyrażeń regularnych. Prefiksy — łącznie z = i ^~ — wybierane są po najdłuższym dopasowaniu, więc ich kolejność w pliku nie ma znaczenia. Wyrażenia regularne sprawdzane są od góry do dołu i wygrywa pierwsze dopasowanie, więc przesunięcie bloku z regexem zmienia to, który zadziała. Bardziej szczegółowy regex umieszczony pod ogólniejszym nie wykona się nigdy.

Co właściwie robi modyfikator ^~?

Zatrzymuje nginx po dopasowaniu prefiksu, zamiast podnosić priorytet. Jeśli najdłuższy pasujący prefiks niesie ^~, nginx pomija fazę regexów i używa tego bloku. Nie wydłuża to dopasowania prefiksu ani nie stawia go ponad innymi prefiksami — tłumi wyłącznie obliczanie wyrażeń regularnych. Dlatego blok ^~ sprawia wrażenie, jakby nic nie robił, gdy pasuje też dłuższy zwykły prefiks: zapamiętany zostaje ten dłuższy, a on niczego nie tłumi.

Czy location /static to to samo co location /static/?

Nie — /static pasuje także do /staticfoo. Dopasowanie prefiksowe to zwykłe porównanie ciągów znaków, a nie granica segmentu ścieżki, więc location /static obsługuje też /staticfiles i /static-backup. Osobna sprawa: gdy /static/ jest użyte z proxy_pass, żądanie do /static bez końcowego ukośnika dostaje przekierowanie 301 na /static/, zanim rozważone zostanie jakiekolwiek wyrażenie regularne.

Czy nginx dekoduje %2F i zwija podwójne ukośniki przed dopasowaniem?

Tak — dopasowanie działa na znormalizowanym URI, nie na surowym żądaniu. nginx dekoduje %XX, rozwija . i .. oraz zwija powtórzone ukośniki, zanim wybierze location. Zdekodowane %2F staje się prawdziwym separatorem i bierze udział w tym rozwijaniu, więc /a/b%2F..%2Fzz jest dopasowywane jako /a/zz. Query string jest odcinany na samym początku i nie bierze w dopasowaniu żadnego udziału.

Czym jest blok location w nginx?

Blok location mówi nginxowi, co zrobić z żądaniem, którego URI pasuje do wzorca. Blok server zwykle zawiera ich kilka, a ciekawe jest nie to, co robi każdy z nich, tylko który z nich nginx wybierze — bo reguły wyboru nie są tymi, których większość ludzi się spodziewa.

Form jest pięć. location = /path pasuje tylko wtedy, gdy całe URI jest równe. location /path pasuje do każdego URI zaczynającego się tymi znakami. location ^~ /path to to samo porównanie prefiksu z jednym dodatkowym efektem. location ~ regex i location ~* regex stosują wzorzec PCRE, z rozróżnianiem i bez rozróżniania wielkości liter. location @name w ogóle nie bierze udziału w dopasowaniu URI i istnieje wyłącznie jako cel dla try_files i error_page.

Wybór przebiega etapami. Najpierw URI jest normalizowane: dekodowanie procentowe, rozwinięcie . i .., zwinięcie powtórzonych ukośników, odcięcie query stringu. Potem location z = równy URI kończy wyszukiwanie natychmiast. Potem porównywane są wszystkie pasujące prefiksy i zapamiętywany jest najdłuższy — kolejność w konfiguracji nie odgrywa tu żadnej roli. Jeśli zapamiętany prefiks niesie ^~, nginx zatrzymuje się i go używa. W przeciwnym razie sprawdzane są location z wyrażeniami regularnymi w kolejności, w jakiej występują w pliku, i wygrywa pierwsze dopasowanie, choćby późniejsze było znacznie bardziej szczegółowe. Jeśli nie pasuje żadne, użyty zostaje zapamiętany prefiks.

Dwie z tych reguł ciągną w przeciwne strony i właśnie tam mieszka zamieszanie: prefiksy wybiera się po długości niezależnie od kolejności, regexy po kolejności niezależnie od długości. Konfiguracja, która czyta się poprawnie od góry do dołu, wciąż może skierować żądanie tam, gdzie tego nie chciałeś, i żadna liczba ponownych lektur tego nie ujawni. Ta strona odtwarza całą sekwencję na Twojej własnej konfiguracji i pokazuje, gdzie odpadł każdy blok.

# From the nginx documentation. Which block serves each request?
server {
    location = /                   { }   # A
    location /                     { }   # B
    location /documents/           { }   # C
    location ^~ /images/           { }   # D
    location ~* \.(gif|jpg|jpeg)$  { }   # E
}

#   /                        -> A   exact match, search ends here
#   /index.html              -> B   no regex matched, longest prefix used
#   /documents/document.html -> C   longer prefix than B
#   /images/1.gif            -> D   ^~ won the prefix stage, regex skipped
#   /documents/1.jpg         -> E   regex beats the longer prefix C

# The last two lines are the whole lesson: identical-looking prefixes
# behave differently because only one of them carries ^~.

Najważniejsze funkcje

Każdy przegrany blok wraz z etapem, na którym odpadł

Każdy zapisany przez Ciebie location dostaje wiersz: pasował, ale był krótszy; pominięty, bo wygrał prefiks ^~; nieosiągalny, bo wcześniejszy regex już się dopasował; albo po prostu brak dopasowania. To zwykle wiedza o tym, dlaczego przegrali pozostali, realnie rozstrzyga sprawę.

Odtworzony czteroetapowy łańcuch decyzji

Normalizacja, dopasowanie dokładne, zapamiętanie najdłuższego prefiksu, zwarcie na ^~, regexy w kolejności z pliku i fallback pokazane są jako osobne kroki na Twojej własnej konfiguracji, a nie opisane w oderwaniu od niej.

Widoczne zwarcie na ^~

Gdy prefiks ^~ tłumi fazę regexów, każdy pominięty regex jest oznaczony jako pominięty, zamiast po cichu zniknąć — a gdy ^~ nie zadziała, bo wygrał dłuższy zwykły prefiks, to również widać.

Zagnieżdżone location rozstrzygane, a nie spłaszczane

nginx schodzi w głąb zwycięskiego prefiksu i przeszukuje jego dzieci, więc zagnieżdżony regex działa przed regexami poziomu nadrzędnego. Zagnieżdżone bloki zachowują w tabeli swoje wcięcie, żeby struktura pozostała czytelna.

Składnia dostępna tylko w PCRE wykrywana z góry

Przeglądarki uruchamiają regexy ECMAScript, nie PCRE. Grupy atomowe, kwantyfikatory zaborcze, klasy POSIX oraz sekwencje takie jak \A i \K są oznaczane, zamiast po cichu obliczane błędnie, więc pewna siebie zła odpowiedź nigdy nie jest podawana jako fakt.

Nic nie jest wysyłane — działa w Twojej przeglądarce

Konfiguracje serwera niosą nazwy hostów upstream, wewnętrzne porty i reguły uwierzytelniania. Parsowanie to zwykła praca na ciągach znaków, bez zależności i bez wywołań sieciowych, potwierdzona automatycznym testem kontraktowym przy każdym buildzie.

Inne sposoby na odpowiedź na to pytanie

nginx -T

Wiersz poleceń

Zrzuca w pełni rozwiniętą konfigurację, co jest bezcenne przy ustalaniu, co faktycznie zostało wczytane. Nie powie natomiast, który location wybierze dane URI — i tę lukę wypełnia ta strona.

error_log ... debug

Działający serwer

Najbardziej wiarygodna dostępna odpowiedź: wiersz z komunikatem using configuration nazywa blok, który nginx naprawdę wybrał. Wymaga roota, przeładowania i serwera, do którego masz dostęp — odpowiada więc po wdrożeniu, a nie przed.

Walidatory składni konfiguracji

Usługa hostowana

Mocne w lintowaniu całych plików i regułach bezpieczeństwa. Zwykle działają po stronie serwera, co oznacza wysłanie konfiguracji zawierającej wewnętrzne nazwy hostów i ścieżki do certyfikatów.

Lektura dokumentacji

Dokumentacja

Dokumentacja nginx podaje algorytm precyzyjnie i warto ją raz przeczytać. Ręczne zastosowanie go do ośmiu bloków i jednego URI to moment, w którym wkradają się błędy, bo dwie z reguł ciągną w przeciwne strony.

Przykłady dopasowania location w nginx

Wyrażenie regularne wygrywa z dłuższym prefiksem

location /documents/  ·  location ~* \.(gif|jpg|jpeg)$  ·  GET /documents/1.jpg
~* \.(gif|jpg|jpeg)$ wins

Prefiks /documents/ pasuje i jest najdłuższym prefiksem w pliku, więc nginx go zapamiętuje — a potem i tak oblicza wyrażenia regularne i oddaje żądanie pierwszemu, które pasuje. Długość przegrywa z fazą regexów. Gdyby ten prefiks zapisano jako ^~ /documents/, wyrażenie regularne nie zostałoby w ogóle uruchomione. To przykład z dokumentacji nginx i akurat ten warto mieć w głowie.

Katalog uploadu, który wykonuje PHP

location /uploads/  ·  location ~ \.php$ { fastcgi_pass ... }  ·  GET /uploads/evil.php
~ \.php$ wins — the upload lands in the interpreter

Prefiks /uploads/ pasuje, ale zwykły prefiks nie zatrzymuje fazy regexów, więc plik wgrany przez kogoś z zewnątrz trafia prosto do PHP-FPM. Zapis location ^~ /uploads/ ucina fazę regexów i zamyka tę drogę. To nie jest scenariusz hipotetyczny: tak wygląda długa seria zgłoszeń typu upload-to-RCE, a różnica między podatnym a bezpiecznym to dwa znaki.

^~, które po cichu nic nie robi

location ^~ /a/  ·  location /a/b/  ·  location ~ \.php$  ·  GET /a/b/x.php
~ \.php$ wins — the ^~ never applied

^~ tłumi fazę regexów tylko wtedy, gdy samo jest najdłuższym pasującym prefiksem. Tutaj /a/b/ jest dłuższe, więc to jego nginx zapamiętuje, a jego zwykły modyfikator pozwala fazie regexów ruszyć. Blok ^~ nadal jest w pliku, nadal wygląda ochronnie i nie ma na to żądanie żadnego wpływu. Czytanie konfiguracji od góry do dołu tego nie pokaże; porównanie długości prefiksów — owszem.

/static łapie także /staticfoo

location /static  ·  location /static/  ·  GET /staticfoo
/static wins

Dopasowanie prefiksowe porównuje znaki, a nie segmenty ścieżki. /staticfoo zaczyna się od /static, więc pasuje, natomiast /static/ nie pasuje wcale, bo URI nie ma ukośnika w tym miejscu. Wszystko, co leży pod ścieżką zaczynającą się tymi samymi literami, obsługuje ten blok — i tak reguła dla /static kończy się serwowaniem /static-backup.

Wygrywa pierwsze wyrażenie regularne, nie najlepsze

location ~ ^/a  ·  location ~ ^/a/b/c$  ·  GET /a/b/c
~ ^/a wins; ~ ^/a/b/c$ is unreachable

Wyrażenia regularne sprawdzane są w kolejności występowania w pliku, a pierwsze dopasowanie kończy wyszukiwanie. Drugi blok jest bardziej szczegółowy i pasuje do tego URI dokładnie, a mimo to nigdy się nie uruchomi — dla żadnego żądania. Prefiksy wybiera się po długości, niezależnie od kolejności; regexy po kolejności, niezależnie od szczegółowości. Pomylenie tych dwóch reguł to zwykły powód, dla którego reguła przestaje działać po tym, jak ktoś uporządkował plik.

Zakodowane wyjście w górę rozwija się przed dopasowaniem

location /a/  ·  location /b/  ·  GET /a/b%2F..%2Fzz
$uri becomes /a/zz, so /a/ wins

nginx dekoduje kodowanie procentowe, rozwija . oraz .. i zwija powtórzone ukośniki, zanim w ogóle sięgnie po jakikolwiek location. %2F dekoduje się do prawdziwego separatora i bierze udział w tym rozwijaniu, więc ten cel żądania nie zostaje w /a/b/ — ląduje na /a/zz. Dopasowywanie do celu, który wpisałeś, zamiast do znormalizowanego $uri daje tu zły wynik.

Jak korzystać z testera location w nginx

  1. 1

    Wklej blok server

    Wrzuć cały blok server albo same bloki location, o których myślisz. Zagnieżdżone location są rozumiane, a oryginalne numery wierszy zostają zachowane, więc tabela odpowiada Twojemu plikowi.

  2. 2

    Wpisz URI żądania

    Wpisz ścieżkę w takiej postaci, w jakiej przychodzi z sieci, razem z kodowaniem procentowym i query stringiem. Trzy wiersze nad tabelą pokazują, jak jest normalizowana przed dopasowaniem.

  3. 3

    Przeczytaj zwycięzcę, potem przegranych

    Karta werdyktu nazywa wybrany blok i podaje jednozdaniowy powód. Tabela decyzji pod spodem tłumaczy każdy pozostały blok: na jakim etapie odpadł i dlaczego.

  4. 4

    Sprawdź diagnostykę

    Raportowane są niezakotwiczone wyrażenia regularne, prefiksy bez końcowego ukośnika, ^~ z wzorcem regex, nieosiągalne duplikaty oraz katalogi uploadu osiągalne przez regex na PHP.

  5. 5

    Podziel się dokładnym stanem

    Kopiowanie linku zapisuje konfigurację i URI we fragmencie adresu, więc kolega otworzy dokładnie to, na co patrzysz. Fragmenty nigdy nie są przesyłane na serwer.

Częste błędy w location w nginx

Oczekiwanie, że ^~ przebije dłuższy prefiks

^~ jest brane pod uwagę tylko na tym prefiksie, który już wygrał na długości. Dłuższy zwykły prefiks wygrywa pierwszy, a faza regexów rusza wtedy tak, jakby ^~ w ogóle nie było.

✗ Niepoprawne
location ^~ /a/ { }
location /a/b/ { }
location ~ \.php$ { }
# /a/b/x.php -> ~ \.php$
✓ Poprawne
location ^~ /a/ { }
location ^~ /a/b/ { }
location ~ \.php$ { }
# /a/b/x.php -> ^~ /a/b/

Prefiks bez końcowego ukośnika łapiący sąsiednie ścieżki

Dopasowanie prefiksowe porównuje znaki, a nie segmenty ścieżki, więc blok obsługuje też każdą sąsiednią ścieżkę zaczynającą się tymi samymi literami.

✗ Niepoprawne
location /static { root /var/www; }
# obsługuje też /staticfoo i /static-backup
✓ Poprawne
location /static/ { root /var/www; }
location = /static { return 301 /static/; }

Umieszczenie szczegółowego regexu pod ogólnym

Regexy sprawdzane są w kolejności z pliku, a pierwsze dopasowanie kończy wyszukiwanie, więc bardziej precyzyjny blok nie wykona się dla żadnego żądania.

✗ Niepoprawne
location ~ ^/api { }
location ~ ^/api/v2/users$ { }
# drugi jest nieosiągalny
✓ Poprawne
location ~ ^/api/v2/users$ { }
location ~ ^/api { }

Zapisanie wyrażenia regularnego po ^~

^~ przyjmuje dosłowny prefiks. nginx wczytuje plik bez protestu, a blok po prostu nigdy do niczego nie pasuje, co utrudnia wychwycenie tego w przeglądzie.

✗ Niepoprawne
location ^~ "\.php$" { deny all; }
✓ Poprawne
location ~ \.php$ { deny all; }

Założenie, że query string bierze udział w dopasowaniu

Query string jest odcinany podczas normalizacji, więc location nigdy nie może się po nim dopasować. Zamiast tego odczytaj $arg_name wewnątrz bloku.

✗ Niepoprawne
location /search?q= { }
# nigdy do niczego nie pasuje
✓ Poprawne
location /search {
    if ($arg_q = "") { return 400; }
}

Co można zrobić testerem location w nginx

Sprawdź konfigurację, zanim trafi na produkcję
Prześledź trasowanie w bloku server, który zmieniłeś, ale jeszcze nie wdrożyłeś. Wyłapiesz tu awarię pojawiającą się tylko przy określonym kształcie URI — a więc dokładnie taką, jakiej test dymny po przeładowaniu zwykle nie zauważa.
Ustal, dlaczego reguła przestała działać
Regex, który kiedyś działał, a teraz nie, prawie zawsze pada ofiarą kolejności: coś dopasowało się wcześniej albo nad nim pojawiło się ^~. Tabela oznacza blok jako nieosiągalny i nazywa ten, który przejął żądanie.
Zaudytuj katalog uploadu albo mediów
Wczytaj preset odtwarzający układ z wykonywaniem uploadu, a potem wklej własne ścieżki. Jeśli regex na PHP przejmuje żądania wewnątrz katalogu przyjmującego zapisy, diagnostyka to powie i nazwie oba bloki.
Zamknij komentarz w przeglądzie kodu dowodem
Kopiowanie linku zapisuje dokładną konfigurację i URI we fragmencie adresu. Wrzucenie tego do pull requesta zamienia spór o pierwszeństwo w tabelę decyzji, którą każdy może przeliczyć od nowa.
Naucz kogoś algorytmu wyboru
Dwie tabele referencyjne to statyczny, indeksowalny materiał, na który można wskazać, a gotowe presety pokazują każdą pułapkę bez psucia serwera. Zwłaszcza przykład z ^~ potrafi szybko zakończyć dyskusję.

Jak działa wybór location w nginx

Normalizacja dzieje się przed sięgnięciem po jakikolwiek location
URI jest dekodowane procentowo, segmenty . i .. są rozwijane, a powtórzone ukośniki zwijane — i dopiero wtedy wybierany jest location. Zdekodowane %2F staje się prawdziwym separatorem i bierze udział w tym rozwijaniu, więc /a/b%2F..%2Fzz jest dopasowywane jako /a/zz. Trzy zdekodowane znaki są wyjątkiem i zostają dosłowne: %25, %23 i %3F — dlatego /a%3Fx=1 ma znak zapytania w ścieżce i pusty query string. + nie jest tu spacją; spacją jest wyłącznie %20. Wyjście powyżej katalogu głównego oraz niepoprawna sekwencja ucieczki są odrzucane kodem 400, zanim dopasowanie w ogóle się zacznie.
Decyduje długość prefiksu, nie kolejność w konfiguracji
Porównywany jest każdy pasujący prefiks i wygrywa najdłuższy, niezależnie od tego, czy stoi w pliku pierwszy, czy ostatni. Porównanie idzie po znakach, a nie po segmentach ścieżki, więc /static pasuje do /staticfoo. Zwycięzca jest zapamiętywany, a nie od razu używany, bo faza regexów wciąż może go przebić.
^~ tłumi regexy; nie podnosi priorytetu
Modyfikator sprawdzany jest wyłącznie na tym prefiksie, który już wygrał na długości. Jeśli pasuje też dłuższy zwykły prefiks, to on zostaje zapamiętany, a faza regexów rusza jak zwykle — blok ^~ nie ma wtedy na żądanie żadnego wpływu. Umieszczenie ^~ na zagnieżdżonym location nie chroni przed regexem zadeklarowanym na poziomie zewnętrznym i nigdy nie tłumi regexów zagnieżdżonych wewnątrz własnego bloku.
Regexy idą w kolejności z pliku, a pierwsze dopasowanie kończy wyszukiwanie
nginx trzyma location z regexami w kolejności, w jakiej je zapisano, i ich nie sortuje. Szczegółowość, długość i zakotwiczenie nie mają wpływu na to, który zostanie sprawdzony pierwszy, więc precyzyjny wzorzec umieszczony pod ogólnym to martwa konfiguracja. W dopasowany location z regexem nginx i tak schodzi, więc jego zagnieżdżone location są przeszukiwane później.
PCRE i ECMAScript to nie ten sam język
nginx kompiluje regexy w location przy użyciu PCRE, bez trybu UTF i bez trybu wieloliniowego, więc wzorce działają na bajtach, a ^ kotwiczy wyłącznie do początku URI. Jedna różnica ma ciężar bezpieczeństwa: w PCRE $ pasuje także tuż przed końcowym znakiem nowej linii, więc URI kończące się na %0A nadal spełnia \.php$, choć silnik JavaScriptu by tego odmówił. To zachowanie jest tu odwzorowane i raportowane, bo to znany sposób na obejście reguł opartych na rozszerzeniu pliku.

Dobre praktyki dla location w nginx

Chroń katalogi z prawem zapisu przez ^~, nie zwykłym prefiksem
Każdy katalog przyjmujący upload potrzebuje location ^~ /uploads/, żeby faza regexów nie mogła oddać zapisanego pliku interpreterowi. Zwykły prefiks wygląda równoważnie i nie jest.
Dawaj prefiksom katalogów końcowy ukośnik
Pisz location /static/ zamiast location /static, chyba że świadomie chcesz, żeby ten sam blok obsługiwał /staticfoo i /static-backup. Dodaj osobny location = /static, gdy samą ścieżkę też trzeba obsłużyć.
Układaj regexy od najbardziej szczegółowego do najogólniejszego
Wygrywa pierwsze dopasowanie, więc ogólny wzorzec nad precyzyjnym czyni ten precyzyjny nieosiągalnym. Trzymanie regexów w małej liczbie i w świadomej kolejności jest łatwiejsze w utrzymaniu niż rozważanie nakładania się wzorców po fakcie.
Zakotwicz regexy, które mają pasować do prefiksu ścieżki
location ~ /admin szuka w dowolnym miejscu URI i pasuje do /public/admin/x. Napisz ~ ^/admin, jeśli chodzi Ci o początek. Zakotwiczenie wyłącznie na końcu jest normalne i poprawne przy trasowaniu po rozszerzeniu pliku.
Po każdej zmianie kolejności sprawdź trasowanie ponownie
Przesuwanie bloków jest bezpieczne dla prefiksów i zmienia zachowanie regexów. Ponieważ diff, który tylko zmienia kolejność wierszy, wygląda w przeglądzie niegroźnie, ponowne przepuszczenie dotkniętych URI to najtańszy sposób, żeby to wyłapać.

Tester location w nginx — najczęstsze pytania

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.

Powiązane narzędzia

Zobacz wszystkie narzędzia →

Generator i konstruktor poleceń cURL

Web & API

Twórz polecenia curl w przeglądarce — ustaw metodę, nagłówki, autoryzację i treść, a gotowe polecenie pojawi się natychmiast. Presety dla Bearer, POST JSON i przesyłania plików. Bezpłatnie, prywatnie, bez rejestracji.

Generator htpasswd — bcrypt, Apache MD5 (apr1) i Basic Auth

Web & API

Generuj wpisy htpasswd z bcrypt, Apache MD5 (apr1), SHA-1 i innymi algorytmami. Gotowe bloki konfiguracji dla Apache, nginx i Docker. 100% w Twojej przeglądarce — bez przesyłania danych.

Generator Open Graph i meta tagów

Web & API

Generuj tagi Open Graph, Twitter Card i SEO meta tagi z podglądem na żywo dla Google, Facebooka i X. 100% za darmo, w przeglądarce, bez rejestracji — skopiuj i wklej kod.

Dekoder traceparent — W3C Trace Context

Web & API

Koniec z liczeniem cyfr hex. Darmowy dekoder traceparent online — działa w przeglądarce, nic nie wysyła. Trace ID, span ID, 8 bitów trace-flags, tracestate, Datadog/X-Ray/B3.

Narzędzie do odszyfrowywania AES — OpenSSL i CryptoJS

Narzędzia bezpieczeństwa

Odszyfruj AES online — GCM/CBC/CTR, hasło lub klucz surowy, automatyczne wykrywanie formatu OpenSSL i CryptoJS „U2FsdGVkX1”. 100% w przeglądarce, klucze nigdy jej nie opuszczają.

Narzędzie do szyfrowania AES — GCM, CBC i CTR

Narzędzia bezpieczeństwa

Darmowe szyfrowanie AES online — AES-128/192/256, GCM/CBC/CTR, hasło (PBKDF2) lub klucz surowy. Działa w 100% w przeglądarce; nic nie jest przesyłane.