Skip to content
Zurück zum Blog
Tutorials

Nginx-location-Priorität: Matching-Reihenfolge erklärt

Wie nginx einen location-Block auswählt: die exakte Reihenfolge für =, ^~, ~ und Präfixe, plus typische Fallstricke — mit kostenlosem Online-Tester.

12 Min. Lesezeit

Nginx-location-Priorität: Matching-Reihenfolge erklärt

Nginx liest Ihre location-Blöcke nicht von oben nach unten und hört auch nicht beim ersten passenden auf. Genau dieses eine Missverständnis steckt hinter den meisten Fehlerberichten der Sorte „mein location-Block greift einfach nicht“. Bei Präfix-locations spielt es überhaupt keine Rolle, an welcher Stelle der Datei ein Block steht: nginx vergleicht alle und merkt sich die längste Übereinstimmung.

Die tatsächliche nginx-location-Priorität ist eine feste Abfolge aus vier Schritten:

  1. Exakte Übereinstimmung. Wenn ein location = /path der URI entspricht, nimmt nginx diesen Block und hört auf. Kein Präfixvergleich, keine Regex.
  2. Längstes Präfix. nginx vergleicht jede Präfix-location (location /path und location ^~ /path), mit der die URI beginnt, und merkt sich die längste davon. Ausgewählt ist sie damit noch nicht.
  3. Die Abkürzung über ^~. Trägt das gemerkte Präfix ein ^~, überspringt nginx die Regex-Phase vollständig und verwendet diesen Block.
  4. Regex, in Dateireihenfolge. Andernfalls prüft nginx die ~- und ~*-locations in der Reihenfolge, in der sie in der Konfiguration stehen, und die erste Übereinstimmung gewinnt. Passt keine, kommt das in Schritt 2 gemerkte Präfix zum Zug.

Zwei dieser Regeln ziehen in entgegengesetzte Richtungen: Präfixe wählt nginx nach Länge, unabhängig von der Reihenfolge, Regexes nach Reihenfolge, unabhängig von der Länge. Wer eine Konfiguration von oben nach unten liest, bekommt diesen Konflikt nie zu Gesicht. Wenn Sie die Antwort für Ihre eigene Datei wollen statt für die Beispiele unten, fügen Sie sie in den kostenlosen Nginx Location Tester ein. Er spielt genau diese Abfolge nach und zeigt, in welcher Stufe jeder unterlegene Block ausgeschieden ist. Er läuft in Ihrem Browser, eine eingefügte Produktivkonfiguration verlässt die Seite also nie. Jede hier beschriebene Matching-Regel wurde an einem laufenden nginx 1.27.5 geprüft und nicht aus Sekundärartikeln übernommen.

Nginx-location-Priorität auf einen Blick

Fünf Modifikatoren nehmen an der URI-Zuordnung teil, plus einer, der es nicht tut.

ModifikatorSyntaxZuordnung überBeendet die Regex-PhaseTypischer Einsatz
=location = /pathGleichheitJaSehr häufig getroffene Pfade wie / oder /favicon.ico
^~location ^~ /pathBeginnt mitJa, sofern es das längste Präfix istVerzeichnisse, die nie eine Regex erreichen dürfen
~location ~ regexPCRE, Groß-/Kleinschreibung beachtetNeinEndungs-Routing, bei dem die Schreibweise zählt
~*location ~* regexPCRE, Groß-/Kleinschreibung ignoriertNeinEndungs-Routing, bei dem sie nicht zählt
(keiner)location /pathBeginnt mitNeinAllgemeines Routing nach Pfad
@location @nameNie über die URIZiele für error_page und try_files

Als Faustregel: eine exakte Übereinstimmung schlägt alles, eine Regex schlägt ein Präfix, und Präfixe schlagen einander über die Länge. Die einzige Ausnahme ist ^~, und sie ist enger gefasst, als sie aussieht.

Diese Tabelle ist nur im lockersten Sinne eine Rangfolge. ^~ steht darin über ~, trotzdem verliert ein ^~-Block regelmäßig gegen eine Regex: nginx zieht den Modifikator nur bei genau dem Präfix heran, das bereits über die Länge gewonnen hat.

