Skip to content

Nginx Location Tester — warum dieser Block greift

Welcher nginx location-Block greift — und warum jeder andere verloren hat. Kostenloser Tester für =, ^~, ~ und ~*, komplett im Browser.

Kein Tracking Läuft im Browser Kostenlos
Ihre Konfiguration wird lokal in Ihrem Browser geparst und nie hochgeladen. Server-Configs enthalten Upstream-Hostnamen und Auth-Blöcke — öffnen Sie das Netzwerk-Panel und sehen Sie zu, wie es stumm bleibt, oder gehen Sie ganz offline.
Eine echte Fehlkonfiguration ausprobieren
Ausgewählte location
~* \.(gif|jpg|jpeg)$

Erster passender regulärer Ausdruck in Konfigurationsreihenfolge. Die Länge ist irrelevant.

Wogegen nginx tatsächlich matcht
Anfrageziel
/documents/1.jpg
Normalisierte $uri
/documents/1.jpg
Query-String $args

Das Matching läuft nur gegen den normalisierten Pfad. Der Query-String wird vorher abgetrennt und spielt nie mit.

Warum dieser Block gewonnen hat
Warum dieser Block gewonnen hat
Zeile location Stufe Ergebnis Grund
2 = / Exakt Kein Treffer Eine =-location verlangt Gleichheit der ganzen URI, nicht nur denselben Anfang.
3 / Präfix Passt, aber kürzer Es passt, aber ein anderes Präfix hat mehr Zeichen getroffen.
4 /documents/ Präfix Passt, aber kürzer Es passt, aber ein anderes Präfix hat mehr Zeichen getroffen.
5 ^~ /images/ Präfix Kein Treffer Die URI beginnt nicht mit diesem Präfix.
6 ~* \.(gif|jpg|jpeg)$ Regex Ausgewählt Erster passender regulärer Ausdruck in Konfigurationsreihenfolge. Die Länge ist irrelevant.

nginx location-Modifikatoren: =, ^~, ~, ~* im Vergleich

nginx location-Modifikatoren: =, ^~, ~, ~* im Vergleich
Modifikator Syntax Matcht über Reihenfolge Stoppt Regex Typischer Einsatz
= location = /path Gleichheit 1 Ja Heiße Pfade wie / — der schnellstmögliche Treffer.
^~ location ^~ /path Beginnt mit 2 Ja Verzeichnisse, die nie an einen regulären Ausdruck gehen dürfen, etwa Uploads.
~ location ~ regex PCRE-Regex 3 Nein Endungs-Routing, bei dem Groß-/Kleinschreibung zählt.
~* location ~* regex PCRE-Regex 3 Nein Endungs-Routing, bei dem Groß-/Kleinschreibung egal ist.
(keiner) location /path Beginnt mit 4 Nein Allgemeines Routing nach Pfad.
@ location @name Nur intern Nein Fallbacks für error_page und try_files.

Die Spalte Reihenfolge ist keine einfache Rangliste. Eine Präfix-location stoppt die Regex-Auswertung nur, wenn sie ^~ trägt und selbst der längste Treffer ist — genau deshalb wirkt ein ^~-Block manchmal völlig folgenlos.

nginx location-Priorität: die Auflösungsreihenfolge

nginx location-Priorität: die Auflösungsreihenfolge
# Stufe Beendet die Suche Was passiert
1 Normalisieren Nein Prozent-Dekodierung, Auflösung von . und .., Zusammenfassen wiederholter Schrägstriche. Der Query-String wird hier abgetrennt und nimmt am Matching nie teil.
2 Exakt Ja location = /path, auf Gleichheit geprüft. Ein Treffer beendet die Suche sofort.
3 Auto-Redirect Ja Eine Proxying-location, deren Name die URI plus Schrägstrich ist. nginx antwortet 301 und erreicht die regulären Ausdrücke nie.
4 Präfix Nein Jedes passende Präfix wird verglichen und das längste gemerkt. Die Reihenfolge in der Konfiguration wird ignoriert.
5 Verschachtelt Nein In das gewinnende Präfix wird hineingestiegen. Ein verschachtelter regulärer Ausdruck wird vor der Elternebene geprüft.
6 Regex Ja Reguläre Ausdrücke werden in Konfigurationsreihenfolge geprüft und der erste Treffer gewinnt. Ein längerer oder spezifischerer, weiter unten geschriebener Ausdruck läuft nie.
7 Fallback Ja Kein regulärer Ausdruck passte, also wird das zuvor gemerkte Präfix verwendet.
Matching-Reihenfolge, der ^~-Kurzschluss, der Abstieg in verschachtelte locations, das Auto-Redirect-Verhalten und die URI-Normalisierung wurden gegen den nginx-Quellcode geprüft und durch Ausführen der Konfigurationen auf nginx 1.27.5 bestätigt. — Go Tools Engineering · Jul 22, 2026

