Come avevo promesso ho preparato una miniguida su mod_rewrite.
Purtroppo, come si conviene in questi casi windows ha avuto la bella idea di mandarmi a donnine allegre mezzo disco fisso per cui ora mi trovo a dover riformattare e reinstallare tutto da capo
Avevo preparato qualche esempio in più ma questo è quello che sono riuscito a recuperare.
Ho deciso così di dividere la guida in diverse tranche.
In questa parte solo i concetti introduttivi di mor_rewrite con due o tre esempi basilari. Appena finisco di reinstallare mi rifaccio la parte sulle espressioni regolari e gli altri esempietti che mi ero preparato (se me li ricordo ancora
)
Intanto ecco quello che è rimasto della guida
Guida a mod_rewriteParte 1: concetti introduttiviVediamo di chiarire un poco come sfruttare apache e il modulo mod_rewrite.
1. cosa è mod_rewritemod_rewrite è un modulo di apache, ovvero un "aggeggio" del programma che rende disponibile il vostro sito su internet che ha come scopo, quello di prendere l'indirizzo digitato dall'utente (URL) e trasformarlo secondo precise regole.
Pensatelo un po' come il traduttore di google: voi inserite una parola e lui vi da la traduzione in un'altra lingua.
Nel caso di mod_rewrite non abbiamo la traduzione da una lingua all'altra, ma da un indirizzo web all'altro
2. perchè usare mod_rewriteTre sono le ragioni principali che possono spingere ad utilizzare mod_rewrite
a) indirizzi del tipo
http://www.sito.it/index.php?page=7 non sono molto graditi ai motori di ricerca (in particolare a google), e quindi in presenza di indirizzi di questo tipo il nostro sito potrebbe non essere indicizzato completamente
B) tramite mod_rewrite è possibile semplificare un po' alcuni indirizzi difficilmente memorizzabili
c) l'utente non viene a conoscenza della struttura effettiva del sito
3. come funziona mod_rewriteSenza entrare nel dettaglio tecnico di come funziona mod_rewrite (spiegato per bene
qui) diciamo che il funzionamento è questo
a) l'utente digita nel browser l'indirizzo
B) quando schiaccia invio viene fatta un richiesta al webserver
c) apache controlla l'indirizzo con le regole definite in un file apposito per cercare eventuali istruzioni su come comportarsi
d) se trova una regola adatta prende la pagina richiesta (che solitamente è diversa da quella digitata dall'utente) e la invia al browser del navigatore
4. prerequisitiPrima di gettarci a capofitto negli esempi, è importantissimo prestare attenzione a due cose
a) il modulo mod_rewrite deve essere caricato (altrimenti apache non si sogna minimamente di gestire le "regole" che gli scriveremo)
B) se non esiste, va creato un file .htaccess nella root del vostro sito in cui vanno inserite queste direttive
RewriteEngine On
Options +FollowSymlinks
RewriteBase /
La prima riga dice ad apache di attivare la funzionalità di riscrittura degli URL (ovvero quello che andremo a sfruttare noi nei nostri esempi). La seconda riga indica ad apache di seguire i link simbolici (praticamente sono i collegamenti di windows sotto linux, con qualche differenza).
A questo punto siete pronti per dare uno sguardo agli esempi
5. esempiIn questa sezione riporto alcuni esempi, e di volta in volta introdurrò elementi più complicati (almeno per quanto mi permette la conoscenza che ho di mod_rewrite)
5.1. da index.htm a index.phpNote: la pagina index.php sul nostro sito non esiste
Scopo: l'utente digita
http://www.sito.it/index.php e non vogliamo che riceva un errore di pagina non trovata
I motivi per applicare una tecnica del genere possono essere molteplici. Ad esempio potremmo aver preparato un sito in php, ma ora ci siamo trasferiti su un sito che non supporta php e vogliamo che l'utente non sia costretto ad aggiornare i propri segnalibri
Per fare questo andiamo ad editare il file .htaccess e scriviamo
RewriteRule ^index.php$ index.htm
Cosa fa questa riga del .htaccess? Allora
RewriteRule è una parola riservata, che dice ad apache che quella che segue è una regola per riscrivere un indirizzo. Il primo argomento della RewriteRule è l'indirizzo che l'utente digita nel suo browser (quindi qualcosa che contiene index.php) e il secondo argomento è invece la traduzione. In pratica questa riga dice ad apache che, qualora l'utente digiti l'indirizzo
http://www.sito.it/index.php la pagina che deve caricare e mandare all'utente è
http://www.sito.it/index.htm.
5.2. mascheramento di querystring Note: le querystring sono quelle parti dell'indirizzo di una paginaa che seguono il ? e solitamente sono i parametri da passare alla pagina perchè venga svolto qualche compito
Scopo: l'utente digita
http://www.sito.it/index.php/news.htm. In realtà l'indirizzo è del tipo
http://www.sito.it/index.php?sezione=newsAncora una volta dobbiamo editare il file .htaccess e inserirvi quanto segue
RewriteRule ^index.php/(.*)\.htm$ index.php?sezione=$1
Questa regole è leggermente più complicata della precedente. Analizziamola pian piano.
RewriteRule è la solita parola chiave riservata.
^index.php/(.*)\.htm$ dice ad apache di considerare tutti quegli URL che iniziano con index.php, hanno poi una slash (/) e quindi un qualcosa tipo news.htm. Il codice (.*) appartiene all'ambito delle espressioni regolati e vuol dire: considera qualsiasi carattere (.) ripetuto per un numero arbitrario di volte (*) e rendilo una "variabile" (le parentesi tonde).
index.php?sezione=$1 indica ad apache di trasformare l'URL in index.php?sezione=news. Il simbolo $1 (tecnicamente chiamato back-reference), vuol praticamente dire di sostituire in quel punto il valore della prima variabile creata precedentemente con il codice (.*)
5.3. problema dei link relativiNote: supponiamo di avere una struttura del sito simile alla seguente
root
+--strumenti [directory]
| +--login.php [file per il login all'area riservata]
+--index.php [index del sito]
+--cancella.php [script per cancellare il contenuto dell'archivio]
e non volere che l'utente debba digitare come indirizzo
http://www.sito.it/strumenti/login.php?id=123, sia perchè non vogliamo rendere noto che la pagina login.php accetta un parametro di nome id con un valore numerico, sia perchè vogliamo che google possa indicizzare anche la nostra pagina login.php
Scopo: vogliamo che l'utente digiti qualcosa del tipo
http://www.sito.it/login/123Aggiungiamo in .htaccess una regola RewriteRule come la seguente
RewriteRule ^login\/(.*)$ strumenti/login.php?id=$1
Come abbiamo visto nell'esempio 5.2. qui c'è il codice (.*) che "crea una variabile" e il valore di questa variabile sarà poi sostituito a $1.
Questa regola, seppur corretta sintatticamente è abbastanza "debole" per quanto riguarda la sicurezza.
Supponiamo infatti che un utente digiti
http://www.sito.it/login/ciao_mamma.
Per come abbiamo definito la regola apache (e mod_rewrite) andranno a vedere se c'è una corrispondenza con la regola preparata. login/ c'è nell'URL e c'è anche nella regola che abbiamo scritto noi, quindi questa regola potrebbe essere quella da applicare. Secondo la regola poi, dopo login/ ci dovrebbe essere una stringa ulteriore e nell'URL abbiamo ciao_mamma che va bene, quindi la regola "combacia" con quanto immesso dall'utente come indirizzo e mod_rewrite effettua la sostituzione, andando a puntare alla pagina
http://www.sito.it/strumenti/login?id=ciao_mamma. Come potete notare il problema è che ora l'id passato alla pagina login non è un numero come ci si aspetterebbe ma una "frase". Se il codice di login.php è fatto bene, all'interno ci sarà un controllo che verifica se il valore di id è un numero, altrimenti stampa un messaggio di errore.
Supponiamo anche che questo controllo ci sia, la regola presenta comunque uno svantaggio. In questo caso apache ha dovuto prima effettuare la riscrittura dell'url (operazione "relativamente semplice e rapida"), poi ha dovuto elaborare la pagina login.php e quindi inviare all'utente una pagina con un semplice messaggio di errore: "guarda che l'id doveva essere un numero". Ora immaginatevi questa situazione moltiplicata per 100, 1000, 10.000 pagine. Come potete ben intuire apache è costretto a svolgere un sacco di lavoro inutile solo per visualizzare un messaggio di errore.
E' possibile a tal proposito modificare un poco la RewriteRule in modo da rendere il tutto un po' più efficiente
RewriteRule ^login\/([0-9]{1,10})$ strumenti/login.php?id=$1
Come potete notare, la regola si è fatta appena appena più complessa. La differenza sta in quel ([0-9]{1-10]) che sostituisce (.*). Si intuisce quindi che lo scopo sia lo stesso, ovvero quello di creare una sorta di variabile per permettere poi la sostituzione con $1. Che vantaggio porta l'introduzione di questa miglioria? Apache ora, quando va a controllare l'URL immesso dall'utente non accetta più un indirizzo come il precedente
http://www.sito.it/login/ciao_mamma ma solo indirizzi del tipo
http://www.sito.it/login/XXX dove XXX è un numero. Questo perchè il codice ([0-9]{1,10}) dice che sono ammessi solo i caratteri da 0 a 9 e se ne può trovare solo un numero compreso da 1 e 10. Quindi se l'utente digita
http://www.sito.it/login/ciao_mamma apache troverà prima la corrispondeza tra login/ e la prima parte della regola, poi però noterà che ciao_mamma non rientra nei caratteri ammessi (non sono numeri) e quindi non procederà con la traduzione dell'URL nè tantomeno processerà la pagina login.php. Quindi verrà eseguito solo il confronto per vedere se l'URL immesso "combacia" con la regola.
Inoltre questa regola aumenta anche la sicurezza perchè con la regola precedente utente malizioso avrebbe potuto digitare qualcosa del tipo
http://www.sito.it/login/./../cancella.php e, a seconda poi del contenuto effettivo di login.php, invocare magari lo script cancella.php (ovviamente questo è solo un esempio, un buon controllo sul valore di id all'interno di login.php avrebbe comunque impedito il verificarsi di un simile problema). Invece forzando apache a considerare solo caratteri numeri questo URL non avrebbe subito alcuna riscrittura, ma sarebbe risultato un semplice errore.
5.4. il problema dei link relativi e delle cartelle inesistentiNote: supponiamo di avere una struttura del sito simile alla seguente
root
+--strumenti
| +--visualizza.php
+--immagini
+--vis.gif
A volte capita di scrivere regole del tipo
RewriteRule ^visualizza/(.*)/(.*).htm$ strumenti/visualizza.php?sezione=$1&codicelibro=$2
Con questa regola verrebbo intercettati URL del tipo
http://www.sito.it/visualizza/libri/150 e trasformati quindi in
http://www.sito.it/visualizza?sezione=libri&codicelibro=150.
Una cosa di questo genere, anche se molto bella e utile, ha lo svantaggio però di sballare tutti i link relativi presenti nella pagina.
Se ad esempio nella nostra visualizza.php avessimo un link del tipo !img src="./../immagini/vis.gif"! (dove i ! sostituiscono le parentesi angolari). In questo caso il link sarebbe tecnicamente corretto. Ma se viene effettuata la riscrittura dell'URL tramite mod_rewrite ci troviamo in una situazione un po' strana in cui ci compare magiamente una directory che non esiste, visualizza in questo caso. In pratica è come se il nostro file visualizza.php si trovasse in root/visualizza/strumenti/visualizza.php invece di root/strumenti/visualizza.php e di conseguenza il link all'immagine diventerebbe root/visualizza/immagini/vis.gif che ovviamente non esiste.
Per ovviare a questo inconveniente ci sono tre strade
a) riscrivere la pagina visualizza.php tenendo presente di questa directory fittizia (quindi il link all'immagine diventerebbe !img src="./../../immagini/vis.gif"!
B) utilizzare il flag [L] nella RewriteRule
c) utilizzare il tag base dell'html