Der vierstufige Auswahlalgorithmus

Die nginx-location-Zuordnungsreihenfolge sitzt am schnellsten, wenn man sie an einer Konfiguration durchspielt, die alle Regeln gleichzeitig auslöst. Das folgende Beispiel stammt aus der nginx-Dokumentation:

server {
    location = /                   { return 200 "A\n"; }
    location /                     { return 200 "B\n"; }
    location /documents/           { return 200 "C\n"; }
    location ^~ /images/           { return 200 "D\n"; }
    location ~* \.(gif|jpg|jpeg)$  { return 200 "E\n"; }
}

Fünf Anfragen, fünf verschiedene Antworten:

AnfrageGewinnerWarum
/AExakte Übereinstimmung. Die Suche endet sofort.
/index.htmlBKeine Regex passte, also greift das gemerkte Präfix.
/documents/document.htmlCLängeres Präfix als /.
/images/1.gifD^~ gewann die Präfix-Stufe, deshalb lief die Regex nie.
/documents/1.jpgEDie Regex schlug ein längeres Präfix, dem ^~ fehlte.

Vergleichen Sie die letzten beiden Zeilen. /images/ und /documents/ sind beide Präfixe, beide passen, beide sind für ihre jeweilige Anfrage die längste Übereinstimmung. Die eine Anfrage landet im Präfix-Block, die andere in der Regex. Der einzige Unterschied sind zwei Zeichen.

Schritt 2 liest praktisch jeder falsch: nginx verwendet das längste Präfix nicht, es merkt es sich. Der Block ist damit ein Kandidat, und die Regex-Phase kann ihm die Anfrage noch wegnehmen. Nur die Schritte 1, 3 und 4 beenden die Suche.

Warum nginx „längstes Präfix“ in Zeichen zählt, nicht in Pfadsegmenten

Der Präfixvergleich ist ein schlichter Zeichenkettenvergleich. Er weiß nicht, dass / Pfadsegmente trennt, und er hält an keiner Segmentgrenze an. Mit dieser Konfiguration:

server {
    location /static  { }
    location /static/ { }
}

bedient location /static eine Anfrage auf /staticfoo. Die URI beginnt mit diesen sieben Zeichen, also passt sie. /static/ passt überhaupt nicht, weil an dieser Stelle kein Schrägstrich steht. Eine Anfrage auf /static/x geht den anderen Weg und nimmt /static/, das längere der beiden.

Die Folge davon: location /static besitzt auch /static-backup, /staticfiles und alles andere, was zufällig mit denselben Buchstaben beginnt. Wenn Sie ein Verzeichnis meinten, schreiben Sie den abschließenden Schrägstrich und ergänzen Sie eine exakte location für den nackten Pfad:

server {
    location /static/ { root /var/www; }
    location = /static { return 301 /static/; }
}

Die meisten Tutorials verwenden aufgeräumte Pfadbeispiele, an denen das nie auffällt, und deshalb übersteht der Fehler so oft das Code-Review. Der Nginx Location Tester zeigt jeden Block, der gepasst hat, samt der Zeichenzahl, auf die er jeweils gepasst hat. Ein Präfix, das seine Geschwister verschluckt, sehen Sie damit, statt es sich erschließen zu müssen.

Was ^~ wirklich bedeutet (und was nicht)

Die verbreitete Beschreibung des nginx-location-Modifikators ^~ lautet: „Er gibt diesem Block Vorrang vor Regexes.“ Das ist nah genug an der Wahrheit, um gefährlich zu sein.

Was ^~ tatsächlich tut: während des Präfixvergleichs gar nichts. Es verlängert die Übereinstimmung nicht und ändert auch nicht, welches Präfix nginx sich merkt. Geprüft wird der Modifikator erst danach, an dem einen Präfix, das bereits über die Länge gewonnen hat. Trägt dieser Gewinner ein ^~, entfällt die Regex-Phase. Tut er es nicht, läuft sie ganz normal.

Das heißt umgekehrt: ein längeres schlichtes Präfix setzt den Modifikator stillschweigend außer Kraft.