Die Auswahlregeln auf dieser Seite wurden gegen ein laufendes nginx 1.27.5 geprüft statt aus Sekundärquellen übernommen, und die Engine ist durch Unit-Tests abgedeckt, die aus diesen Läufen stammen.

nginx location-Matching: kurze Antworten

Verarbeitet nginx Regex-locations vor den Präfix-Treffern?

Nein — Präfixe werden zuerst geprüft, ein passender regulärer Ausdruck gewinnt trotzdem. nginx prüft zuerst alle Präfix-locations und merkt sich den längsten Treffer, danach wertet es die Regex-locations in der Reihenfolge aus, in der sie in der Datei stehen. Der erste passende reguläre Ausdruck gewinnt. Passt keiner, wird die gemerkte Präfix-location verwendet. Die einzige Ausnahme ist ^~: Trägt das längste passende Präfix diesen Modifikator, entfällt die Regex-Phase vollständig.

Spielt die Reihenfolge der location-Blöcke in nginx eine Rolle?

Nur bei Regex-locations. Präfix-locations — einschließlich = und ^~ — werden über den längsten Treffer ausgewählt, ihre Reihenfolge in der Datei ist also belanglos. Regex-locations werden von oben nach unten geprüft und der erste Treffer gewinnt; einen Regex-Block zu verschieben ändert daher, welcher greift. Ein spezifischerer regulärer Ausdruck unterhalb eines breiteren wird nie ausgeführt.

Was macht der Modifikator ^~ wirklich?

Er stoppt nginx nach dem Präfix-Treffer, statt die Priorität zu erhöhen. Trägt die längste passende Präfix-location ^~, überspringt nginx die Regex-Phase und verwendet diesen Block. Der Modifikator macht den Präfix-Treffer nicht länger und stellt ihn nicht über andere Präfixe — er unterdrückt nur die Regex-Auswertung. Deshalb wirkt ein ^~-Block folgenlos, sobald ein längeres einfaches Präfix ebenfalls passt: Gemerkt wird dann das längere, und das unterdrückt nichts.

Ist location /static dasselbe wie location /static/?

Nein — /static passt auch auf /staticfoo. Der Präfixvergleich ist ein reiner Zeichenkettenvergleich und kennt keine Segmentgrenzen, location /static bedient also auch /staticfiles und /static-backup. Davon unabhängig: Wird /static/ mit proxy_pass verwendet, beantwortet nginx eine Anfrage auf /static ohne abschließenden Schrägstrich mit einem 301 auf /static/, bevor überhaupt ein regulärer Ausdruck betrachtet wird.

Dekodiert nginx %2F und fasst doppelte Schrägstriche vor dem Matching zusammen?

Ja — gematcht wird gegen die normalisierte URI, nicht gegen die rohe Anfrage. nginx dekodiert %XX, löst . und .. auf und komprimiert wiederholte Schrägstriche, bevor eine location ausgewählt wird. Ein dekodiertes %2F wird zu einem echten Trennzeichen und nimmt an dieser Auflösung teil, /a/b%2F..%2Fzz wird also als /a/zz gematcht. Der Query-String wird vorher abgetrennt und spielt beim Matching überhaupt keine Rolle.

Was ist ein nginx location-Block?

Ein location-Block sagt nginx, was mit einer Anfrage geschehen soll, deren URI auf ein Muster passt. In einem server-Block stehen meist mehrere davon, und interessant ist nicht, was jeder einzelne tut, sondern welchen nginx auswählt — denn die Auswahlregeln sind nicht die, die die meisten vermuten.

Es gibt fünf Formen. location = /path passt nur, wenn die gesamte URI gleich ist. location /path passt auf jede URI, die mit diesen Zeichen beginnt. location ^~ /path ist derselbe Präfixvergleich mit einem zusätzlichen Effekt. location ~ regex und location ~* regex wenden ein PCRE-Muster an, mit bzw. ohne Beachtung der Groß-/Kleinschreibung. location @name nimmt am URI-Matching überhaupt nicht teil und existiert nur als Ziel für try_files und error_page.

