Indirizzi SEO friendly con Apache HTTP mod_rewrite

Per tutti quei siti che hanno la necessità di essere indicizzati correttamente dai motori di ricerca, esistono diverse accortezze su dove e come posizionare le parole chiave che possono agevolare l’indicizzazione dei contenuti. Un esempio? Il contenuto del tag <title> o dei titoli (<h1> ecc… per intendersi) ha molta rilevanza nella fase di crowling dei bot dei motori di ricerca. Non meno importante è il formato degli URL del sito: avere degli indirizzi che prescindono dalla tecnologia (*.jsp, *.php) non sono solo più comprensibili agli utenti, ma lo sono anche per i motori di ricerca.

Riprendiamo quindi l’argomento già introdotto dal post di Fabio e tentiamo di generalizzarlo per tutte quelle tecnologie che sfruttano Apache HTTP Server, siano esse PHP, Ruby, Python o persino JSP quando si accoppia l’HTTP server con Tomcat (per esempio). Questo post non vuole essere un tutorial, ma sono una condivisione dell’esperienza (diciamo tentativi…) sulle difficoltà incontrate nell’uso di questo strumento.

Le due vie

Quando si ha la necessità di riscrivere gli URL, possiamo scegliere due strade:

  • se siete amanti delle espressioni regolari, potete affidare tutto il compito ad Apache;
  • al contrario, riscriviamo gli indirizzi programmaticamente (JSP, PHP che sia…) e lasciamo un minima configurazione per Apache;

Quello di cui abbiamo bisogno è il modulo mod_rewrite di Apache, attivo di default al momento dell’installazione del server. Un modo per usarlo è creare un file .htaccess nella root del nostro sito e capire cosa metterci dentro… Questo file infatti non è specificatamente dedicato al mod_rewrite: spesso infatti è usato per indicare al server quali cartelle proteggere da password. Per quel che ci riguarda, ci basta usare la seguente sintassi:

RewriteEngine On
RewriteRule EXPR Nuovofile [FLAG,FLAG]

che fin qui è abbastanza chiara: abilita il motore di riscrittura degli indirizzi e definisce una regola: l’engine testa tutte le regole in sequenza e a quella che trova corrispondenza viene applicata la trasformazione. E’ possibile modificare il comportamento attraverso l’uso di particolari FLAG. Consultate la guida relativa di Apache per comprenderne i dettagli. Quelli più usati sono:

  • L – Ultima Direttiva: l’engine esegue tutte le trasformazioni specificate nel file .htaccess, anche se ha già trovato la corrispondenza. E’ possibile quindi usare questo flag per impedire che si facciano operazioni inutili;
  • QSA – Query String Append: riporta la query string dall’url fittizio a quello reale. Utile per portarsi dietro parametri che non avevamo previsto;
  • NC – No Case: valuta l’espressine senza fare differenza tra caratteri maiuscoli e minuscoli;

La via delle espressioni regolari

Se siete a vostro agio con le espressioni regolari, questa è la vostra soluzione: .htaccess sarà il vostro unico file centralizzato dove tenere tutte le trasformazioni.

Immaginiamo di avere alcune pagine da trasformare: facciamo un esempio in PHP (perché effettivamente è l’unico con cui ho avuto modo di lavorare 🙂 ), ma con Apache HTTP + Tomcat, usando file JSP, non dovrebbe cambiare niente (anzi, ogni commento/smentita in proposito è ben accetto!!). Mappiamo quindi le seguenti chiamate:


http://www.mysite.com/contacts.php
http://www.mysite.com/portfolio.php
http://www.mysite.com/portfolio.php?category=catX
http://www.mysite.com/subcategory.php?category=catX&subcategory=subcatY

rispettivamente in


http://www.mysite.com/contacts/
http://www.mysite.com/portfolio/
http://www.mysite.com/portfolio/catX/
http://www.mysite.com/portfolio/catX/subcatY/

Gli indirizzi che ne ricaviamo sono indubbiamente più leggibili e contengono già le parole chiave al loro interno. Per ottenere ciò, avremo bisogno di un file .htaccess così fatto:

RewriteEngine On
RewriteRule ^contacts/?$ ./contacts.php [L]
RewriteRule ^portfolio/?$ ./portfolio.php [L]
RewriteRule ^portfolio/([A-Za-z0-9\-]+)/?$ ./portfolio?category=$1 [L]
RewriteRule ^portfolio/([A-Za-z0-9\-]+)/([A-Za-z0-9\-]+)/?$ ./subcategory.php?category=$1&subcategory=$2 [L]