server {
    location ^~ /a/    { }
    location /a/b/     { }
    location ~ \.php$  { }
}

Eine Anfrage auf /a/b/x.php landet bei ~ \.php$. /a/b/ ist das längste passende Präfix, also merkt nginx sich dieses; sein schlichter Modifikator lässt die Regex-Phase zu; die Regex passt zuerst und nimmt die Anfrage mit. Der ^~-Block steht weiterhin in der Datei, sieht weiterhin schützend aus und hat auf diese Anfrage nicht den geringsten Einfluss.

Ändern Sie die URI auf /a/x.php, verhält sich dieselbe Konfiguration völlig anders: jetzt ist ^~ /a/ die längste Übereinstimmung, die Regex-Phase entfällt, und der ^~-Block gewinnt. Gleiche Datei, gleiche Form der Anfrage, entgegengesetztes Ergebnis.

Der klassische Einsatz von ^~ besteht darin, ein beschreibbares Verzeichnis von einem Interpreter fernzuhalten:

server {
    location ^~ /uploads/ { }
    location ~ \.php$     { fastcgi_pass unix:/run/php-fpm.sock; }
}

Lassen Sie das ^~ weg, und eine Anfrage auf /uploads/evil.php geht direkt an PHP-FPM. Das ist das Muster hinter einer langen Reihe von Upload-zu-RCE-Meldungen, und zwischen verwundbar und sicher liegen zwei Zeichen. Genau deshalb zählt auch der Fall des ausgehebelten ^~: ein längeres schlichtes Präfix wie location /uploads/thumbs/ reißt die Lücke für alles darunter wieder auf, und der Diff, der das anrichtet, sieht vollkommen harmlos aus.

Beachten Sie außerdem den Geltungsbereich. ^~ unterdrückt nur Regexes, die auf der eigenen Ebene deklariert sind; Regexes innerhalb des eigenen Blocks unterdrückt es nie, und ein ^~ an einer verschachtelten location kann nicht vor einer Regex schützen, die auf server-Ebene steht. Schalten Sie den Modifikator im Nginx Location Tester um und beobachten Sie, wie der Gewinner wechselt. Das Werkzeug weist jede übersprungene Regex ausdrücklich aus, statt sie aus der Tabelle verschwinden zu lassen.

Regex-locations: Reihenfolge schlägt Genauigkeit

Eine nginx-location-Regex verwendet ~, wenn die Groß-/Kleinschreibung beachtet werden soll, und ~*, wenn nicht. Der Präfixvergleich beachtet unter Linux dagegen immer die Groß-/Kleinschreibung. (Auf Dateisystemen, die das nicht tun, etwa unter macOS, vergleicht nginx Präfixe ohne Rücksicht auf die Schreibweise und zwingt jede Regex-location dazu, sich wie ~* zu verhalten. Wer auf dem Mac entwickelt und unter Linux ausliefert, kann sich damit eine kaputte Regel bis ins Deployment hinein verstecken.)

Die Regel, an der die meisten Konfigurationen scheitern: nginx wertet Regexes in der Reihenfolge aus, in der sie in der Konfigurationsdatei stehen, und die erste Übereinstimmung beendet die Suche. Genauigkeit, Länge und Verankerung haben auf die Reihenfolge keinen Einfluss.

server {
    location ~ ^/a       { }
    location ~ ^/a/b/c$  { }
}

Eine Anfrage auf /a/b/c nimmt ~ ^/a. Der zweite Block passt exakt auf diese URI und ist weit präziser, kommt aber bei keiner einzigen Anfrage zum Zug. Es ist tote Konfiguration, die nginx -t kommentarlos durchwinkt.

Ordnen Sie Regexes also von der genauesten zur allgemeinsten und halten Sie die Liste kurz. Ein breites Muster weit oben macht alles darunter unerreichbar, und weil ein Diff, der nur Zeilen umsortiert, harmlos aussieht, kommt diese Regression eher beim Aufräumen als beim neuen Feature.

