Apache et les .htaccess : Les réécritures d’URLs

Le concept d’URL Rewriting

L’URL rewriting est une pratique qui consiste à « déguiser » des URLs pour qu’elles soient plus intéressantes pour le SEO, mais aussi plus jolies et logiques. De cette manière, nous pourrons par exemple déguiser l’url /mes_articles.php?id=38, avec l’url /mes_articles/mon titre/38, plus intéressante pour Google et consorts.

Ce déguisement d’url se fait grâce à des patterns, qui sont des conditions. Toute URL qui valide une condition se voit transformer en entrant dans le serveur.

Pour créer ces patterns, il faut utiliser une technique nommée « Expressions régulières », qui est sans aucun doute une des choses les plus hermétiques aux néophytes, mais qui est heureusement assez simple une fois que la logique et la syntaxe sont acquises.

Les expressions régulières

Les expressions régulières sont un sujet très vaste, qui mériterait à lui tout seul un article plus long que celui-ci. Je serais donc obligé de passer bien plus vite sur le sujet que nécessaire. 

Voilà un exemple simple d’expression régulière: /Bonjour [a-z]+/.

Explication:
 – les « / » sont un moyen simple d’indiquer qu’on est en présence d’une expression régulière.
 – le « + » s’applique à ce qu’il suit, donc dans notre cas [a-z]. Il signifie que ce caractère peut être répété entre 1 et l’infini pour valider la condition.
 – le [a-z], enfin, est une classe de caractères, qui signifie que tous les caractères entre a et z valide la condition.

La chaîne « Bonjour martin », par exemple, valide notre contrat, de la même manière que la chaîne « Bonjour martin, comment vas-tu ?« , car notre expression est bien présente dans la chaîne.

A l’inverse, « Bonjour, martin », ne valide pas la chaîne, car la virgule n’est pas prévue dans le contrat.

Pour finir, il est possible de « capturer » des portions de chaîne pour les utiliser plus tard, grâce aux parenthèses, comme le montre cet exemple.

Pour vous aider à tester vos expressions régulières, je vous conseille d’utiliser Rubular, qui contient un petit aide-mémoire des syntaxes les plus fréquentes en plus de son outil de test.

Un peu de munitions pour vos expressions régulières

Le vocabulaire des expressions régulières est assez étendu, je ne vais pas vous en faire une liste exhaustive ici. Voilà tout de même la liste des symboles utilisés pour la suite

^ début de ligne
$ fin de ligne
[] classe de caractères
() parenthèses capturantes
+ au moins un
$1, $2, …  On réécrit une portion capturée précédemment.

Il y en a bien évidemment plus, mais voilà ceux que vous utiliserez le plus pour les expressions régulières.

Le vif du sujet, L’URL Rewriting

Pour la suite, nous allons avoir besoin d’un serveur apache avec mod_rewrite d’installé. Si vous avez un mutualisé, c’est normalement le cas. Si vous travaillez avec Wamp, pensez à activer mod_rewrite.

Placez-vous dans le dossier racine de votre site, et ouvrez (ou créez) le fichier .htaccess.

La première chose à faire est d’activer mod rewrite. pour cela, écrivez RewriteEngine On. Toutes vos réécritures devront se placer en DESSOUS de cette ligne.

La syntaxe permettant de créer une réécriture est très simple : RewriteRule pattern nouvelle_url [options].

Voilà quelques exemples : 

RewriteRule ^ma_page$ mon_fichier.php [L]

Cet exemple relie une uri de notre choix (ma_page) à un fichier.
Le flag [L] signifie que l’on stop ici la lecture des règes de redirections.

RewriteRule ^blog/(.*)$ articles/$1 [R=301]

Pour cet exemple, il faut imaginer une nouvelle version de site, ou la partie blog change d’URLs à cause d’un nouveau CMS. Nous effectuons donc une redirection de nos anciennes adresses (/blog/mon-titre) vers les nouvelles (/articles/mon-titre).
Il faut noter le $1, qui réinsert le titre de l’article, et le Flag [R=301], qui indique à Google que c’est une redirection de type 301, donc permanente.

RewriteRule ^/articles/([a-z0-9]+)/([0-9]+)$ articles.php?title=$1&id=$2 [L]

Pour ce dernier exemple, le but est de donner un permalien à des articles, qui ne sont pas réellement des fichiers, mais des données mySQL (par exemple). Nous découpons donc nos belles URL pro-SEO en un format compréhensible par php, avec des variables $_GET .

