Come sempre succede, la leggibilità e la facilità possono averci fatto non apprezzare alcuni concetti importanti, che abbiamo subito interiorizzato ma che non abbiamo concettualizzato, un po’ come se, nel passaggio dall’età infantile a quella adolescenziale, ci fossimo trovati subito a pedalare su una bici nuova fiammante, di modello diverso da quello che usavamo fino al giorno prima, e non avessimo fatto attenzione al fatto che i freni sono di tipo diverso, sui pedali si può fare un po’ meno forza, etc, etc ...
Partiamo quindi con alcuni concetti fondamentali
In Nginx, ogni area di competenza delle nostre definizioni è definita da parentesi graffe. Possono quindi essere logicamente separate o innestate più aree di competenza nei nostri file di configurazione, e ognuna sarà ben separata dall’altra da parentesi graffe.
La separazione o l’innestamento di aree diverse diventa così molto facile da comprendere a una prima occhiata. Ogni “area di competenza” è definita Context.
Data questa bellissima definizione, mi correggo già un po’ partendo dal primo context, il Main
Main Context
Il main context infatti è al di fuori delle parentesi graffe e definisce un primo livello di astrazione dal “fuori” al “dentro”
# Il main context è qui, oltre le frontiere delle nostre amate graffe
. . .
user www www; ## attenzione a questo parametro, definisce quale user gruppo può eseguire
worker_processes 1; ## valore di default
context {
# . . .questo è tecnicamente un context
}
Nel main context sono definite le direttive che implicano direttive globali inerenti l’applicativo che andiamo a settare. Le direttive più tipiche, sono user e gruppo a cui è permesso eseguire l’applicativo o direttive che affinano l’utilizzo della cpu.
Event Context
Partiamo a descrivere questo context molto particolare, precisando che ce ne può essere solo uno. Qui vengono definite (se dobbiamo o vogliamo fare un lavoro di fino) meglio alcune particolarità uii worker process e definire quindi alcuni parametri sulla loro gestione delle connessioni.
Potreste trovare un articolo molto interessante su questi aspetti qui:
events {
# events context
worker_connections 1024; #valore che possiamo definire di default
}
HTTP Context
Usando Nginx come web server e/o proxy server il context http racchiude un bel po’ di configurazioni, anche innestate in altri blocchi, che definiscono come l’applicativo deve comportarsi con connessioni http e https
http {
# http context
#. . .
}
È una buona idea definire dentro il context http access e error log, il tipo di compressione dei file, che probabilmente sarà gzip, e altre definizioni sui tempi considerati giusti per tenere attive le connessioni, etc, etc…
Dentro il http context, troviamo i server context, ecco quindi già una struttura tipica, che magari padroneggiamo benissimo, ma che non abbiamo mai distinto concettualmente in maniera precisa e fine
# main context
#. . .
user www www; ## attenzione a questo parametro, definisce quale user gruppo può eseguire
worker_processes 1; ## valore di default
events {
# events context
worker_connections 1024; #valore che possiamo definire di default
}
http {
# http context
server {
# primo bloccoserver
}
server {
# secondo blocco server
}
}
Ogni blocco server può essere usato per definire un virtual host. Dentro ogni blocco server, come sappiamo, tra le cose che facilmente vi troveremo, possiamo ricordate un listen, che indica su quale porta andiamo a intercettare le richieste e il server_name e cioè il nome del virtual host
server {
listen 80;
server_name sitocasuale.it;
}
server {
listen 443 ssl;
server_name sitocasuale.it;
}
Se già non lo fate o non avete previsto un meccanismo similare, vi consiglierei di mettere come primo blocco server qualcosa di simile
server {
listen 80;
return 404;
}
in questa maniera, se vi sfuggisse un record A settato su un ip sbagliato (specie se siete stati un po’ permissivi sul resto delle configurazioni), non dovreste avere brutte sorprese con domini indesiderati che puntano sul vostro stesso sito.
Veniamo ora al location context.
Location Context
Il location context ci permette di definire con molta precisione e (diciamocelo) creatività il tipo di responso che il web server / proxy server dovrà dare a seconda della richiesta dell’utente.
server {
listen 80;
server_name sitocasuale.it;
location /path {
}
}
Mettiamo per esempio che si voglia definire una risposta standard per il robots.txt, su un sito che per qualche motivo deve avere i robot bloccati.
Possiamo usare tranquillamente
location /robots.txt {
return 200 "User-agent: *\nDisallow: /\n"
}
Ovvero ...
server {
listen 80;
server_name sitocasuale.it;
location /robots.txt {
return 200 "User-agent: *\nDisallow: /\n"
}
}
quando l’utente chiederà quindi http://sitocasuale.it/robots.txt ecco che dall’alto verso il basso, tramite nginx abbiamo definito che su porta 80, per virtualhost sitocasuale.it, alla richiesta del file robots.txt deve essere risposto un 200 con questo contenuto testuale : Disallow : /
In un’ottica di ripasso dei concetti fondamentali, che come ci siamo detti magari abbiamo interiorizzato ma che potremmo non avere chiaro quanto dovremmo, analizziamo queste quattro modalità.
Prefix match
location /test1 { return 200 "ciao solo per 1”; }
entra in gioco con sitocasuale.it/test1
Exact match
location =/test1 { return 200 "ciao solo per 1, e sono molto preciso nel cercare esattamente questa combinazione”; }
entra in gioco con sitocasuale.it/test1 prima del prefix match
Regex match case sensitive
location ~ /test[0-9] { return 200 "ciao da 0 a 9, ma attenzione, maiuscole o minuscole non le sento ”; }
entra in gioco con sitocasuale.it/test1 sitocasuale.it/test2 sitocasuale.it/test3 sitocasuale.it/test4 … fino a sitocasuale.it/test9
Regex match case insensitive
location ~* /test[0-9] { return 200 "ciao da 0 a 9, e metti pure le maiuscole, car* ” }
entra in gioco con sitocasuale.it/test1 sitocasuale.it/test2 e tanti altri, basta considerare tutte le combinazioni di numeri e maiuscole/minuscole
Quando si scrivono regole con i location, bisogna fare molta attenzione con le priorità, le regex hanno la priorità, per esempio, sul prefix match.
Non scordiamo in questa sede il
Preferential prefix match
location ~^ /test1 {
return 200 " io sovrasto un po’ le regex, e quindi attenzione a come mi usi ”
}
che in pratica è una forma di prefix match sotto steroidi , che sovrasta le regex.
Quindi, anche se la forma migliore per capire è giocare un po’ con la cosa, possiamo dare questo ordine di priorità
- Exact match
- Preferential prefix match
- Regex match
- Prefix match
Se magari siamo andati a volte un po’ di corsa, non fa male tenersi questo schema da qualche parte, perché altrimenti è facile fare dello spaghetti code, e non sarebbe male, se temiamo su qualche progetto di aver fatto un po’ troppo di fretta, rifattorizzare il tutto.
Attenzione alla complessità
Usando Nginx, a volte sfugge la sua complessità, che ci permette quasi di programmare, dato l’uso (per esempio) degli if e delle variabili, che potremmo affrontare nel prossimo articolo.
Un tipico caso di potenzialità da comprendere sono rewrite, che possono essere usate sia come redirect che come rewrite.
Redirect
rewrite ^/ciao.html https://sitocasuale.it/verociao/ permanent;
location /verociao
{
return 200 "come noti cambia url";
}
o che possono essere usate in maniera molto interessante, per reindirizzare internamente le richieste.
Rewrite
rewrite ^/ciao.html /verociao;
location /verociao
{
return 200 "come noti non cambia url";
}
Nel primo caso abbiamo un cambio di url in cima, nel secondo il cambiamento è tutto interno e non sta a me dire ovviamente la potenza della cosa.
Ci sono tante cose da dire su Nginx e sul doverlo studiare con attenzione per sfruttarlo al meglio, rimanete su questi canali per altre piccole disamine di questo fantastico strumento!