Come faccio a capire quale location ha selezionato nginx?
Incolla la configurazione e l'URI della richiesta in questo tester per vedere il blocco vincente e il motivo per cui ogni altro blocco è stato eliminato. Su un server in esecuzione, aggiungi error_log /var/log/nginx/debug.log debug; e cerca la riga "using configuration", che nomina la location selezionata. I due approcci rispondono a domande diverse: il log dice che cosa ha fatto un server vivo, questa pagina dice che cosa farebbe una configurazione che non hai ancora messo in produzione.
Perché la mia espressione regolare in una location nginx non funziona?
Di solito per uno di tre motivi, e la tabella delle decisioni dice quale. Una regex precedente ha già corrisposto, quindi la tua non è mai stata eseguita — le regex si provano nell'ordine del file e vince la prima corrispondenza. Oppure il prefisso corrispondente più lungo porta ^~, che salta del tutto la fase delle regex. Oppure la regex va bene ma l'URI non è quello che pensi: la corrispondenza gira sul percorso normalizzato, dopo la decodifica delle percentuali e la risoluzione di .., con la query string rimossa.
Perché la mia corrispondenza esatta non scatta?
Una location = richiede che l'intero URI sia uguale, non che inizi con il pattern. location = /a/ non corrisponde a /a, e location = /a non corrisponde a /a/b. Qui le barre finali sono caratteri ordinari, quindi le due forme sono stringhe diverse. Quando una location esatta corrisponde, la ricerca si ferma subito e nient'altro viene nemmeno confrontato.
nginx confronta la query string in un blocco location?
No. La query string viene separata durante la normalizzazione e la selezione della location gira solo sul percorso. Ecco perché location = /a corrisponde a una richiesta per /a?x=/b. Se devi ramificare su un parametro devi leggere $arg_name o $args dentro il blocco. Una sottigliezza che vale la pena conoscere: %3F si decodifica in un punto interrogativo letterale che resta nel percorso, quindi /a%3Fx=1 ha una query string vuota e un percorso che contiene ?.
Posso usare la sintassi delle regex di JavaScript in una location nginx?
No — nginx usa PCRE, e le differenze contano. Questa pagina gira nel tuo browser, dove esistono solo le espressioni regolari ECMAScript, quindi i costrutti esclusivi di PCRE vengono rilevati e segnalati invece che valutati male in silenzio: gruppi atomici, quantificatori possessivi, modificatori inline come (?i), classi POSIX come [[:alpha:]] ed escape come \A e \K che JavaScript legge tranquillamente come lettere ordinarie. Quando una location viene segnalata, i candidati restanti vengono comunque valutati nell'ordine di nginx, ma il verdetto di quel blocco va verificato su un server reale. Se stai scrivendo il pattern in sé, il tester di espressioni regolari copre a fondo la sintassi ECMAScript. Le corrispondenze per prefisso delle location nginx distinguono maiuscole e minuscole?
Su Linux sì — location /Static/ non corrisponde a /static/x. Su filesystem che non distinguono maiuscole e minuscole, come macOS e Cygwin, nginx confronta i prefissi senza distinguerle e in più forza ogni location a regex a comportarsi come ~*. Questa pagina modella il comportamento di Linux, che è quello che i server di produzione eseguono quasi sempre. Se sviluppi su Mac e rilasci su Linux, quella differenza può nascondere una regola rotta finché non va in produzione.
try_files cambia quale blocco location è stato selezionato?
No. La selezione della location finisce per prima; try_files gira dopo, dentro il blocco che ha già vinto. Se una richiesta non raggiunge mai il blocco che contiene il tuo try_files, la direttiva è irrilevante — la causa abituale è una regex ~ \.php$ che prende la richiesta prima che il blocco a prefisso con il fallback possa agire. Un redirect interno emesso più tardi fa ripartire la corrispondenza, quindi un URI riscritto viene risolto di nuovo sulla lista delle location, dall'inizio.
Perché nginx risponde 301 quando chiedo una directory senza barra?
A produrlo sono due meccanismi diversi. Se una location il cui nome finisce con / porta proxy_pass o un'altra direttiva *_pass, una richiesta per lo stesso percorso senza barra riceve un 301 durante la selezione della location — prima che venga valutata qualsiasi regex. A parte questo, il modulo dei file statici emette un 301 quando il percorso si risolve in una directory reale su disco. Il primo caso è visibile qui; il secondo dipende dal tuo filesystem. Aggiungere location = /path sopprime il primo.
I blocchi location annidati cambiano il risultato?
Sì, e in un modo facile da farsi sfuggire. nginx scende dentro la location a prefisso vincente e cerca tra i suoi figli, quindi una regex annidata viene provata prima delle regex del livello superiore. Un ^~ sul blocco esterno non lo protegge dalle regex annidate al suo interno, e l'annidamento può rendere irraggiungibile un prefisso globalmente più lungo quando un fratello del livello esterno vince per primo. Qui i blocchi annidati sono modellati con la stessa indentazione con cui li hai scritti.
La mia configurazione nginx viene caricata da qualche parte?
No. Il parsing e la corrispondenza avvengono in locale nel tuo browser con semplici operazioni su stringhe — non c'è nessuna chiamata al server e non viene conservato niente. Qui conta più che per la maggior parte degli strumenti, perché un vero blocco server contiene hostname di upstream, porte interne, percorsi dei certificati e regole di autenticazione. Non devi crederci sulla parola: apri gli strumenti per sviluppatori del browser e guarda il pannello Network restare in silenzio mentre digiti, oppure disconnettiti del tutto e continua a provare. L'assenza di qualsiasi richiesta esterna è anche imposta da un test di contratto automatico a ogni build, quindi non può regredire di nascosto.