Chiunque, e sottolineo chiunque, gestisca un sito web, prima o poi dovrà fare i conti (ma sono certo sia già successo) con l’ostico mondo delle rewrite, delle redirect e dei proxypass. Ed è a quel punto che scatterà la ricerca infernale su vecchi files di configurazione, o la caccia su Google, della stringa magica che fa al nostro caso e che risolverà (speriamo) tutti i nostri problemi.In questo articolo del blog parleremo quindi di Apache httpd rewrite con esempi di redirect e proxypass.
Che si tratti di cambiare il path di una pagina, di togliere il www dal nostro dominio, o di riscrivere in HTTPS il traffico HTTP, le forche caudine del RewriteEngine sono li ad aspettarvi.
Apache httpd rewrite esempi – Let’s go!!!
Alla base del funzionamento della riscrittura delle URL c’è un modulo di Apache che si chiama mod_rewrite. Cerchiamo di capire cos’è e cosa fa.
Cos’è il mod:Rewrite?
Il termine “mod_rewrite” si riferisce a un modulo per il server Web Apache, che “riscrive” o reindirizza le richieste del client al contenuto richiesto. Fondamentalmente, il modulo trasforma le richieste in arrivo tramite il browser in un path che punta a un file nel file system del server web. Grazie al mod_rewrite è quindi possibile “riscrivere” una URL. A tal fine viene definita una “RewriteRule”, che controlla questa riscrittura e si realizza con l’ausilio di espressioni regolari.
Entriamo nel vivo della discussione e vediamo come si attiva il mod_rewrite e come si scrivono le regole di riscrittura più comuni.
Come attivare il mod_rewrite su apache
Il mod_rewrite è un semplicissimo modulo di apache, già disponibile nel pacchetto base (per cui non è necessario compilarlo). Per attivarlo sarà sufficiente cercare all’interno del file di configurazione di apache, httpd.conf, la seguente stringa:
# LoadModule rewrite_module modules/mod_rewrite.so
HTTPUna volta trovata la stringa, eliminiamo il commento (#) da inizio riga.
La nuova configurazione sarà la seguente:
LoadModule rewrite_module modules/mod_rewrite.so
HTTPRiavviando il servizio httpd, il modulo sarà pronto per essere utilizzato e potremo iniziare a scrivere le nostre regole!!!
Per pulizia e smania di ordine, è mia abitudine creare un file esterno ai soliti files di configurazione, all’interno del quale inserisco tutte le regole, in modo da mantenere il più possibile vicini all’originale, i files di configurazione nativi.
Solitamente creo un file dedicato alle rewrites all’interno della cartella conf del nostro apache e lo includo nel file di configurazione:
Include conf/rewrites.conf
HTTPAll’interno del file inserirò tutte le mie rewrites. La prima riga da inserire nel file è l’abilitazione del modulo di rewrite che abbiamo attivato prima:
RewriteEngine on
HTTPSotto questa prima riga possiamo iniziare a scrivere tutte le regole di cui abbiamo bisogno.
Un’alternativa alla creazione di un file dedicato alle rewrite è quella di inserire tutte le nostre regole all’interno del file .htaccess. Dal punto di vista funzionale non cambia nulla. La differenza grande sta invece nelle performance. Inserendo le regole nel file di configurazione, le nostre regole verranno caricate in memoria al primo riavvio, con benefici in termini di velocità. Il file .htaccess invece, viene letto ad ogni chiamata che arriva al webserver. Ciò significa che per ogni chiamata in ingresso, il web server deve leggere il file con le relative regole, capire se attuarle, e poi si passa finalmente all’attuazione vera e propria. Lascio a voi le considerazioni :).
Ovviamente non risentiremo di ciò su un sito web che riceve poco traffico. Ma su un sito enterprise, con una grossa mole di visitatori, è fortemente sconsigliato l’utilizzo del file .htaccess.
Apache httpd rewrite esempi redirect proxypass e use cases
Iniziamo a fare qualche esempio di uso comune, in modo da spiegare anche il significato dei FLAGS, che sono fondamentali per un corretto funzionamento delle regole.
RewriteEngine on
RewriteRule ^mypage$ mypage.html [NC]
HTTPIn questo esempio, ^mypage$ è il pattern, mentre mypage.html è la sostituzione, e [NC] è il flag. Leggendo la regola noterete che sono presenti alcuni caratteri “particolari”, che andiamo a spiegare di seguito e che saranno utili negli esempi successivi:
- ^ indica l’inizio della nostra URI, ovvero tutto quello presente dopo il dominio.
- $ Indica la fine della URI interessata dalla regola .
- mypage è la stringa da matchare.
- mypage.html è il file presente sul file system a cui accederà il visitatore.
- [NC] significa “No Case sensitive” e fa si che la regola non faccia differenze tra maiuscole e minuscole
A questo punto potremo testare la nostra regole scrivendo sulla barra degli indirizzi del browser http[s]://TUODOMINIO/mypage. La regola farà in modo che la url digitata punti al file mypage.html:
- http[s]://TUODOMINIO/mypage – funzionerà perché fa il match esatto con la regola
- http[s]://TUODOMINIO/Mypage – funzionerà perché la regole è case insensitive
- http[s]://TUODOMINIO/mypage.html, funzionerà perché la pagina reale presente sul file system sarà sempre raggiungibile
La regola invece non funzionerebbe se chiamassimo:
- http[s]://TUODOMINIO/mypage/ perché abbiamo esplicitato chiaramente che la nostra regola (grazie al $) termina con la stringa mypage e non prende in considerazione quello che c’è dopo.
- http[s]://TUODOMINIO/homepage, perché non fa match con la stringa “mypage” presente nella regola.
Ora che abbiamo un’idea generale di come funziona una regola di rewrite, vediamo qualche altro esempio pratico
ESEMPIO DI REWRITE CAMBIO DOMINIO
Il nostro sito TUODOMINIO.com deve cambiare nome in NEWDOMAIN.IT:
RewriteCond %{HTTP_HOST} ^TUODOMINIO.com$ [OR] RewriteCond %{HTTP_HOST} ^www.TUODOMINIO.com$ RewriteRule (.*)$ https://www.NEWDOMAIN.com/$1 [R=301,L]
Abbiamo introdotto alcune nuove componenti:
- RewriteCond è la condizione che deve verificarsi affinché la RewriteRule venga applicata. Equivale quindi a una IF.
- %{HTTP_HOST} è l’FQDN richiamato. Quindi la prima riga significa: Se l’FQDN richiamato sarà TUODOMINIO.COM
- $1 è una variabile e serve a mantenere invariata la URI richiesta. Se per esempio chiamassimo https://TUODOMINIO.COM/contatti.html o https://www.TUODOMINIO.COM/contatti.html, la chiamata verrà ridiretta su https://www.NEWDOMAIN.com/contatti.html. L’utilizzo delle variabili è fondamentale quando, nel cambiare il nome del dominio, restano invece invariate i contenuti e i relativi nomi delle pagine.
Apache httpd rewrite esempi di dettaglio
Altra opzione di redirezione del traffico per cambio domini è la seguente:
Redirect 301 / https://www.NEWDOMAIN.com/
Qui però non manteniamo la URI richiesta e tutto il traffico andrà sempre nella home del nuovo dominio.
Se chiamassimo https://TUODOMINIO.COM/contatti.html, verremmo rediretti su https://www.NEWDOMAIN.com. Come vedete, la URI contatti.html viene persa. Questo accade perchè nella regola non è presente la variabile $1 (che abbiamo visto nell’esempio precedente).
Questo può essere utile soltanto se non ci interessa mantenere attivi i contenuti del vecchio sito.
Organizing websites is highly dynamic and often chaotic. Thus, it is crucial that host web servers manipulate URLs in order to cope with temporarily or permanently relocated resources, prevent attacks by automated worms, and control resource access.
The Apache mod_rewrite module has long inspired fits of joy because it offers an unparalleled toolset for manipulating URLs. The Definitive Guide to Apache mod_rewrite guides you through configuration and use of the module for a variety of purposes, including basic and conditional rewrites, access control, virtual host maintenance, and proxies.
Acquista Introduction to Apache mod_rewrite (English Edition) online su amazon
REDIRECT DI UNA SINGOLA PAGINA O DI UN SINGOLO FILE
Redirect /path/old/file/oldfile.html /path/new/file/new.html
# oppure, altro esempio
Redirect /contatti.html /contattaci.html
HTTPQuesta modalità di redirect si applica principalmente quando vogliamo cambiare il nome di una pagina, mantenendo però al suo interno gli stessi contenuti.
Senza questa regola, tutte le persone abituate a visitare questa pagina, magari grazie a un bookmark, riceverebbero un errore 404. Con la regola invece, pur chiamando contatti.html, che magari non esiste più, si viene rediretti automaticamente sul nuovo contenuto offerto dalla pagina contattaci.html.
REDIRECT DI UNA PAGINA SU UNA PAGINA DI UN SITO ESTERNO
Redirect /oldfile/oldfile.html https://www.example.com/newfile/newfile.html
HTTPQuesto codice risponderà con una redirect 302, ovvero con una redirect temporanea. Nel caso in cui volessimo farla diventare definitiva, ovvero una redirect 301, sarà sufficiente scrivere:
Redirect <strong>301</strong> /oldfile/oldfile.html https://www.example.com/newfile/newfile.html
HTTPAlcune precisazioni su quest’ultimo esempio.
Il primo path, ovvero quello del vecchio file (/oldfile/oldfile.html), deve essere un percorso UNIX locale e relativo, NON il percorso assoluto. Quindi, se la tua docroot si trova nella directory /home/username/htdocs, non dovrai includere il path completo (assoluto). Il primo “/” infatti rappresenta la directory della docroot, ovvero /home/username/htdocs. Pertanto il file /path/oldfile/oldfile.html indicato nella regola, sarà presente sul file system al path: /home/username/htdocs/oldfile/oldfile.html, ma noi lo richiameremo nella regola con /oldfile/oldfile.html.
Il secondo percorso (quello relativo alla destinazione) può essere un percorso UNIX locale, ma può anche essere un URL completo, per collegarsi a una pagina su un server diverso, o sullo stesso server. Come potete vedere infatti, la regola ha come destinazione https://….. e non un path locale, che invece inizierebbe con /… (senza https://).
REDIRECT DA UNA CARTELLA A UN FILE HTML CON REDIRECTMATCH
RedirectMatch 301 ^/blog/about /blog/about.html
HTTPn questa regola abbiamo introdotto una nuova variabile, ovvero quel 301 che vedete dopo RedirectMatch. Quel 301 rappresenta il response code http che il webserver invia al client. 301 significa Permanently Moved, ovvero “spostato definitivamente”. Ciò significa che il browser si salverà questa risposta del webserver e alla successiva chiamata alla vecchia pagina, farà automaticamente la riscrittura, senza chiedere la vecchia pagina al server.
REDIRECT DA DEFAULT.HTML A INDEX.HTML
Redirect /default.html /index.html
HTTPREWRITERULE DA VECCHIA DIRECTORY A NUOVA DIRECTORY
RewriteRule ^blog/archives/(.*)$ /newarchives/$1 [R=301,NC,L]
HTTPIn questo esempio ritroviamo il $1. Ciò significa che ogni volta che nel browser scriveremo /blog/archives/*, verremo rediretti al path /newarchives/*.
Esempio pratico:
Chiamo https://MIOSITO.NET/blog/archives/biblioteca.html e verrò ridiretto su https://MIOSITO.NET/newarchives/biblioteca.html.
REDIRECT DI PAGINE NON ESISTENTI, VERSO LA HOME (es. index.php)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
HTTP!-f – se il file richiamato non esiste
!-d – se la directory richiamata non esiste
RIDIRIGIAMO GLI ERRORI 404 SU UNA PAGINA SPECIFICA
ErrorDocument 404 https://example.com/404.html
HTTPOvviamente possiamo usare questa regola anche per tutte le altre pagine di errore come le 500 o le 502.
ErrorDocument 502 https://example.com/502.html
HTTPFORZIAMO L’USO DEL WWW
RewriteCond %{HTTP_HOST} ^example.com
RewriteRule (.*) https://www.example.com/$1 [R=301,L]
HTTPChiamando example.com, il server risponderà al cliente con una rewrite permanente (301) verso www.example.com
RIMUOVIAMO IL WWW
RewriteCond %{HTTP_HOST} ^www.example.com
RewriteRule (.*) https://example.com/$1 [R=301,L]
HTTPQuesta regola fa l’esatto opposto della precedente.
FORZIAMO L’HTTPS CON UNA REWRITE PER TUTTO IL TRAFFICO
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
Header always set Content-Security-Policy "upgrade-insecure-requests;"
HTTPo in alternativa
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L,NE]
Header always set Content-Security-Policy "upgrade-insecure-requests;"
HTTPIn questo secondo esempio dobbiamo ricordarci di cambiare www.example.com con l’FQDN del nostro dominio. La prima regola invece è completamente dinamica.
RENDIAMO STATICA UNA URL DINAMICA
RewriteRule ^([0-9]+).html /abc.php?id=$1 [QSA,L]
HTTPQuesta regola è più complessa delle altre. Proviamo a spiegarla.
Se un cliente chiama http[s]://MIOSITO.COM/unqualunquenumero.html (es 919.html), il nostro server erogherà il contenuto presente in http[s]://MIOSITO.COM/abc.php?id=919.
Questo tipo di regola viene solitamente utilizzata per staticizzare e quindi rendere le URL più semplici da leggere, sia per i clienti che per i motori di ricerca (SEO. Discorso che prima o poi affronteremo in futuro. Anche il 301 affrontato finora è fondamentale per il SEO. Ne parleremo). D’altro canto è molto più semplice scrivere https://miosito.com/919.html che https://miosito.com/abc.php?id=919.
Vi faccio un altro esempio. Pensate a un catalogo di abbigliamento. E’ più facile scrivere:
https://miosito.com/it/scarpe/uomo/mocassini.html
oppure
https://miosito.com/catalogo.php?category=scarpe&sgenere=uomo&type=mocassini
Ci siamo risposti 😍 Questa tipologia di regola serve proprio a questo.
Entriamo nel dettaglio della regola.
([0-9]+) – qualunque numero.
([a-z-]*) qualunque lettera minuscola, più il “-” come separatore. Se invece volete supportare anche le lettere maiuscole, allora dovrete usare “([a-zA-Z-]*). Per esempio:
RewriteRule ^place/([a-zA-Z-]*).html /place/abc.php?id=$1 [QSA,L]
HTTP[QSA,L] Query String Append aggiunge il paramento inviato come query string. La “L” invece significa Last Rule e blocca l’esecuzione di tutte le regole successive.
ESPONIAMO UN FILE POSIZIONATO IN PATH DIVERSO DA QUELLO RICHIAMATO
RewriteCond %{REQUEST_URI} ^/robots.txt
RewriteRule ^/(.*) /static/robots/robots.txt [PT,NC,L]
HTTPQuesto può essere utile se per qualche motivo non abbiamo possibilità di inserire il robots.txt nella root della nostra docroot.
Blocchiamo spider, crawler, user agents e bots
Per bloccare uno spider, un crawler, uno specifico user agents o un particolare bot, vi consiglio la nostra guida Apache bloccare bot e user agent con mod_rewrite
PROXYPASS PER CHIAMATE VERSO UN SISTEMA INTERNO NON ESPOSTO SU INTERNET
ProxyPass /login http://10.10.10.10/login
ProxyPassReverse /login https://10.10.10.10/login
HTTPQuesta configurazione è utile nel caso in cui volessimo esporre su internet un servizio erogato da un nostro server di backend che non è esponibile direttamente su internet.
Nel caso in cui il servizio di backend rispondesse in https (cosa ovviamente consigliata) allora la configurazione da attuare dovrà essere la seguente:
SSLProxyEngine On
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
ProxyTimeout 40 # choose your own config
ProxyPass /login http://10.10.10.10/login
ProxyPassReverse /login https://10.10.10.10/login
HTTPRIMUOVIAMO LE QUERY STRINGS DALLE URI (update 30/11/2022)
Poniamo il caso che abbiamo delle url, indicizzate su google, del tipo:
https://miosito.com/contatti?region=uk
https://miosito.com/contatti?region=usa
Se per qualche motivo le region uk e usa non dovessero più esistere, ma la pagina dei contatti dovesse rimanere la stessa, potrebbe essere utile rimuovere dalle SERP le pagine con le query strings di contatti. Vediamo che tipo di regola attuare:
RewriteCond %{QUERY_STRING} .+
RewriteCond %{REQUEST_URI} (.*)
RewriteRule ^(.*)$ https://miosito.com%{REQUEST_URI} [L,R=302,QSD]
HTTPL e R=302 le abbiamo già analizzate in precedenza.
Abbiamo un nuovo FLAG che si chiama QSD = Query Strings Delete
Le pagine richieste dal visitatore del sito, verranno epurate delle query strings e grazie al paramentro %{REQUEST_URI} verremo rediretti alla pagina richiesta (in questo caso /contatti). La regola è dinamica, pertanto non dovrete preoccuparvi di specificare la pagina di destinazione.
Rimuovere lo slash / dalla fine del PATH
In alcuni casi può risultare utile rimuovere lo / (slash) dalla fine della URL. Per farlo, potete utilizzare questa semplice regola di rewrite:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/+$ $1 [L,R=301]
HTTPApache httpd rewrite esempi – Tools utili
Come avrete notato nell’articolo, molto spesso le nostre regole contengono, anzi devono contenere, delle regular espressions. Molto spesso è proprio la scrittura di queste regole che più ci mette in difficoltà. Le scriviamo, ma non succede quello che ci aspettiamo.
Per risolvere Ci sono alcuni tools utili presenti sul web, attraverso i quali è possibile testare le nostre regular espressions. Quello che uso più spesso e che trovo estremamente utile è senza dubbio https://www.regextester.com.
Tra le utility che mette a disposizione c’è anche un mini riassunto delle Top Regular Expressions:
Cheat Sheet
Character classes
. any character except newline
\w \d \s word, digit, whitespace
\W \D \S not word, digit, whitespace
[abc] any of a, b, or c
[^abc] not a, b, or c
[a-g] character between a & g
Anchors
^abc$ start / end of the string
\b word boundary
Escaped characters
\. \* \\ escaped special characters
\t \n \r tab, linefeed, carriage return
\u00A9 unicode escaped ©
Groups & Lookaround
(abc) capture group
\1 backreference to group #1
(?:abc) non-capturing group
(?=abc) positive lookahead
(?!abc) negative lookahead
Quantifiers & Alternation
a* a+ a? 0 or more, 1 or more, 0 or 1
a{5} a{2,} exactly five, two or more
a{1,3} between one & three
a+? a{2,}? match as few as possible
ab|cd match ab or cd
Bloccare i bot tramite mod_rewrite
Qualora vogliate mettere in sicurezza il vostro sito web, bloccando i bots e user agents indesiderati, vi lascio il link al mio tutorial dedicato al blocco dei bots tramite mod_rewrite.
Apache httpd rewrite esempi redirect proxypass Video Tutorial
Vi condivido quest’utile tutorial presente su Youtube. Il video è veramente completo, con oltre 2 ore di lezione.
Apache httpd rewrite esempi -Conclusioni
Chiaramente, questa voleva essere soltanto un’introduzione al troppo vasto mondo delle regole di rewrite e delle regular espressions che la fanno da padrone in quest’ambito. Spero che questa piccola infarinata generale possa essere d’aiuto a qualcuno di voi. Sicuramente lo sarà per me, che correrò qui a fare copia/incolla quando ne avrò bisogno 😆.
Mi impegnerò ad aggiungere altri esempi man mano che mi capiteranno nel lavoro di tutti i giorni. Se vorrete aggiungerne altri, vi invito a commentare l’articolo. Provvederò ad aggiornarlo con le vostre indicazioni.
Anche ulteriori risorse di test potrebbero essere utili. Pertanto, se avete altre risorse da segnalare, utilizzate semper i commenti 😂.
Condividete se l’articolo vi è sembrato interessante. 😊
Il confronto è sempre costruttivo.
I wish you a funny job
Fabio Iegri
Vi lascio il link di questa newsletter qualora vogliate iscrivervi: https://www.linkedin.com/newsletters/web-in-cloud-6945274376917274624/
Principal Web Solutions Architect – Technology & Architecture Manager @ Accenture – Google Cloud Certified – Professional Cloud Architect
Parla di #web, #cloud, #websecurity, #webperformance e #webarchitecture