Wie nginx eine location wählt
- Die URI wird zuerst normalisiert: Prozent-Dekodierung, mehrfache Schrägstriche zusammengeführt,
.und..aufgelöst. Der Query-String ist nie Teil des Location-Matchings. - Alle Präfix-locations (ohne Modifikator,
=,^~) werden verglichen. Ein exakter=-Treffer gewinnt sofort. Sonst wird der längste passende Präfix gemerkt. - Hat dieser längste Präfix
^~, gewinnt er, und Regexe werden übersprungen. - Regex-locations (
~schreibungsabhängig,~*schreibungsunabhängig) werden in der Reihenfolge der Datei getestet. Der erste Treffer gewinnt, selbst wenn vorher ein längerer Präfix passte. - Passt kein Regex, wird der gemerkte längste Präfix verwendet.
- Innerhalb der gewinnenden location läuft dasselbe Verfahren erneut für verschachtelte locations.
Zwei Folgen überraschen am meisten: Ein schlichtes location /images/ verliert gegen location ~ \.png$ für /images/a.png, weil Regexe nach Präfixen geprüft werden; und location /api passt auch auf /apiary, weil Präfixe String-Präfixe sind, keine Pfadsegmente. Nutzen Sie /api/ oder ^~, wenn Sie es so meinen.
proxy_pass und der abschließende Schrägstrich
Hat proxy_pass einen URI-Teil (irgendetwas nach dem Host, auch nur /), ersetzt nginx den Teil der Request-URI, der auf den Location-Präfix passte, durch ihn. location /api/ { proxy_pass http://app/; } macht aus /api/users /users. Ohne URI-Teil geht die Request-URI unverändert durch. Nicht zusammenpassende Schrägstriche (/api gegen /api/, oder http://app gegen http://app/) erzeugen //users oder users — der Tester gibt die exakte Upstream-URI aus, damit Sie es sehen. In einer Regex-location ist ein URI-Teil nicht erlaubt, es sei denn, ein rewrite hat die URI zuerst geändert.
root gegen alias
root hängt die ganze URI an das Verzeichnis an: root /srv; location /static/ liefert /srv/static/x.css. alias ersetzt den Location-Präfix: alias /srv/assets/; location /static/ liefert /srv/assets/x.css. Bei alias müssen die abschließenden Schrägstriche von location und alias übereinstimmen, und in einer Regex-location muss alias Captures verwenden.
rewrite-Flags
| Flag | Wirkung |
|---|---|
| last | Rewrites beenden, Location-Matching mit der neuen URI neu starten (max. 10-mal, dann 500) |
| break | Rewrites beenden, in der aktuellen location mit der neuen URI bleiben |
| redirect | 302 an den Client senden |
| permanent | 301 an den Client senden |
| (keines) | Mit dem nächsten rewrite fortfahren; auf server-Ebene wird das Ergebnis dann gegen locations gematcht |
try_files
Jedes Argument wird als Datei (oder Verzeichnis, mit abschließendem Schrägstrich) relativ zu root/alias geprüft; das erste existierende wird ausgeliefert. Das letzte Argument ist der Fallback und wird nicht geprüft: Es ist eine interne Umleitung auf eine URI (die erneut durch das Location-Matching geht), eine benannte location @name oder ein Statuscode im Stil =404. Der Tester sieht Ihr Dateisystem nicht, also listet er die Pfade, die geprüft würden.
add_header-Vererbung
add_header wird von der server-Ebene nur geerbt, wenn die location kein eigenes add_header hat. Ein einziges add_header Cache-Control in einer location lässt die auf server-Ebene gesetzten Security-Header stillschweigend wegfallen. Die Spur weist darauf hin.
Fragen
Unterstützt es die volle nginx-Konfigurationssyntax?
Der Parser versteht die echte Syntax: verschachtelte Blöcke, Kommentare, Strings in Anführungszeichen, Regex-Argumente; include-Direktiven werden aufgelistet, aber nicht gefolgt (fügen Sie die eingebundene Datei auch ein). Variablen außer $uri, $request_uri, $args und Regex-Captures bleiben Text, und „if“-Blöcke werden gezeigt, aber nicht ausgewertet.
Warum verhält sich mein Regex in nginx anders?
nginx nutzt PCRE; diese Seite nutzt JavaScript-Regexe. Sie stimmen bei fast allem überein, was in location-Blöcken vorkommt, aber possessive Quantoren, Rekursion und manche Lookbehind-Formen unterscheiden sich. Die Spur sagt, wenn ein Regex nicht kompiliert werden konnte.
Kann es testen, welcher server-Block für einen Host antwortet?
Ja. Fügen Sie mehrere server-Blöcke ein und füllen Sie das Host-Feld aus. Die Auswahl folgt nginx: exakter Name, längste Wildcard mit * am Anfang, längste Wildcard mit * am Ende, erster passender Regex, dann default_server, dann der erste Server für diesen Port.
Wie teste ich auf dem echten Server?
nginx -T gibt die vollständig zusammengeführte Konfiguration aus (alle includes aufgelöst), die Sie hier einfügen können. Für eine Live-Prüfung: curl -sI -H "Host: example.com" http://127.0.0.1/pfad und die Antwort lesen; fügen Sie vorübergehend add_header X-Debug-Location "$uri" hinzu, wenn Sie sehen müssen, welcher Block geantwortet hat.