Die Auswahl läuft in Stufen ab. Zuerst wird die URI normalisiert: Prozentzeichen dekodiert, . und .. aufgelöst, wiederholte Schrägstriche zusammengefasst, Query-String abgetrennt. Dann beendet eine =-location, die der URI gleicht, die Suche sofort. Danach wird jedes passende Präfix verglichen und das längste gemerkt — die Reihenfolge in der Konfiguration spielt hier überhaupt keine Rolle. Trägt dieses gemerkte Präfix ein ^~, hört nginx auf und verwendet es. Andernfalls werden die Regex-locations in der Reihenfolge geprüft, in der sie in der Datei stehen, und der erste Treffer gewinnt, so spezifisch ein späterer auch sein mag. Passt keiner, wird das gemerkte Präfix verwendet.

Zwei dieser Regeln ziehen in entgegengesetzte Richtungen, und genau dort sitzt die Verwirrung: Präfixe werden nach Länge gewählt, unabhängig von der Reihenfolge, reguläre Ausdrücke nach Reihenfolge, unabhängig von der Länge. Eine Konfiguration, die sich von oben nach unten korrekt liest, kann eine Anfrage trotzdem irgendwohin leiten, wo Sie sie nicht haben wollten, und noch so häufiges Nachlesen zeigt das nicht. Diese Seite spielt die gesamte Sequenz gegen Ihre eigene Konfiguration durch und zeigt, wo jeder Block ausgeschieden ist.

# 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 ^~.

Wichtige Funktionen

Jeder unterlegene Block, mit der Stufe seines Ausscheidens

Jede location, die Sie geschrieben haben, bekommt eine Zeile: passt, aber kürzer; übersprungen, weil ein ^~-Präfix gewonnen hat; unerreichbar, weil ein früherer regulärer Ausdruck gepasst hat; oder schlicht kein Treffer. Zu wissen, warum die anderen verloren haben, klärt die Frage meist erst wirklich.

Die vierstufige Entscheidungskette, nachgespielt

Normalisierung, exakter Treffer, gemerktes längstes Präfix, der ^~-Kurzschluss, Regex in Dateireihenfolge und der Fallback erscheinen als einzelne Schritte gegen Ihre eigene Konfiguration statt als abstrakte Beschreibung.

Der ^~-Kurzschluss wird sichtbar

Unterdrückt ein ^~-Präfix die Regex-Phase, wird jeder übersprungene reguläre Ausdruck als übersprungen ausgewiesen, statt still zu verschwinden — und wenn das ^~ nicht greift, weil ein längeres einfaches Präfix gewonnen hat, steht auch das da.

Verschachtelte locations aufgelöst, nicht plattgemacht

nginx steigt in das gewinnende Präfix hinab und durchsucht dessen Kinder, ein verschachtelter regulärer Ausdruck läuft also vor denen der Elternebene. Verschachtelte Blöcke behalten ihre Einrückung in der Tabelle, damit die Struktur lesbar bleibt.

PCRE-eigene Syntax wird vorab erkannt

Browser führen ECMAScript-Ausdrücke aus, kein PCRE. Atomare Gruppen, possessive Quantoren, POSIX-Klassen und Escapes wie \A und \K werden markiert statt stillschweigend falsch ausgewertet, damit nie eine selbstbewusst falsche Antwort als Tatsache erscheint.

Nichts wird hochgeladen — es läuft in Ihrem Browser

Server-Configs enthalten Upstream-Hostnamen, interne Ports und Auth-Regeln. Das Parsen ist reine Zeichenketten-Arbeit ohne Abhängigkeiten und ohne Netzwerkaufrufe, bei jedem Build durch einen automatisierten Vertragstest bestätigt.

Andere Wege, diese Frage zu beantworten

nginx -T

Kommandozeile

Gibt die vollständig aufgelöste Konfiguration aus, was unbezahlbar ist, um zu sehen, was tatsächlich geladen ist. Welche location eine bestimmte URI auswählt, sagt es nicht — genau diese Lücke füllt diese Seite.

error_log ... debug

Laufender Server