Die Verankerung verdient dieselbe Sorgfalt. location ~ /admin ist an keinem Ende verankert, sucht also überall in der URI und passt bereitwillig auf /public/admin/x. Schreiben Sie ~ ^/admin, wenn Sie den Anfang meinen. Nur am Ende zu verankern, wie in ~ \.php$, ist beim Endungs-Routing normal und richtig.

Ein paar PCRE-Details, bei denen von JavaScript geprägte Intuitionen danebenliegen:

  • nginx kompiliert location-Muster mit PCRE, ohne UTF- und ohne Multiline-Modus; die Muster arbeiten also auf Bytes, und ^ verankert ausschließlich am Anfang der URI.
  • Das $ von PCRE passt auch unmittelbar vor einem abschließenden Zeilenumbruch. Eine URI, die auf %0A endet, erfüllt \.php$ weiterhin, ein bekannter Weg an Regeln vorbei, die an einer Dateiendung hängen.
  • Konstrukte ohne JavaScript-Entsprechung sind in PCRE häufig: atomare Gruppen (?>…), possessive Quantoren a*+, Inline-Modifikatoren wie (?i), POSIX-Klassen wie [[:alpha:]] sowie Escapes wie \A, \z, \K und \Q…\E.
  • Ein Muster, das { oder } enthält, muss in Anführungszeichen stehen. location ~ ^/a{2}$ lädt nicht und meldet unknown directive "2}$", weil die geschweifte Klammer das Token beendet hat. Schreiben Sie location ~ "^/a{2}$".

Erfassungsgruppen funktionieren so, wie man es erwartet, und $1 und folgende stehen innerhalb des Blocks zur Verfügung:

upstream backend {
    server 127.0.0.1:8080;
}

server {
    location ~ ^/user/(\d+)/profile$ {
        proxy_pass http://backend/profiles/$1;
    }
}

Wenn Sie noch am Muster selbst herumprobieren statt an seiner Position in der Datei, testen Sie es zuerst im Regex-Tester; der Regex-Spickzettel behandelt die Syntax ausführlich.

Der Schritt, den alle überspringen: URI-Normalisierung

Bevor nginx überhaupt eine location heranzieht, schreibt es das Anfrageziel um. Es vergleicht Ihre Muster mit dem normalisierten Pfad, nicht mit den Bytes, die über die Leitung kamen. Kaum ein Tutorial erwähnt das, und es entscheidet überraschend viele Fälle von „meine location passt nicht“.

Die Normalisierung erledigt vier Dinge: sie trennt den Query-String ab, dekodiert Prozentkodierungen im Pfad, löst .- und ..-Segmente auf und fasst wiederholte Schrägstriche zusammen.

AnfragezielNormalisierte $uriAnmerkung
//a//x/a/xWiederholte Schrägstriche zusammengefasst
/a/../b/x/b/x.. wird vor der Zuordnung aufgelöst
/a/b%2F..%2Fzz/a/zz%2F wird zu einem echten Trennzeichen und geht in die Auflösung ein
/a/%2e%2e/b/x/b/x%2E wird zu einem Punkt, der ebenfalls mitspielt
/a%20b/x/a b/x%20 wird zu einem echten Leerzeichen
/a+b/x/a+b/x+ ist im Pfad kein Leerzeichen
/a?x=/b/aQuery-String wird zuerst abgetrennt
/a%3Fx=1/a?x=1%3F bleibt literal; der Query-String ist leer

Drei dekodierte Zeichen sind Ausnahmen: %25, %23 und %3F gibt nginx unverändert wieder aus und interpretiert sie kein zweites Mal. Deshalb landet bei /a%3Fx=1 ein Fragezeichen im Pfad und nichts in $args.

Zwei Ziele erreichen die location-Auswahl überhaupt nie. ..-Segmente, die über die Wurzel hinausklettern, und eine ungültige Escape-Sequenz wie %00 weist nginx beide schon vor der Zuordnung mit 400 ab.

Sicherheitsrelevant wird das, sobald Sie einen location-Block als Zugriffsgrenze verwenden: nginx hält dann den Pfad, den Sie geschrieben haben, gegen den aufgelösten Pfad:

server {
    location /a/ { }
    location /b/ { }
}

Eine Anfrage auf /a/b%2F..%2Fzz bleibt nicht unterhalb von /a/b/. Sie normalisiert sich zu /a/zz, und damit bearbeitet location /a/ sie. Wer über das rohe Ziel statt über $uri nachdenkt, kommt hier zur falschen Antwort, und eine falsche Antwort im Kontext der Zugriffskontrolle hat einen eigenen Namen. Bevor Sie sich darauf verlassen, dass location /admin irgendetwas schützt, prüfen Sie also, wie der normalisierte Pfad tatsächlich aussieht. Der Nginx Location Tester zeigt das rohe Ziel, die normalisierte $uri und den abgetrennten Query-String als drei getrennte Zeilen; und wenn Sie nur die Kodierung selbst durchdenken müssen, erledigt der URL-Dekodierer & -Kodierer das isoliert.

Eine weitere Konsequenz gehört klar ausgesprochen: der Query-String nimmt niemals an der Zuordnung teil. location /search?q= kann keine Anfrage auf /search?q=1 treffen, weil die Auswahl immer nur /search zu sehen bekommt. Um auf einen Parameter zu verzweigen, lesen Sie $arg_name innerhalb des Blocks aus.

Fünf Konfigurationen, die nicht tun, was Sie denken

Ein ^~-Block verliert gegen ein längeres schlichtes Präfix

Symptom: ein ^~-Verzeichnis sieht geschützt aus, und eine Regex bearbeitet trotzdem Anfragen darin. Ursache: nginx prüft ^~ nur an dem Präfix, das bereits über die Länge gewonnen hat. Gemerkt hat es sich stattdessen ein längeres schlichtes Präfix, und das unterdrückt nichts. Lösung: setzen Sie ^~ auch auf das längere Präfix, oder entfernen Sie das längere Präfix.

# Broken: /a/b/x.php goes to the regex
location ^~ /a/    { }
location /a/b/     { }
location ~ \.php$  { }

# Fixed: /a/b/x.php goes to ^~ /a/b/
location ^~ /a/    { }
location ^~ /a/b/  { }
location ~ \.php$  { }

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

Symptom: ein Block, der für ein Verzeichnis gedacht war, bedient auch Pfade, die lediglich mit denselben Buchstaben beginnen. Ursache: die Präfixzuordnung vergleicht Zeichen, keine Pfadsegmente, deshalb passt location /app auch auf /application. Lösung: schreiben Sie den abschließenden Schrägstrich und ergänzen Sie location = /app, falls der nackte Pfad ebenfalls behandelt werden muss.

Die spezifische Regex steht unter der breiten

Symptom: eine präzise Regel greift nie, und nirgends erscheint ein Fehler. Ursache: nginx prüft Regexes in Dateireihenfolge, und die erste Übereinstimmung beendet die Suche; alles unterhalb eines breiten Musters bleibt damit unerreichbar. Lösung: verschieben Sie das spezifische Muster über das breite, oder ziehen Sie das breite mit einem Anker enger.

Eine Regex hinter ^~ geschrieben

Symptom: eine deny-Regel lädt sauber und blockiert nichts. Ursache: ^~ erwartet ein literales Präfix, kein Muster. nginx beschwert sich nie; der Block passt schlicht auf keine URI. Lösung: verwenden Sie den Regex-Modifikator.

# Broken: matches nothing, loads without error
location ^~ "\.php$" { deny all; }

# Fixed
location ~ \.php$ { deny all; }

Annehmen, der Query-String spiele mit

Symptom: eine location, die ? enthält, passt nie. Ursache: der Query-String wird bei der Normalisierung abgetrennt, und die location-Auswahl läuft allein gegen den Pfad. Lösung: ordnen Sie über den Pfad zu und werten Sie $arg_name innerhalb des Blocks aus.

location /search {
    if ($arg_q = "") { return 400; }
}

Debugging: herausfinden, welcher Block tatsächlich gewonnen hat

Das Debug-Log gibt die maßgebliche Antwort und kostet zugleich am meisten Einrichtungsaufwand. Es braucht ein Binary mit Debug-Unterstützung, prüfen Sie das also zuerst:

