Introduction à l'URL Rewriting

L’URL Rewriting permet de “ré-écrire des URLs”.
Grâce à cette fonctionnalité, vous pouvez proposer des URLs “virtuelles” sur votre site, qui ne correspondent à aucune page réelle : vous donnez une certaine URL, ou vous la mettez dans un lien, et en fait le client verra affichée une page toute autre.

L’URL Rewriting permet de “réécrire des URLs”.

Pré requis : avoir quelques notions sur les expressions réguliéres..

Introduction

L’URL Rewriting permet de “ré-écrire des URLs”.
Grâce à cette fonctionnalité, vous pouvez proposer des URLs “virtuelles” sur votre site, qui ne correspondent à aucune page réelle : vous donnez une certaine URL, ou vous la mettez dans un lien, et en fait le client verra affichée une page toute autre.

Les exemples qui suivent supposent une mise en pratique avec Apache (version 1 ou 2) et son module “mod_rewrite”.
PHP est pris comme langage de référence pour les exemples pour les noms des pages, mais cela fonctionne bien sûr avec d’autres langages :-)

Par exemple :
http://www.monsite.fr/a/b/c/ affichera en réalité sur mon site la page correspondant à l’URL de votre site : http://www.monsite.fr/index.php?page=a&section=b&client=c

L’intérêt est double :
- le référencement : certains moteurs de recherche n’indexent pas les pages au delà d’un certain nombre de paramètres. C’est le cas de Google qui bloque au delà de deux. Ainsi, la page que j’ai donné en exemple ( http://www.monsite.fr/index.php ?page=a&section=b&client=c ) qui contient trois paramètres “page”, “section” et “client” ne sera pas indexée, ce qui nuira au bon référencement de votre site.
- la sécurité, ou plutot le coté “pratique” : vous avez par exemple un répertoire admin/ auquel vous ne voulez que personne accède. Grâce à l’URL Rewriting, vous pouvez spécifier que toute page appelée dans le répertoire admin/ doit afficher en fait http://www.monsite.fr/erreur.html

Mise en pratique

En pratique, l’URL Rewriting est disponible (a minima) sur Apache, et sur IIS.
Nous traiterons le cas d’Apache, qui est très répandu, je n’ai jamais testé sur IIS (le serveur HTTP Microsoft).

1- Vérifier que l’URL Rewriting est utilisable

En PHP, il suffit de vérifier que le module “mod_rewrite” est chargé.
Faites une page et regardez dans la liste “Apache Loaded Modules” si ce module est bien activé. En général même chez de petits hébergeurs payants c’est le cas.

2- Fonctionnement

L’URL Rewriting se présente concrètement sous forme de “règles” que vous allez préciser dans un fichier .htaccess
Rappelons que les fichiers .htaccess ont d’autres fonctions, qui ne seront pas exposées ici : restriction d’accès à une page, erreurs personnalisées, redirections.

L’URL Rewriting utilise donc des règles, composées d’un masque de recherche qui est une expression régulière, et un masque de remplacement en fonction (un peu comme preg_replace en PHP)
Si l’URL entrée par l’utilisateur (ou dans un lien) vérifie le masque de recherche, elle est remplacée par l’autre masque, celui de remplacement.
A noter : si le masque de remplacement est un tiret, la réécriture n’a pas lieu.

3- Premier exemple

Voyons un premier exemple très simple.
Mettez dans votre .htaccess :

RewriteEngine on
RewriteRule ^test\.html$ /test.php

Mettez ensuite une page test.php à la racine de votre site :
Exemple de contenu :

Ceci est la page test.php !!

Si vous essayez d’aller sur http://www.votresite.fr/test.html, vous verrez la page test.php s’afficher ! Et ce bien que test.html n’existe pas en réalité.

Remarque : si c’est uniquement pour faire une redirection fixe, pas besoin d’URL Rewriting : un RedirectPermanent marche aussi.. Remarque2 : selon la version et les réglages de votre serveur, il est possible que ceci ne marche pas (erreur 500 ou 404) : mettez alors test.php au lieu de /test.php en réécriture.

4- Limites

Certaines regex ne marcheront pas sur de l’URL Rewriting.
Les notions “avancées” des langages de regex, du genre test avant, test arrière, conditions, n’ont pas marché sur mon serv Apache.

Conclusion : une expression régulière utilisée dans ce cas se doit d’être VERIFIEE !

Pour l’anecdote, dans un masque compliqué un jour, [abcd] fonctionnait, mais pas [abcdef], allez comprendre ;o)

Les références

Comme tout outil utilisant les regex, on peut capturer du texte et le réutiliser lors du remplacement.

Ceci se fait comme avec preg_replace, par l’ajout de parenthèses pour capturer, et de références $1,$2,... pour restituer ce qui a été capturé. Exemple : vous désirez que toute page php demandée dans repertoire1 affiche en fait la page équivalent dans répertoire2 :

