Come nginx sceglie una location
- L’URI viene prima normalizzato: decodifica percentuale, barre ripetute unite,
.e..risolti. La query string non fa mai parte della corrispondenza delle location. - Vengono confrontate tutte le location a prefisso (senza modificatore,
=,^~). Una corrispondenza esatta=vince subito. Altrimenti viene ricordato il prefisso corrispondente più lungo. - Se quel prefisso più lungo ha
^~, vince e le regex vengono saltate. - Le location regex (
~sensibile alle maiuscole,~*insensibile) vengono provate nell’ordine in cui compaiono nel file. La prima che corrisponde vince, anche se prima aveva corrisposto un prefisso più lungo. - Se nessuna regex corrisponde, viene usato il prefisso più lungo ricordato.
- Dentro la location vincente la stessa procedura viene eseguita di nuovo per le location annidate.
Due conseguenze sorprendono di più: una semplice location /images/ perde contro location ~ \.png$ per /images/a.png, perché le regex vengono controllate dopo i prefissi; e location /api corrisponde anche a /apiary, perché i prefissi sono prefissi di stringa, non segmenti di percorso. Usa /api/ o ^~ quando è ciò che intendi.
proxy_pass e la barra finale
Se proxy_pass ha una parte URI (qualsiasi cosa dopo l’host, anche solo /), nginx sostituisce con essa la parte dell’URI della richiesta che ha corrisposto al prefisso della location. location /api/ { proxy_pass http://app/; } trasforma /api/users in /users. Senza parte URI, l’URI della richiesta passa invariato. Barre non coerenti (/api contro /api/, o http://app contro http://app/) producono //users o users — il tester stampa l’URI upstream esatto così puoi vederlo. Una parte URI non è ammessa in una location regex a meno che un rewrite non abbia prima cambiato l’URI.
root contro alias
root aggiunge l’intero URI alla directory: root /srv; location /static/ serve /srv/static/x.css. alias sostituisce il prefisso della location: alias /srv/assets/; location /static/ serve /srv/assets/x.css. Con alias le barre finali della location e dell’alias devono concordare, e in una location regex alias deve usare le catture.
Flag di rewrite
| Flag | Effetto |
|---|---|
| last | interrompe l’elaborazione dei rewrite, ricomincia la corrispondenza delle location con il nuovo URI (max 10 volte, poi 500) |
| break | interrompe i rewrite, resta nella location corrente con il nuovo URI |
| redirect | invia un 302 al client |
| permanent | invia un 301 al client |
| (nessuno) | continua con il rewrite successivo; a livello di server il risultato viene poi confrontato con le location |
try_files
Ogni argomento viene controllato come file (o directory, con una barra finale) relativo a root/alias; il primo che esiste viene servito. L’ultimo argomento è il fallback e non viene controllato: è un redirect interno a un URI (che passa di nuovo per la corrispondenza delle location), una location con nome @nome, o un codice di stato in stile =404. Il tester non può vedere il tuo filesystem, quindi elenca i percorsi che verrebbero controllati.
Ereditarietà di add_header
add_header viene ereditato dal livello server solo quando la location non ha alcun add_header proprio. Un solo add_header Cache-Control in una location elimina silenziosamente gli header di sicurezza impostati a livello di server. La traccia lo segnala.
Domande
Supporta l’intera sintassi di configurazione di nginx?
Il parser gestisce la sintassi reale: blocchi annidati, commenti, stringhe tra virgolette, argomenti regex; le direttive include vengono elencate ma non seguite (incolla anche il file incluso). Le variabili diverse da $uri, $request_uri, $args e le catture regex restano come testo, e i blocchi «if» vengono mostrati ma non valutati.
Perché la mia regex si comporta diversamente in nginx?
nginx usa PCRE; questa pagina usa le espressioni regolari JavaScript. Concordano su quasi tutto ciò che si usa nei blocchi location, ma quantificatori possessivi, ricorsione e alcune forme di lookbehind differiscono. La traccia dice quando una regex non ha potuto essere compilata.
Può verificare quale blocco server risponde per un Host?
Sì. Incolla più blocchi server e compila il campo Host. La selezione segue nginx: nome esatto, wildcard più lunga che inizia con *, wildcard più lunga che finisce con *, prima regex corrispondente, poi default_server, poi il primo server per quella porta.
Come faccio la prova sul server reale?
nginx -T stampa l’intera configurazione unita (tutti gli include risolti) che puoi incollare qui. Per una verifica dal vivo, curl -sI -H "Host: example.com" http://127.0.0.1/percorso e leggi la risposta; aggiungi temporaneamente add_header X-Debug-Location "$uri" se devi vedere quale blocco ha risposto.