nginx -V 2>&1 | grep -o with-debug

Dann schalten Sie es ein und greppen nach der Zeile, die den gewählten Block benennt:

error_log /var/log/nginx/debug.log debug;
grep "using configuration" /var/log/nginx/debug.log

Sonden über Response-Header gehen schneller und brauchen keinen Debug-Build. Markieren Sie jeden Kandidaten und lesen Sie die Header zurück:

location ^~ /uploads/ {
    add_header X-Debug-Location "uploads-caret" always;
    return 204;
}
location ~ \.php$ {
    add_header X-Debug-Location "php-regex" always;
    return 204;
}
curl -sI --path-as-is 'http://localhost/uploads/evil.php' | grep -i x-debug-location

--path-as-is ist entscheidend: ohne diese Option löst curl .. hilfsbereit für Sie auf, und Sie testen am Ende eine andere URI als die gemeinte. Wenn Sie etwas Aufwendigeres zusammenbauen, schreibt Ihnen der cURL-Befehlsgenerator die Flags, und der curl Spickzettel deckt den Rest ab. Kommt die Sonde als Weiterleitung oder 404 zurück statt mit Ihrem Header, verrät Ihnen die Referenz zu den HTTP-Statuscodes meistens, welches Modul dahintersteckt.

nginx -T gibt die vollständig zusammengeführte Konfiguration aus, inklusive aller include-Dateien. So finden Sie heraus, in welcher Reihenfolge Ihre Regexes wirklich stehen, nachdem sechs Dateien zusammengesetzt wurden. Das ist selten die Reihenfolge aus der Datei, die Sie gerade bearbeiten.

nginx -T | grep -n "location"

Reproduzieren Sie den Fehler im Nginx Location Tester, bevor Sie den Server anfassen. Gegen eine Konfiguration zu iterieren, die noch nicht ausgerollt ist, geht schneller als ein Reload-Zyklus, und die Entscheidungstabelle benennt die Stufe, an der jeder Block ausgeschieden ist, statt Sie raten zu lassen.

Verschachtelte locations, try_files und was sie nicht ändern

Verschachtelte locations führen denselben Algorithmus eine Ebene tiefer aus. Sobald eine Präfix-location gewonnen hat, steigt nginx in ihre Kinder hinab und wiederholt die Suche dort. Eine verschachtelte Regex kommt also vor den Regexes der Elternebene an die Reihe:

server {
    location ~ \.php$ { }
    location /a/ {
        location ~ \.php$ { return 200 "nested\n"; }
    }
}

/a/x.php bearbeitet der verschachtelte Block. Verschachtelung hat noch einen weniger offensichtlichen Effekt: sie kann ein global längeres Präfix unerreichbar machen, weil nginx auf jeder Ebene nur in den Gewinner hinabsteigt. Liegt location /a/bb/ innerhalb von location /a/ und steht auf der äußeren Ebene ein Geschwister location /a/b, dann geht eine Anfrage auf /a/bb/x an /a/b. Der äußere Vergleich findet zuerst statt, und /a/b gewinnt ihn. Ein Abstieg, der nichts findet, springt auch nicht zurück; die Anfrage bleibt beim Elternblock.

try_files und rewrite gehören nicht zur Auswahl. Sie laufen innerhalb desjenigen Blocks, der bereits gewonnen hat, und können daran nachträglich nichts mehr ändern. Erreicht eine Anfrage den Block mit Ihrem try_files nie, ist die Direktive belanglos, und die übliche Ursache ist eine Regex ~ \.php$, die sich die Anfrage schnappt, bevor der Präfix-Block überhaupt an die Reihe kommt. Die eine Ausnahme, die man kennen sollte: eine interne Weiterleitung (rewrite … last oder ein Sprung über error_page) startet die Zuordnung neu, sodass nginx die umgeschriebene URI wieder von oben gegen die location-Liste auflöst.