RewriteEngine on
RewriteRule ^repertoire1/(.*\.php)$ /repertoire2/$1

Je ne m’étendrai pas plus la dessus ici, histoire de se concentrer sur l’URL Rewriting et non sur les mécanismes de regex.

Les drapeaux

Les flags, ou drapeaux, se placent après le masque de ré-écriture : ils permettent de définir des options pour la réécriture.
Ils peuvent être combinés en étant séparés par une virgule : [L,F] par exemple (voir la suite)

[L] : la règle qui précède sera la dernière, aucune autre tentative de réécriture ne sera effectuée ensuite. Exemple :

RewriteEngine on
RewriteRule ^test\.php$ - [L]
RewriteRule ^test\.php$ /test2.php

Vous tomberez sur test.php, et non test2.php. Sans le [L], vous tomberez sur test2.php ! Ce flag permet par exemple de bloquer l’accès aux images par exemples, tout en gardant une réécriture sur tous les dossiers/fichiers autres.

[R] : force une redirection Exemple :

RewriteEngine on
RewriteRule ^test\.php$ /test2.php [R]
test.php sera redirigée vers test2.php, et non réécrite à la volée : le visiteur verra s’écrire test2.php dans la barre de navigation de son browser. [F] : forbidden, accès interdit : renvoie une erreur 403 (permet de protéger l’accès à certains fichiers/répertoires coté serveur !) Exemple :
RewriteEngine on
RewriteRule ^test\.php$ - [F]

[G] : erreur 410, URL n’existant plus Exemple :

RewriteEngine on
RewriteRule ^test.php$ - [G]

[N] : recommence au début des règles Exemple :

RewriteEngine on
RewriteRule ^test2.php$ /index.html
RewriteRule ^test.php$ /test2.php [N]

Avec ces règles, la page test.php sera réécrite en test2.php, puis en index.html !

[NC] : pattern non sensible à la casse (majuscules/minuscules) Exemple :

RewriteEngine on
RewriteRule ^tEsT.pHP$ /test2.php [NC]
Ce masque réécrira bien test.php (marche également dans l’autre sens.. qui est plus intéressant ;o))

Voila la liste des autres flags, moins utiles pour débuter :
[P] : force le passage par un proxy : non testé
[C] : règles en chaines : non testé
[T] : force le type MIME du fichier demandé : non testé
et autres QSA,NS,PT,S,E…

Les conditions

mod_rexrite permet de mettre différentes conditions avant de réaliser une réécriture.

Trois choses à savoir :
- le “ET” est implicite entre deux conditions sur deux lignes successives, et pour faire un ou, il suffit d’ajouter un flag [OR] en fin de ligne
- pour nier un masque, il suffit de le précéder d’un point d’exclamation ”!”
- les tests agissent sur des “VARIABLES SERVEUR” de la forme %VARIABLE. Une liste exhaustive est dispo dans la doc Apache, on va par exemple tester le host du visiteur :

Exemple : refuser les hosts contenant AOL ou tiscali sur notre page test.php

RewriteEngine on
RewriteCond %REMOTE_HOST AOL [OR]
RewriteCond %REMOTE_HOST tiscali
RewriteRule ^test\.php$ - [F]

Exemple : réécrire test.php en test2.php pour les non-utilisateurs de Firefox

RewriteEngine on
RewriteCond %HTTP_USER_AGENT !^.*Firefox.*$
RewriteRule ^test\.php$ /test2.php

Note : voici mon HTTP_USER_AGENT
- avec Firefox : Mozilla/5.0 (Windows ; U ; Windows NT 5.1 ; fr-FR ; rv:1.7.12) Gecko/20050919 Firefox/1.0.7
- avec IE : Mozilla/4.0 (compatible ; MSIE 6.0 ; Windows NT 5.1 ; SV1 ; .NET CLR 1.1.4322 ; .NET CLR 2.0.50215)

Cette réécriture n’est pas infaillible, on peut régler son user agent sur certains browsers.

Exemple : afficher une page différente en journée et soirée : (curiosité trouvée dans un ppt sur www.w3-campus.com)

RewriteEngine on
RewriteCond %TIME_HOUR%TIME_MIN > 0800
RewriteCond %TIME_HOUR%TIME_MIN < 2000
RewriteRule ^index\.html$ index.jour.html [L]
RewriteRule ^index\.html$ index.nuit.html [L]

A vous d’être imaginatifs maintenant !

Conclusion

Beaucoup de fonctionnalités et options de l’URL Rewriting n’ont pas été abordées ici, mais vous avez déjà un panorama assez large des fonctionnalités de base.

Si vous voulez plus d’infos reportez vous à la doc Apache mod_rewrite (fr)
Ou un autre tuto très bien fait