Die belastbarste verfügbare Antwort: Die Zeile "using configuration" nennt den Block, den nginx wirklich gewählt hat. Sie braucht root, einen Reload und einen erreichbaren Server — sie antwortet also nach dem Deployment, nicht davor.

Konfigurations-Syntaxprüfer

Gehosteter Dienst

Stark beim Linten ganzer Dateien und bei Sicherheitsregeln. Sie laufen in der Regel serverseitig, was bedeutet, eine Konfiguration mit internen Hostnamen und Zertifikatspfaden hochzuladen.

Die Dokumentation lesen

Referenz

Die nginx-Dokumentation beschreibt den Algorithmus präzise und ist einmal lesenswert. Ihn von Hand auf acht Blöcke und eine URI anzuwenden ist die Stelle, an der die Fehler entstehen, weil zwei der Regeln in entgegengesetzte Richtungen zeigen.

Beispiele für nginx location-Matching

Ein regulärer Ausdruck schlägt das längere Präfix

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

Das Präfix /documents/ passt und ist das längste Präfix in der Datei, nginx merkt es sich also — und wertet danach trotzdem die regulären Ausdrücke aus und übergibt die Anfrage dem ersten, der passt. Die Länge verliert gegen die Regex-Phase. Wäre das Präfix als ^~ /documents/ geschrieben, wäre der reguläre Ausdruck nie ausgeführt worden. Das ist das Beispiel aus der nginx-Dokumentation, und es ist dasjenige, das man wirklich verinnerlichen sollte.

Das Upload-Verzeichnis, das PHP ausführt

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

Das Präfix /uploads/ passt, aber ein einfaches Präfix stoppt die Regex-Phase nicht — eine hochgeladene Datei wird also direkt an PHP-FPM übergeben. location ^~ /uploads/ schneidet die Regex-Phase ab und schließt die Lücke. Das ist kein Gedankenspiel: Es ist die Form hinter einer langen Reihe von Upload-zu-RCE-Meldungen, und zwischen verwundbar und sicher liegen zwei Zeichen.

Ein ^~, das still und leise nichts tut

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

^~ unterdrückt die Regex-Phase nur dann, wenn es selbst das längste passende Präfix ist. Hier ist /a/b/ länger, also merkt nginx sich dieses, und sein einfacher Modifikator lässt die Regex-Phase laufen. Der ^~-Block steht weiterhin in der Datei, sieht weiterhin nach Schutz aus und hat auf diese Anfrage keine Wirkung. Beim Lesen von oben nach unten fällt das nicht auf; beim Vergleich der Präfixlängen schon.

/static fängt auch /staticfoo ein

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

Der Präfixvergleich arbeitet auf Zeichen, nicht auf Pfadsegmenten. /staticfoo beginnt mit /static, passt also, und /static/ passt überhaupt nicht, weil die URI an dieser Stelle keinen Schrägstrich hat. Alles, was unter einem Pfad erreichbar ist, der nur mit denselben Buchstaben beginnt, wird von diesem Block bedient — so bedient eine /static-Regel am Ende auch /static-backup.

Der erste reguläre Ausdruck gewinnt, nicht der beste

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

Reguläre Ausdrücke werden in der Reihenfolge ausgewertet, in der sie in der Datei stehen, und der erste Treffer beendet die Suche. Der zweite Block ist spezifischer und passt genau auf diese URI — und wird nie ausgeführt, für keine einzige Anfrage. Präfix-locations werden nach Länge gewählt, unabhängig von der Reihenfolge; Regex-locations nach Reihenfolge, unabhängig von der Spezifität. Diese beiden Regeln zu verwechseln ist der übliche Grund, warum eine Regel „nicht mehr funktioniert“, nachdem jemand die Datei aufgeräumt hat.

Kodiertes Traversal wird vor dem Matching aufgelöst

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

nginx dekodiert Prozentzeichen, löst . und .. auf und fasst wiederholte Schrägstriche zusammen, bevor überhaupt eine location betrachtet wird. %2F wird zu einem echten Trennzeichen und nimmt dann an dieser Auflösung teil, dieses Ziel bleibt also nicht innerhalb von /a/b/ — es landet auf /a/zz. Wer gegen das getippte Ziel statt gegen die normalisierte $uri prüft, bekommt hier die falsche Antwort.