Url rewriting

Les RewriteCond, petit manuel

RewriteCond est un mot-clé de la configuration Apache qui permet (comme son nom l’indique si bien) de définir des conditions pour l’application de RewriteRule.

La règle est simple : Une RewriteCond s’applique uniquement pour la RewriteRule qui suivra. Une RewriteRule pour donc avoir plusieurs Rewrite Cond (toutes celles qui le précèdent depuis la dernière Rewrite Rule), mais chaque RewriteCond ne s’applique que pour une seule RewriteRule.

Ces conditions fonctionnent comme toutes les autres conditions en programmation : si elles ne sont pas valides, la Rule est ignorée.

Les RewriteCond se présentent généralement sous la forme RewriteCond string pattern, à quelques exceptions près (je vous en présenterai une plus bas). Si la chaîne string correspond (match) le pattern, la condition est valide. La puissance de RewriteCond est que ces strings peuvent contenir des variables serveur, ou même des références de réécritures (les groupes captures par des parenthèses).

Pour illustrer le propos, voilà quelques exemples de cas pratiques.

Rediriger plusieurs domaines vers un domaine principal

Votre site est mon-blog.fr, mais vous avez aussi acheté le domaine mon-blog.com . Pour un souci de référencement, vous n’avez certainement pas envie d’utiliser les deux domaines, il faut donc faire une redirection. Voilà la solution :

RewriteCond %{HTTP_HOST} !http://mon-blog.fr$
RewriteRule ^(.*)$ http://mon-blog.fr$1 [R=301, L]

La variable serveur utilisée, HTTP_HOST, correspond à l’hôte présent dans la requête.
Le symbole ! signifie « différent ».

 

Si l’hôte est différent de http://mon-blog.fr, nous appliquons la redirection vers la bonne adresse.

Appliquer une condition negative

Vous avez décidé de mettre votre Blog dans un sous-dossier, il faut donc rediriger les anciennes URLs. Seul problème, les images, elles, n’ont pas bougé car vous avez décidé de les garder dans un dossier séparé (pour versionaliser votre blog, par exemple).

RewriteCond %{REQUEST_URI} !^/images/(.+)$
RewriteRule ^(.*)$ /blog/$1 [R=301, L]

La variable serveur REQUEST_URI est l’URL de la requête privée de l’hôte.

Cette condition vous permet de rediriger toutes les URLs, a l’exception de celles de vos images.

Appliquer une redirection en fonction de l’origine de la requête

Quelqu’un s’amuse à vous piquer vos articles complets ? Ou bien se permet de linker vos images directement ? La solution (si le dialogue échoue) serait de lui envoyer des images différentes de ce que le reste du monde voit, en réécrivant les URLs en fonction de l’origine de la requête.

RewriteCond %{HTTP_REFERER} !http://blog-de-mon-concurrent-voleur.fr.*$
RewriteCond %{REQUEST_URI} !^/images/.*$
RewriteRule ^(.*)$ /images/dont-steal-please.jpg [L]

Les deux conditions s’appliquent bien à notre règle, et signifient que toutes les requêtes venant de blog-de-mon-concurrent-voleur.fr à destination d’une image afficheront à la place notre image dont-steal-please.jpg, faite pour l’occasion.

Activer un mode « maintenance » en fonction de la présence d’un fichier

Pour finir, voila un exemple un peu exotique, où l’on applique une redirection en fonction de l’existence d’un fichier.

RewriteCond /var/www/mon-blog/tmp/maintenance -f
RewriteCond %{REQUEST_URI} !^/maintenance/.*$
RewriteRule ^(.*)$  maintenance/index.php [L]

Si le fichier maintenance est present, toutes les requêtes seront redirigées vers maintenance/index.php, à moins qu’elles n’y pointent déjà (pour ne pas rediriger les CSS et les images). De cette façon il est très simple de passer et retirer le mode maintenance.

Pour finir

La puissance des RewriteCond est énorme, et je ne peux que vous conseiller d’aller voir la liste des variables serveurs disponibles sur le site d’apache. De plus leur utilisation n’est pas réellement compliquée, la grosse difficulté vient surtout de l’utilisation des Regexp.

N’hésitez pas à poser vos questions en commentaires, que ce soit pour éclaircir un point où proposer un sujet qui pourrait vous intéresser, que je traiterai dans un prochain article.