Und schließlich: die 301, die Sie bekommen, wenn Sie ein Verzeichnis ohne abschließenden Schrägstrich anfragen, ist kein Fehler der Zuordnung. Zwei getrennte Mechanismen erzeugen sie. Trägt eine location, deren Name auf / endet, ein proxy_pass oder eine andere *_pass-Direktive, beantwortet nginx eine Anfrage auf denselben Pfad ohne Schrägstrich schon während der Auswahl mit einer 301, vor jeder Regex-Auswertung und unter Beibehaltung des Query-Strings:

server {
    location /user/ { proxy_pass http://backend/; }
}
# GET /user?x=1  ->  301 to /user/?x=1

location = /user zu ergänzen unterdrückt diese Weiterleitung. Davon unabhängig gibt das Modul für statische Dateien eine eigene 301 aus, wenn ein Pfad auf ein echtes Verzeichnis auf der Platte zeigt; das hängt an Ihrem Dateisystem, nicht an Ihrer Konfiguration.

FAQ

Welche fünf location-Modifikatoren gibt es in nginx?

Die fünf nginx-location-Modifikatoren sind = für exakte Zuordnung, ^~ für ein Präfix, das die Regex-Phase überspringt, kein Modifikator für ein gewöhnliches Präfix, ~ für eine Regex mit Beachtung der Groß-/Kleinschreibung und ~* für eine ohne. Eine sechste Form, location @name, nimmt nie an der URI-Zuordnung teil und existiert nur als Ziel für error_page und try_files.

Macht eine exakte =-Übereinstimmung nginx schneller?

Eine location mit exakter Übereinstimmung beendet die Suche sofort und spart den Präfix-Durchlauf sowie jede Regex-Auswertung. Die Ersparnis ist real, aber zu klein, um sie zu bemerken. Sie lohnt sich für Endpunkte, die tausende Male pro Sekunde getroffen werden, etwa Health Checks oder /favicon.ico. Ein ganzer Stapel =-Blöcke für gewöhnliche Seiten kostet mehr an Konfigurationskomplexität, als er einbringt.

Kann ich einen location-Modifikator ohne Leerzeichen schreiben, etwa ~*^/api?

Ja. location ~*^/api/ und location ~* ^/api/ bedeuten exakt dasselbe, weil nginx den Modifikator vorne vom Namen abtrennt und dabei den längsten Modifikator zuerst erkennt, also ~* vor ~. Schreiben Sie das Leerzeichen trotzdem. Ein angeklebter Modifikator liest sich wie ein Teil des Musters, und Menschen parsen ihn beim Review falsch.

Was ist der Unterschied zwischen root und alias innerhalb eines location-Blocks?

root hängt die gesamte URI an das Verzeichnis an, alias ersetzt damit das zugeordnete Präfix. Mit location /static/ { root /var/www; } sucht eine Anfrage auf /static/x.css nach /var/www/static/x.css; wechseln Sie zu alias /var/www/assets/;, sucht sie nach /var/www/assets/x.css. Bei alias geben Sie entweder der location und dem Pfad beiden einen abschließenden Schrägstrich oder keinem von beiden.

Kann eine Anfrage auf mehr als einen location-Block passen?

Mehrere Blöcke können passen, aber genau einer bearbeitet die Anfrage. nginx vergleicht jede Präfix-location und, wenn nötig, jede Regex-location und übergibt die Anfrage dann an den einen Gewinner. Von den unterlegenen Blöcken erbt dieser Gewinner nichts: was Sie überall brauchen, gehört auf server- oder http-Ebene, sonst müssen Sie es wiederholen.

Sagt mir nginx -t, welche location passen wird?

Nein. nginx -t prüft Syntax und Gültigkeit der Konfiguration; es simuliert nie eine Anfrage und sagt deshalb nichts über die Zuordnungsreihenfolge. Um herauszufinden, welcher Block eine URI besitzt, lesen Sie das Debug-Log, fügen Sie einen temporären Response-Header hinzu oder fügen Sie die Konfiguration in den Nginx Location Tester ein und lesen Sie nach, warum jeder Block gewonnen oder verloren hat.

Tags: nginx web-server devops regex configuration

Verwandte Artikel

Alle Artikel anzeigen