So verwenden Sie den nginx location Tester

  1. 1

    Den server-Block einfügen

    Fügen Sie einen ganzen server-Block ein oder nur die location-Blöcke, über die Sie nachdenken. Verschachtelte locations werden verstanden, und die ursprünglichen Zeilennummern bleiben erhalten, damit die Tabelle zu Ihrer Datei passt.

  2. 2

    Die Anfrage-URI eingeben

    Tippen Sie den Pfad so, wie er auf der Leitung ankommt, samt Prozent-Kodierung und Query-String. Die drei Zeilen über der Tabelle zeigen, wie er vor dem Matching normalisiert wird.

  3. 3

    Erst den Gewinner lesen, dann die Verlierer

    Die Urteilskarte nennt den ausgewählten Block und den Grund in einer Zeile. Die Entscheidungstabelle darunter erklärt jeden anderen Block: an welcher Stufe er ausgeschieden ist und warum.

  4. 4

    Die Diagnosen prüfen

    Nicht verankerte reguläre Ausdrücke, Präfixe ohne abschließenden Schrägstrich, ein ^~ mit Regex-Muster, unerreichbare Duplikate und Upload-Verzeichnisse, die über einen PHP-Regex erreichbar sind, werden alle gemeldet.

  5. 5

    Den exakten Zustand teilen

    „Link kopieren“ kodiert Konfiguration und URI im URL-Fragment, damit eine Kollegin genau das öffnet, was Sie gerade ansehen. Fragmente werden nie an einen Server übertragen.

Häufige Fehler bei nginx location

Erwarten, dass ^~ ein längeres Präfix überstimmt

^~ wird nur an dem Präfix betrachtet, das über die Länge bereits gewonnen hat. Ein längeres einfaches Präfix gewinnt zuerst, und die Regex-Phase läuft dann, als wäre das ^~ nicht da.

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

Ein Präfix ohne abschließenden Schrägstrich fängt Geschwister ein

Der Präfixvergleich arbeitet auf Zeichen statt auf Pfadsegmenten, der Block bedient also auch jeden Geschwisterpfad, der mit denselben Buchstaben beginnt.

✗ Falsch
location /static { root /var/www; }
# also serves /staticfoo and /static-backup
✓ Richtig
location /static/ { root /var/www; }
location = /static { return 301 /static/; }

Den spezifischen regulären Ausdruck unter den breiten setzen

Reguläre Ausdrücke werden in Dateireihenfolge geprüft, und der erste Treffer beendet die Suche — der präzisere Block wird also für keine einzige Anfrage ausgeführt.

✗ Falsch
location ~ ^/api { }
location ~ ^/api/v2/users$ { }
# the second is unreachable
✓ Richtig
location ~ ^/api/v2/users$ { }
location ~ ^/api { }

Einen regulären Ausdruck hinter ^~ schreiben

^~ nimmt ein literales Präfix. nginx lädt die Datei klaglos, und der Block matcht schlicht nie etwas, was im Review schwer zu entdecken ist.

✗ Falsch
location ^~ "\.php$" { deny all; }
✓ Richtig
location ~ \.php$ { deny all; }

Annehmen, der Query-String nehme am Matching teil

Der Query-String wird bei der Normalisierung abgetrennt, eine location kann darauf also nie matchen. Lesen Sie stattdessen $arg_name innerhalb des Blocks.

✗ Falsch
location /search?q= { }
# never matches anything
✓ Richtig
location /search {
    if ($arg_q = "") { return 400; }
}

Was Sie mit dem nginx location Tester machen können

Eine Konfiguration prüfen, bevor sie in Produktion geht
Denken Sie das Routing eines server-Blocks durch, den Sie bearbeitet, aber noch nicht ausgerollt haben. Der Fehler, den das findet, ist der, der nur bei einer bestimmten URI-Form auftritt — also genau die Sorte, die ein Smoke-Test nach dem Reload gern verpasst.
Herausfinden, warum eine Regel nicht mehr greift
Ein regulärer Ausdruck, der früher lief und jetzt nicht mehr, ist fast immer ein Opfer der Reihenfolge: Etwas hat vorher gepasst, oder darüber ist ein ^~ aufgetaucht. Die Tabelle markiert den Block als unerreichbar und nennt den Block, der die Anfrage genommen hat.
Ein Upload- oder Medienverzeichnis auditieren
Laden Sie das Preset, das die Upload-Ausführungs-Form nachstellt, und fügen Sie dann Ihre eigenen Pfade ein. Nimmt ein PHP-Regex Anfragen innerhalb eines beschreibbaren Verzeichnisses entgegen, sagt die Diagnose das und nennt beide Blöcke.
Einen Review-Kommentar mit Belegen klären
„Link kopieren“ hält Konfiguration und URI exakt im URL-Fragment fest. In einen Pull Request geworfen ersetzt das eine Diskussion über Vorrang durch eine Entscheidungstabelle, die jeder nachrechnen kann.
Den Auswahlalgorithmus vermitteln
Die beiden Referenztabellen sind statisches, crawlbares Material, auf das Sie zeigen können, und die Preset-Chips führen jede Falle vor, ohne dass dafür ein Server kaputtgehen muss. Besonders das ^~-Beispiel beendet die Debatte meist schnell.