Le prime due regole sono molto semplici: si delimita l’URL tra ^ e $ e si ammette che l’indirizzo possa finire per / o meno. Gli ultimi due invece cosa fanno? Dopo la stringa “portfolio“, ammettono caratteri alfanumerici, compreso il segno meno, presenti almeno una volta ([A-Za-z0-9\-]+). Il fatto che siano tra parentesi tonde introduce il concetto di sostituti: in pratica, tutto ciò che corrisponde a questa espressione regolare viene copiato in una variabile $1, $2, ecc... disponibile nella parte destra della regola. In questo caso viene riusata per costruire i parametri da passare agli script.

La via dei programmatori

Se invece trovate inumane le espressioni regolari, possiamo sempre affidarci al nostro linguaggio di programmazione preferito, ed indicare ad Apache che tutte le richieste, ad esclusione dei file o cartelle esistenti, saranno servite da un unico “dispatcher (sia esso un file PHP o una Servlet).

RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d  
RewriteCond %{SCRIPT_FILENAME} !-f 
RewriteRule ^.*$ ./dispatcher.php

Se le due condizioni definite da RewriteCond sono vere (cioè la richiesta non è una risorsa esistente), allora si procede con la regola che li segue. A questo punto, spetterà al dispatcher il compito di spezzare l’indirizzo e rigirare le richieste ai file giusti.

Qualche considerazione

Questo è quanto ho appreso ultimamente sull’argomento, niente di nuovo (o di meglio) rispetto a quello che si trova in giro in rete. L’esigenza di farne un post in realtà mi è venuta in seguito ad un paio di difficoltà che ho incontrato.

Una di queste riguarda gli indirizzi trasformati che finiscono con “/“: nell’espressione regolare infatti ho messo che siano facoltativi. Nell’uso ho notato questo: se non viene usata la barra al termine dell’indirizzo, la pagina viene caricata normalmente, altrimenti non vengono caricati né gli stili né gli script!! Per quel che ho capito, l’uso della barra viene interpretato da browser come una cartella, per cui, se si usano i percorsi relativi nella pagina per referenziare i file css e js, tutto viene spostato di un livello. Inserendo i percorsi assoluti invece si risolve il problema: questo adesso mi fa capire come mai WordPress usa proprio i percorsi assoluti…

L’altro problema invece riguarda il caricamento del file .htaccess su Aruba: appena messo, il sito rispondeva con un bellissimo “Internal Server Error”!! Che fare, visto che il file in locale non creava problemi? Dopo moooolta pazienza, ho scoperto che se l’URL fittizio e il file originale hanno lo stesso nome, come per esempio:

RewriteRule ^contacts/?$ ./contacts.php [L]

su Aruba non va!! Soluzione?! Rinominare contacts.php in _contacts.php… Soluzione non strutturale ma funzionale! 🙂 Commenti? Giudizi? A voi la parola.

Andrea Como

Sono un software engineer focalizzato nella progettazione e sviluppo di applicazioni web in Java. Presso OmniaGroup ricopro il ruolo di Tech Leader sulle tecnologie legate alla piattaforma Java EE 5 (come WebSphere 7.0, EJB3, JPA 1 (EclipseLink), JSF 1.2 (Mojarra) e RichFaces 3) e Java EE 6 con JBoss AS 7, in particolare di CDI, JAX-RS, nonché di EJB 3.1, JPA2, JSF2 e RichFaces 4. Al momento mi occupo di ECM, in particolar modo sulla customizzazione di Alfresco 4 e sulla sua installazione con tecnologie da devops come Vagrant e Chef. In passato ho lavorato con la piattaforma alternativa alla enterprise per lo sviluppo web: Java SE 6, Tomcat 6, Hibernate 3 e Spring 2.5. Nei ritagli di tempo sviluppo siti web in PHP e ASP. Per maggiori informazioni consulta il mio curriculum pubblico. Follow me on Twitter - LinkedIn profile - Google+

  • Pingback: best seo software()

  • Hai salvato la mia giornata. Erano ore che cercavo di capire perché il mod_rewrite non funzionasse su Aruba. L’unica risposta sensata sul web l’hai data tu!

  • C’ho perso molto tempo anche io prima di scoprire il problema: il minimo era condividerla, anche se dovrebbe farlo Aruba.