So funktioniert die Auswahl der nginx location

Die Normalisierung passiert, bevor irgendeine location betrachtet wird
Die URI wird prozent-dekodiert, .- und ..-Segmente werden aufgelöst und wiederholte Schrägstriche zusammengefasst, und erst danach wird eine location gewählt. Ein dekodiertes %2F wird zu einem echten Trennzeichen und nimmt an dieser Auflösung teil, /a/b%2F..%2Fzz wird also als /a/zz gematcht. Drei dekodierte Zeichen sind Ausnahmen und bleiben literal: %25, %23 und %3F — deshalb hat /a%3Fx=1 ein Fragezeichen im Pfad und einen leeren Query-String. Ein + ist hier kein Leerzeichen; nur %20 ist eines. Traversal über das Root hinaus und eine ungültige Escape-Sequenz werden beide mit 400 abgewiesen, bevor das Matching beginnt.
Die Präfixlänge entscheidet, die Konfigurationsreihenfolge nicht
Jede passende Präfix-location wird verglichen, und die längste gewinnt, ob sie nun zuerst oder zuletzt in der Datei steht. Verglichen wird zeichenweise, nicht nach Pfadsegmenten, /static passt also auf /staticfoo. Der Gewinner wird gemerkt statt sofort verwendet, weil die Regex-Phase ihn noch überstimmen kann.
^~ unterdrückt reguläre Ausdrücke; es erhöht nicht die Priorität
Der Modifikator wird nur an dem Präfix geprüft, das über die Länge bereits gewonnen hat. Passt zusätzlich ein längeres einfaches Präfix, wird dieses gemerkt und die Regex-Phase läuft wie gewohnt — der ^~-Block hat auf die Anfrage überhaupt keine Wirkung. Ein ^~ an einer verschachtelten location schützt nicht vor einem auf der äußeren Ebene deklarierten regulären Ausdruck, und es unterdrückt nie die regulären Ausdrücke, die in seinem eigenen Block verschachtelt sind.
Reguläre Ausdrücke laufen in Dateireihenfolge, und der erste Treffer beendet die Suche
nginx behält Regex-locations in der Reihenfolge, in der sie geschrieben wurden, und sortiert sie nicht. Spezifität, Länge und Verankerung haben keinen Einfluss darauf, welcher zuerst geprüft wird; ein präzises Muster unterhalb eines breiten ist also tote Konfiguration. In eine getroffene Regex-location wird weiterhin hineingestiegen, ihre verschachtelten locations werden also anschließend durchsucht.
PCRE und ECMAScript sind nicht dieselbe Sprache
nginx kompiliert location-Regexe mit PCRE, ohne UTF- und ohne Multiline-Modus, die Muster arbeiten also auf Bytes und ^ verankert nur am Anfang der URI. Ein Unterschied hat sicherheitsrelevantes Gewicht: PCREs $ matcht auch direkt vor einem abschließenden Zeilenumbruch, eine URI mit %0A am Ende erfüllt also weiterhin \.php$, obwohl eine JavaScript-Engine sie ablehnen würde. Dieses Verhalten wird hier nachgebildet und gemeldet, weil es ein bekannter Weg ist, an Regeln vorbeizukommen, die auf einer Dateiendung aufbauen.

Best Practices für nginx location

Beschreibbare Verzeichnisse mit ^~ schützen, nicht mit einem einfachen Präfix
Jedes Verzeichnis, das Uploads annimmt, braucht location ^~ /uploads/, damit die Regex-Phase eine abgelegte Datei nicht an einen Interpreter übergeben kann. Ein einfaches Präfix sieht gleichwertig aus und ist es nicht.
Verzeichnis-Präfixen einen abschließenden Schrägstrich geben
Schreiben Sie location /static/ statt location /static, außer Sie wollen bewusst, dass /staticfoo und /static-backup vom selben Block bedient werden. Ergänzen Sie ein eigenes location = /static, wenn auch der nackte Pfad behandelt werden muss.
Reguläre Ausdrücke vom spezifischsten zum allgemeinsten ordnen
Der erste Treffer gewinnt, ein breites Muster über einem präzisen macht das präzise also unerreichbar. Wenige, bewusst geordnete reguläre Ausdrücke sind leichter zu pflegen, als hinterher über Überschneidungen nachzudenken.
Reguläre Ausdrücke verankern, die ein Pfadpräfix treffen sollen
location ~ /admin sucht irgendwo in der URI und passt auf /public/admin/x. Schreiben Sie ~ ^/admin, wenn Sie den Anfang meinen. Nur am Ende zu verankern ist für Endungs-Routing normal und richtig.
Nach jedem Umsortieren das Routing erneut prüfen
Blöcke zu verschieben ist bei Präfixen ungefährlich und ändert bei regulären Ausdrücken das Verhalten. Da ein Diff, der nur Zeilen umsortiert, im Review harmlos aussieht, ist das erneute Durchspielen der betroffenen URIs der billigste Weg, das zu erwischen.

FAQ zum nginx location Tester

Wie finde ich heraus, welche location nginx ausgewählt hat?
Fügen Sie die Konfiguration und die Anfrage-URI in diesen Tester ein, um den gewinnenden Block zu sehen und zu erfahren, warum jeder andere Block ausgeschieden ist. Auf einem laufenden Server ergänzen Sie error_log /var/log/nginx/debug.log debug; und suchen die Zeile "using configuration", die die ausgewählte location nennt. Die beiden Wege beantworten unterschiedliche Fragen: Das Log sagt Ihnen, was ein laufender Server getan hat, diese Seite sagt Ihnen, was eine noch nicht ausgerollte Konfiguration tun würde.
Warum funktioniert mein nginx location-Regex nicht?
Meist ist es einer von drei Gründen, und die Entscheidungstabelle benennt, welcher. Ein früherer regulärer Ausdruck hat bereits gepasst, Ihrer wurde also nie ausgeführt — reguläre Ausdrücke werden in Dateireihenfolge geprüft, der erste Treffer gewinnt. Oder das längste passende Präfix trägt ^~, was die Regex-Phase komplett überspringt. Oder der Ausdruck ist in Ordnung, aber die URI ist nicht die, die Sie erwarten: Gematcht wird gegen den normalisierten Pfad, nach Prozent-Dekodierung und Auflösung von .., ohne Query-String.
Warum greift mein exakter Treffer nicht?
Eine =-location verlangt, dass die gesamte URI gleich ist, nicht dass sie mit dem Muster beginnt. location = /a/ passt nicht auf /a, und location = /a passt nicht auf /a/b. Abschließende Schrägstriche sind hier ganz gewöhnliche Zeichen, die beiden Formen sind also verschiedene Zeichenketten. Passt eine exakte location, endet die Suche sofort und nichts anderes wird überhaupt noch verglichen.
Matcht nginx den Query-String in einem location-Block?
Nein. Der Query-String wird bei der Normalisierung abgetrennt, und die Auswahl der location läuft allein gegen den Pfad. Deshalb passt location = /a auf eine Anfrage nach /a?x=/b. Wenn Sie anhand eines Parameters verzweigen müssen, lesen Sie im Block $arg_name oder $args. Eine Feinheit lohnt sich zu wissen: %3F wird zu einem literalen Fragezeichen, das im Pfad bleibt, /a%3Fx=1 hat also einen leeren Query-String und einen Pfad, der ein ? enthält.
Kann ich JavaScript-Regex-Syntax in einer nginx location verwenden?
Nein — nginx nutzt PCRE, und die Unterschiede sind relevant. Diese Seite läuft in Ihrem Browser, wo es nur ECMAScript-Ausdrücke gibt; PCRE-eigene Konstrukte werden deshalb erkannt und markiert, statt stillschweigend falsch ausgewertet zu werden: atomare Gruppen, possessive Quantoren, Inline-Modifikatoren wie (?i), POSIX-Klassen wie [[:alpha:]] und Escapes wie \A und \K, die JavaScript klaglos als gewöhnliche Buchstaben liest. Ist eine location markiert, werden die übrigen Kandidaten weiterhin in nginx' Reihenfolge ausgewertet, aber das Urteil zu diesem Block gehört auf einem echten Server geprüft. Wenn Sie das Muster selbst schreiben, deckt der Regex-Tester die ECMAScript-Syntax ausführlich ab.
Unterscheiden nginx location-Präfixe Groß- und Kleinschreibung?
Unter Linux ja — location /Static/ passt nicht auf /static/x. Auf Dateisystemen ohne diese Unterscheidung, etwa unter macOS und Cygwin, vergleicht nginx Präfixe ohne Beachtung der Groß-/Kleinschreibung und zwingt zusätzlich jede Regex-location, sich wie ~* zu verhalten. Diese Seite bildet das Linux-Verhalten ab, das auf Produktionsservern praktisch immer gilt. Wer auf einem Mac entwickelt und auf Linux ausrollt, übersieht durch diesen Unterschied eine kaputte Regel leicht bis ins Deployment.
Ändert try_files, welcher location-Block ausgewählt wurde?
Nein. Die Auswahl der location ist zuerst abgeschlossen; try_files läuft danach, innerhalb des Blocks, der bereits gewonnen hat. Erreicht eine Anfrage den Block mit Ihrem try_files nie, ist die Direktive belanglos — üblicher Grund ist ein ~ \.php$-Regex, der die Anfrage abfängt, bevor der Präfix-Block mit dem Fallback überhaupt zum Zug kommt. Ein später ausgelöster interner Redirect startet das Matching allerdings neu, eine umgeschriebene URI wird also erneut von oben gegen die location-Liste aufgelöst.
Warum antwortet nginx mit 301, wenn ich ein Verzeichnis ohne Schrägstrich anfrage?
Dafür gibt es zwei verschiedene Mechanismen. Trägt eine location, deren Name auf / endet, ein proxy_pass oder eine andere *_pass-Direktive, wird eine Anfrage auf denselben Pfad ohne Schrägstrich schon während der location-Auswahl mit 301 beantwortet — bevor irgendein regulärer Ausdruck ausgewertet wird. Davon unabhängig sendet das Modul für statische Dateien ein 301, wenn der Pfad auf ein echtes Verzeichnis auf der Platte zeigt. Das Erste ist hier sichtbar, das Zweite hängt von Ihrem Dateisystem ab. Ein zusätzliches location = /path unterdrückt das Erste.
Ändern verschachtelte location-Blöcke das Ergebnis?
Ja, und zwar auf eine Art, die man leicht übersieht. nginx steigt in die gewinnende Präfix-location hinab und durchsucht deren Kinder, ein verschachtelter regulärer Ausdruck wird also vor den regulären Ausdrücken der Elternebene geprüft. Ein ^~ am äußeren Block schützt ihn nicht vor seinen eigenen verschachtelten regulären Ausdrücken, und Verschachtelung kann ein insgesamt längeres Präfix unerreichbar machen, wenn ein Geschwisterblock auf der äußeren Ebene zuerst gewinnt. Verschachtelte Blöcke werden hier mit derselben Einrückung abgebildet, in der Sie sie geschrieben haben.
Wird meine nginx-Konfiguration irgendwohin hochgeladen?
Nein. Parsen und Matchen passieren lokal in Ihrem Browser mit einfachen Zeichenketten-Operationen — es gibt keinen Server-Aufruf und nichts wird gespeichert. Das wiegt hier schwerer als bei den meisten Tools, weil ein echter server-Block Upstream-Hostnamen, interne Ports, Zertifikatspfade und Auth-Regeln enthält. Sie müssen uns das nicht glauben: Öffnen Sie die Entwicklerwerkzeuge Ihres Browsers und sehen Sie zu, wie das Netzwerk-Panel beim Tippen stumm bleibt, oder trennen Sie die Verbindung ganz und testen Sie weiter. Dass keine externe Anfrage stattfindet, wird zusätzlich bei jedem Build durch einen automatisierten Vertragstest erzwungen und kann daher nicht unbemerkt zurückfallen.

Verwandte Werkzeuge

Alle Werkzeuge anzeigen →