URL Rewriting - Réécriture d'URL à la volée

Bienvenue dans ce tutoriel qui risque d'être long et difficile mais ne vous inquiétez pas, nous allons tout faire pour que vous puissiez comprendre facilement de quoi il va être question !

L'URL rewriting ou réécriture d'URL à la volée et un sujet complexe et de loin l'un des plus important pour un site web. Son objectif est multiple : améliorer le référencement de votre site, protéger votre technologie, simplifier la navigation de vos utilisateurs, permettre l'évolution de votre site, gérer les redirections... pour n'en citer que quelques-uns.

Avant de commencer, vous allez avoir besoin d'un outil très puissant que l'on appelle « Expression régulière » ou « RegExp ». Cet outil vous permettra de définir toutes les règles et conditions que nous allons utiliser dans la suite de ce tutoriel. Afin de vous assurer une bonne compréhension, il est essentiel que vous sachiez les utiliser.

Maintenant que nous sommes prêt à prendre le taureau par les cornes, entrons dans le vif du sujet !




Suivez le guide !

URL Rewriting

L'URL rewriting ou réécriture d'URL est comme nous l'avons brièvement abordé ci-dessus est un élément fondamental de votre site. Avant d'attaquer le code en lui-même, quelques précisions s'imposent.

Cette technique très spéciale permet de réécrire des URL. Concrètement qu'est-ce que cela signifie ? Vous avez déjà certainement vu lors de votre navigation sur le web ce que l'on appelle des pages dynamiques. Elles sont souvent en « .php » et possèdent parfois de nombreux paramètres que l'on trouve après le « ? » comme par exemple :

  • « www.craym.eu/forum/viewtopic.php?fiew=7&tread=24&message=12 »

C'est ce qu'on appelle une URL dynamique. Selon les paramètres que l'on passe dans l'URL, ici le numéro de « fiew », « tread » et « message », l'on obtiendra des résultats différents car la page est créé en fonction de ces paramètres. Ici, on cherche à afficher le forum 7, le 24ème sujet de ce forum et le 12ème message posté mais l'on peut afficher ce que l'on veut rien qu'en changeant les numéros !

C'est extrêmement pratique car une seule page peut en générer des milliers. Malheureusement, cela ne fait pas la joie des robots d'indexation comme Googlebot qui référence notre site. Lui, ne retient que des pages ayant jusqu'à deux paramètres dans l'URL et donc notre page ci-dessus sera tout simplement ignorée c'est qui est un véritable problème !

L'URL rewriting est là pour tout corriger. Avec elle, nous allons recréer une URL plus propre et indexable par les robots. Par exemple, nous pouvons créer l'URL :

  • « www.craym.eu/forum/viewtopic/fiew-7/tread-24/message-12.html »

Ce qui est nettement plus lisible vous en conviendrez. Notre URL ne contient plus de paramètres, elle se termine en « .html » pour camoufler la technologie que nous utilisons (ne facilitons pas le travail des hackers) et tient d'un seul tenant comme si c'était une page classique qui se situait dans le dossier « /forum/viewtopic/fiew-7/tread-24/ ».

Ainsi, plus de problèmes d'indexation ! Votre forum, catalogue de produits, liste de je-ne-sais-quoi sera visible et indexé par Google !

Découvrons les coulisses d'un tel tour de magie !



Suivez le guide ! Le fichier .htaccess

Pour créer nos nouvelles URLs « propres » sans tous les caractères spéciaux « & = ? »... nous allons devoir créer des règles. Ces règles se situent dans un fichier bien précis : le fichier « .htaccess ».

.htaccess

Ce fichier est un simple fichier texte basique qui n'a pas de nom et dont l'extension est « htaccess » d'où le fait qu'il commence par un point. Il parait très basique mais c'est un des fichiers les plus puissants de votre site. C'est dans ce fichier que nous allons écrire nos règles de réécritures.

Notez que ce fichier ne prend effet que pour le dossier et les sous dossiers dans lequel il est situé. Typiquement, on le place à la racine du site web. Vous aurez peut-être du mal à créer le fichier. Pour forcer l'éditeur de texte à enregistrer le fichier correctement, entrez le nom entre guillemet comme ceci : « ".htaccess" ».

Vous vous en servez peut-être déjà pour gérer vos erreurs comme expliqué dans le tutoriel sur la gestion des erreurs du web. Si c'est le cas, ce fichier ne vous sera pas inconnu !

Si vous travaillez sur Wampserveur dont l'installation est expliquée ici, vous pouvez aussi tester votre configuration grâce au module de réécriture intégré. Cliquez simplement sur l'icône en bas à droite, et recherchez le « rewrite_module » dans la configuration d'Apache.

rewrite_module wamp

Un simple clic suffira pour l'activer !

Avant de voir les règles en détails, nous allons tout d'abord vérifier que le module d'URL rewriting est bien en place et actif. Pour cela, si vous avez accès à la configuration de votre serveur et notament au fichier de configuration d'Apache « httpd.conf », vous devriez trouver les lignes :

  • « LoadModule rewrite_module libexec/mod_rewrite.so »
  • « AddModule mod_rewrite.c »

decommentées (sans # devant) ce qui indique que le module est bien lancé. SI ce n'est pas le cas, décommentez-les et redémarrez Apache.

Si vous n'y avez pas accès, ou que vous ne savez pas exactement où il se trouve, nous allons tout simplement effectuer un premier test et vérifier la bonne marche du module de réécriture ! Chez nous, ne vous inquiétez pas, le module est actif et pleinement fonctionnel !


Suivez le guide ! Un premier exemple d'URL rewriting


Dans ce premier exemple introductif, nous allons apprendre comment créer une règle de réécriture de base. Ainsi, non seulement nous pourrons vérifier que l'URL rewriting est bien disponible pour notre hébergement mais en plus comment il fonctionne.

Nous allons placer le code ci-dessous dans le fichier « .htaccess » à mettre à la racine de votre serveur (pour commencer).

Nous allons tout d'abord lancer le module de réécriture. Pour cela, il faut utiliser les instructions suivantes (nous y reviendrons juste après) :

1
2
Options +FollowSymlinks
RewriteEngine On

Une fois lancé, nous allons pouvoir passer nos différentes règles de réécriture. Pour l'exemple, nous allons devoir créer une page web de test. Appelons la « test.html » dans lequel nous allons insérer le code ci-dessous :

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3.   <head>
  4.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5.     <title>Document sans titre</title>
  6.   </head>
  7.   <body>
  8.     Bonjour, je suis la page test.html
  9.   </body>
  10. </html>

Une simple déclaration d'un document XHTML classique.

Nous allons maintenant créer notre première règle de réécriture. Nous voulons accéder à cette page en entrant dans la barre de navigation cette URL : « foo.html ». Pour cela, dans le fichier « .htaccess », nous allons rajouter une règle avec l'instruction « RewriteRule ».

1
2
3
Options +FollowSymlinks
RewriteEngine On
RewriteRule ^foo.html$ test.html [L]

Nous indiquons que si la page demandée commence et finit par « foo.html » (donc est exactement ce fichier), on affiche le fichier « test.html » et on stoppe la réécriture (le drapeau [L] qui signifie "Last")

Nous avons nous-mêmes fait ce test. Comme vous pouvez le constater sur cette image ci-dessous, lors de la demande du fichier « foo.html », le serveur a bien retourné notre page « test.html » !

page de text URL Rewriting


Question

Si vous obtenez une erreur 500 de la part du serveur, c'est qu'il y a une erreur de syntaxe dans le fichier « .htaccess » ou tout simplement que l'hébergeur est incompatible (très très rare de nos jours).

Si vous obtenez une erreur 404, c'est que malheureusement le module de réécriture n'est pas activé et/ou qu'il n'est pas disponible pour votre hébergement.

Notez qu'il est très facile de faire complètement planter son serveur avec un mauvais fichier « .htaccess » contenant ne serait-ce qu'une seule erreur de syntaxe. En cas de bug, renommez simplement le fichier ou supprimez le, le temps de renvoyer le fichier corrigé. Voilà pourquoi nous vous conseillons d'effectuer ces tests dans une période creuse !

Si tout s'affiche comme ci-dessus : félicitations ! Vous venez de terminer votre 1ère règle de réécriture !

Suivez le guide ! Les instructions d'URL Rewriting

Avant de voir en détail ce que nous avons fait dans cette introduction, voici toutes les instructions que nous allons pouvoir mettre dans notre fichier « .htaccess ».

Nous les détaillerons au fur et à mesure que nous en aurons besoin. Voici une rapide description :

Instruction Arguments / Valeur Description
Option +FollowSymlinks Active la gestion des URL symboliques.
RewriteEngine on / off Active/Désactive le module de réécriture.
RewriteOptions inherit
MaxRedirects=1
Applique certaines options de réécriture :

- inherit permet d'hériter des règles créés dans d'autres fichier qui se trouvent plus haut dans l'arborescence.

- Nombre de redirections maximum par fichier (par défaut : 10)
RewriteLog fichier-chemin Chemin depuis la racine où doit être sauvegardé le fichier de log.
RewriteLogLevel 0 - 10 Niveau d'erreur qui doit être inséré dans le log (de 0 à 10, par défaut 0)
RewriteLock fichier-chemin Chemin local du synchronisation lockfile.
RewriteMap MapName MapType:MapSource Nom, type et source d'un Rewriting Map.
RewriteBase URL-chemin Chemin à utiliser comme préfixe dans une règle de réécriture.
RewriteCond Chaine_à_tester Condition [drapeau] Permet d'insèrer une condition sur la règle de réécriture.
RewriteRule pattern substitution [drapeau] Si le pattern correspond, indique comment réécrire l'URL.


Suivez le guide ! Les règles de réécriture

Maintenant que nous avons vu une première règle de réécriture, nous allons en détailler la syntaxe générale. Nous reprendrons pour cela le petit test que nous venons d'effectuer.

1
2
Options +FollowSymlinks
RewriteEngine on

L'instructions « Options +FollowSymlinks » est facultative mais permet d'indiquer au serveur qu'il faut suivre les liens symboliques de réécriture.

« RewriteEngine on » est indispensable pour lancer le module de réécriture d'URL. Vous pouvez aussi désactiver celui-ci en utilisant simplement la valeur off : « RewriteEngine off ». (Très utile en cas de bug !)

Ces deux instructions ne doivent être présente qu'une seule fois par fichier avant la première instruction de réécriture.

Viennent ensuite les différentes instructions et règles de réécriture. Il y en a une par ligne sous la forme suivante (une par ligne pour une réécriture simple, une réécriture complexe avec des conditions s'écrit en plusieurs lignes mais nous verrons ceci plus bas) :

1 RewriteRule URL_a_réécrire URL_réécrite [drapeau]

  • « RewriteRule » indique au serveur qu'on inscrit une nouvelle règle de réécriture.
  • Puis vient l'URL que l'on souhaite réécrire, c'est-à-dire l'URL propre et qui n'a donc pas d'existence physique sur le serveur.
  • On inscrit ensuite l'URL sur laquelle doit être redirigée l'URL propre. Cette URL sera cachée aux visiteurs et ils n'auront aucun moyen de la connaitre.
  • Enfin, on peut faire suivre la règle d'un ou plusieurs drapeaux. Ce sont des instructions supplémentaires qui vous seront indispensables par la suite. Nous y reviendrons après.

Chaque partie de l'instruction est séparée par un ou plusieurs espaces. Notez qu'il ne doit pas y avoir de retour chariot sur une ligne de règle de réécriture !

Le format de l'URL à réécrire est basé sur les expressions régulières, c'est-à-dire que vous pouvez vérifier vos URL avec l'aide de celles-ci et donc être extrêmement précis tout en restant très générique. Concrètement, on peut écrire des choses comme celle-ci :

1 RewriteRule ^article-([0-9]+)-([0-9]+)\.html$ /articles/article.php?id=$1&rubrique=$2 [L]

Et cela fonctionne très bien ! La vrai difficulté résidant dans l'écriture des règles avec les expressions régulières et leurs coordinations entre elles.

Question

Les pièges dans lesquels il ne faut pas tomber.

Pour l'instant, nous ne regardons que le coté « efficace » de la réécriture d'URL mais elle permet le meilleur comme le pire !
Un exemple très simple, regardons ces deux règles :

1
2
3
4
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^page1.html$ page2.html
RewriteRule ^page2.html$ page1.html

La première réécrit « page1.html » en « page2.html », la seconde « page2.html » en « page1.html » . Si aucune des deux règles ne comporte le drapeau [L] qui stoppe la réécriture après avoir appliqué une règle, vous voilà bloqué dans une boucle infinie !

Vous avez envoyé votre serveur dans une boucle dont il ne pourrait pas sortir s’il n’avait ses propres mécanismes de sécurité.
L’aisance avec laquelle une règle mal écrite peut mettre un serveur « sur les genoux » est la raison principale de la non-implémentation du module de réécriture chez certains hébergeurs.

Quelques précisions sur le fichier « .htaccess » :

Chaque fichier « .htaccess » est spécifique à un répertoire. Nous vous conseillons de prendre l'habitude d'indiquer en haut de ce fichier l'emplacement du répertoire sur le site. Chaque répertoire de votre site devra donc proposer son propre fichier « .htaccess ». (c'est tout à fait facultatif, un site peut très bien s'en sortir avec un seul fichier.

Si vous souhaitez mettre en place cette structure, vous pouvez hériter des règles que vous avez déjà mis en place dans les dossier supérieurs grâce à cette option : « RewriteOptions Inherit »

1
2
3
4
5
6
7
8
#Fichier .htaccess : /dossier_no3/

Options +FollowSymlinks
RewriteEngine on
RewriteOptions Inherit

RewriteRule ^page1.html$ page2.html
RewriteRule ^page2.html$ page1.html

Les lignes commençant par le signe dièse « # » sont des commentaires. N'hésitez pas à en ajouter pour rendre vos fichiers plus compréhensibles : ces lignes sont totalement ignorées par le module de réécriture d'URL.

Efin, vous pouvez écrire un nombre illimité de règles avec un nombre illimité de conditions.

Note: vous pouvez consulter les différents drapeaux ici : Drapeau d'URL Rewriting




Suivez le guide ! Les réécritures conditionelles

Jusqu'à maintenant, nous n'avons vu que des règles de réécriture absolues, c'est-à-dire qu'elles s'appliquent quel que soit l'IP, l'hôte ou la requête effectuée. Nous allons maintenant créer des règles avec des conditions pour qu'elles ne s'appliquent que si telle ou telle condition est respectée.

Les réécritures d'URLs peuvent dépendre de nombreux tests : des variables du serveur, des variables d'environnement, des en-têtes HTTP et même de l'horodatage.

Pour cela, nous allons avoir besoin d'un nouveau mot clef : « RewriteCond ». Pour vous donner une première idée sur son utilisation, voici un petit exemple :

1
2
3
4
5
6
7
8
9
10
11
12
13
#Fichier .htaccess : /dossier_no4/

Options +FollowSymlinks
RewriteEngine on
RewriteOptions Inherit

RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla(.*)
RewriteRule  ^/$    /complexe.html  [L]

RewriteCond  %{HTTP_USER_AGENT}  ^Lynx(.*)
RewriteRule  ^/$    /simple.html  [L]

RewriteRule  ^/$    /standard.html  [L]

Dans la première condition, ligne 7, nous testons si le navigateur utilisé commence par Mozilla : « ^Mozilla » suivi d'une chaine quelconque « (.*) ». Si c'est le cas, alors nous réécrivons « ^/$ » qui n'est autre que notre page d'accueil, par notre page complexe créé spécialement pour ce navigateur : « /complexe.html »

Nous procédons de la même manière pour l'agent Lynx avec une autre page.

Si aucune de ses deux règles ne s'appliquent, c'est-à-dire que l'on a un autre agent de navigateur, alors nous affichons la page : « /standard.html»

Question Comment la règle « RewriteCond » fonctionne-t'elle?

La directive « RewriteCond » définit une condition d'application d'une certaine règle.

Une ou plusieurs règles « RewriteCond » peuvent être appliquées à une même directive « RewriteRule » . La règle qui suit n'est appliquée que si l'état actuel de l'URL correspond à son modèle, et si toutes les conditions sont satisfaites.

Elle se construit de manière très simple :

1 RewriteCond Chaine_de_test Condition_a_tester [drapeau]

Ici, « Chaine_de_test » n'est pour l'instant que du texte classique. Mais tester des conditions sur du texte que nous avons inscrit nous-même dans le fichier n'est pas vraiment utile car la condition sera toujours vérifiée ou non.

Nous allons donc effectuer nos tests en extrayant des variables de la requête qu'a envoyé le client :

« Chaîne_de_test » peut donc prendre des formes très variées grâce aux variables et l'on peut tester beaucoup de chose ! Voyez par vous-même le tableau des différentes variables disponibles en URL Rewriting :

Ce tableau est assez imposant n'est-ce pas ? Ne vous inquiétez pas, nous avons séparé cette partie dans une page séparée ou tout est expliqué en détails. Vous pouvez la consulter ici :

Pour le moment, nous allons juste apprendre comment tester une condition avec elles. Nous allons utiliser une syntaxe spéciale pour utiliser ces variables :

1 RewriteCond %{VARIABLE_A_TESTER} Condition_a_tester [drapeau]

C'est approximativement le même syntaxe que nous avons vu juste au-dessus à ceci près que nous précédons notre variable d'un « % » et que nous l'entourons d'accolades.

Question Que se passe t-il dans le serveur au moment où la règle est évaluée ?

« Chaîne_de_test » est tout d'abord évaluée Puis elle est comparée à la chaine : « Condition_a_tester ».

Notez que « Condition_a_tester » peut-être une expression régulière ce qui permet de tester absolument tout ce que l'on souhaite !

Voici un exemple :

1
2
3
4
5
6
7
#Fichier .htaccess : /dossier_test/

RewriteEngine on

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{REQUEST_FILENAME} (.*)\.jpg$
RewriteRule %1 dossier_image/%1.jpg

Ici, on vérifie que la requête provient de la même page (HTTP_REFERER est vide) ET que la requête est une image.

Si c'est le cas, alors on redirige l'adresse de l'image demandée sur le bon dossier : « dossier_image/ » où le serveur trouvera le bon fichier.

 

Au lieu d'utiliser des expressions régulières, on peut utiliser différentes expressions de comparaison pour tester certaines propriétés de l'URL qui ne sont pas disponibles avec les expressions régulières :

Expression Description
<expression

Traite « expression » comme une chaîne de caractères et compare si « Chaîne_de_test » est inférieure au sens lexicographique.

>expression

Traite « expression » comme une chaîne de caractères et compare si « Chaîne_de_test » est supérieure au sens lexicographique.

=expression

Traite « expression » comme une chaîne de caractères et compare si « Chaîne_de_test » est absolument égale au sens lexicographique, c'est-à-dire que chaque caractères de la chaine est identique.
Si « expression » est "" (deux guillemets) alors « Chaîne_de_test » est comparée à la chaîne vide.

Notez que vous pouvez utiliser le drapeau [NC] pour supprimer la casse.

-d

Traite « Chaîne_de_test » comme un chemin, vérifie s'il existe ou pas, et s'il s'agit d'un répertoire.

-f

Traite « Chaîne_de_test » comme un chemin, vérifie s'il existe ou pas, et s'il s'agit d'un fichier régulier.

-s

Traite « Chaîne_de_test » comme un chemin, vérifie s'il existe ou pas, et s'il s'agit d'un fichier régulier dont la taille est supérieure à zéro.

-l

Traite « Chaîne_de_test » comme un chemin, vérifie s'il existe ou pas, et s'il s'agit d'un lien symbolique.

-x

Traite « Chaîne_de_test » comme un chemin, vérifie s'il existe ou pas, et si le client a le droit d'exécution.
Ce droit est déterminé en accord avec le système d'exploitation sous-jacent.

-F

Vérifie si « Chaîne_de_test » est un fichier valide, accessible à travers tous les contrôles d'accès du serveur actuellement configurés pour ce chemin.
C'est une sous-requête interne qui effectue cette vérification.

Attention ! A utiliser avec précautions car les performances du serveur peuvent s'en trouver affectées !

-U

Vérifie si « Chaîne_de_test » est une URL valide, accessible à travers tous les contrôles d'accès du serveur actuellement configurés pour ce chemin.
C'est une sous-requête interne qui effectue cette vérification

Attention ! A utiliser avec précautions car les performances du serveur peuvent s'en trouver affectées !

Note : Vous pouvez préfixer l'expression avec un caractère '!' (point d'exclamation) pour indiquer une expression de non-correspondance.


Suivez le guide ! Réécritures avancées

Il nous reste une instruction importante à étudier pour maitriser correctement nos règles de réécriture :

  • RewriteBase

La directive RewriteBase définit explicitement l'URL de base pour les réécritures au niveau du répertoire mais qu'est-ce que cela signifie ?

Comme vous le savez déjà, vous pouvez placer vos règles de réécriture dans différents répertoires grâce à plusieurs fichiers « .htaccess ». Celles-ci agissent alors localement, en amputant le répertoire local de son préfixe avant traitement, et en n'appliquant les règles de réécriture que sur ce qui reste de l'URL.

Lorsque le traitement est terminé, le préfixe définit par « RewriteBase » est automatiquement rajouté à l'URL.

Si vous n'utilisez pas l'instruction « RewriteBase » explicitement, la valeur par défaut sera « RewriteBase chemin répertoire physique ».

Lorsqu'une substitution intervient pour une nouvelle URL, le module de réécriture doit réinjecté l'URL dans le traitement du serveur. Pour y parvenir, il doit connaître le préfixe de l'URL ou l'URL de base correspondant. Cependant, pour la plupart des sites web, les URLs ne correspondent PAS directement aux chemins des fichiers physiques, cette assertion s'avère ainsi souvent fausse ! C'est pourquoi vous pouvez utiliser la directive RewriteBase pour spécifier le préfixe correct.

Question

Si les URLs de votre serveur web ne correspondent pas directement aux chemins physiques des fichiers, vous devrez utiliser l'instruction « RewriteBase » dans chaque fichier « .htaccess » où vous voudrez utiliser des instructions « RewriteRule » .

 

Par exemple, considérons le fichier « .htaccess » du répertoire /abc/def/ :

1
2
3
4
5
6
# Fichier de configuration pour le répertoire /abc/def/

RewriteEngine on

RewriteBase /xyz
RewriteRule ^avant\.html$ après.html [L]

Dans le fichier de configuration, on note que le chemin physique « /abc/def » correspond au répertoire virtuel « /xyz » grâce à l'instruction Alias : « Alias /xyz /abc/def ».

Pour indiquer au serveur que l'on atteint la page grâce qu répertoire « /xyz » et non pas « /abc/def » (sinon notre Alias n'aurait servi à rien), nous indiquons au serveur que le répertoire de base est « /xyz » grâce à la règle « RewriteBase ».

Dans notre exemple, une requête pour le fichier « /xyz/avant.html » sera donc correctement réécrite sous sous sa forme chemin physique « /abc/def/après.html ».

 

Question Est-il possible comme dans les expressions régulières de faire de la capture d'expression ?


Bien sur ! C'est ce que nous allons voir tout de suite ! Rappelons que la capture fonctionne exactement comme dans les expressions régulières.

Il en existe de deux types :

  • références arrières de règle de réécriture : ce sont des références arrières de la forme $N (0 <= N <= 9), qui donnent accès aux parties groupées (entre parenthèses) du modèle tiré de la RewriteRule assujettie au jeu de conditions concerné.
  • Références arrières de condition : ce sont des références arrières de la forme %N (1 <= N <= 9), qui donnent accès aux parties groupées (là aussi entre parenthèses) du modèle de la dernière condition satisfaite du jeu de conditions concerné.


Voici un shéma pour vous aider à comprendre comment cela fonctionne :

Référence arrière

Les flèches en rouges illustrent quand les captures sont utilisables pour une référence arrière de condition.

La petite flèche verte en bas indique la possibilité d'une référence arrière de réécriture.

Voici un exemple concret :

1
2
3
4
5
6
# Fichier de configuration pour le répertoire /dossier_test/

RewriteEngine on

RewriteCond %{HTTP_HOST} ^(www\.unsite\.com)$
RewriteRule ^(.+)$ %1/$1

Ici, nous vérifions si le domaine entré par l'utilisateur correspond à notre site, si c'est le cas, nous réécrivons juste l'URL pour afficher la page.

Suivez le guide ! Les variables d'URL Rewriting

Nous avons ci-dessus montré que nous pouvions utiliser des variables pour effectuer nos comparaisons. Mais nous ne les avons pas détaillées.

Il en existe un très grand nombre qui sont utilisables pour l'URL Rewriting. 38 pour ne rien vous cacher ! Cela aurait été un peu trop imposant de toutes les expliquer dans cette page. Elles sont donc toutes disponibles ici :



Suivez le guide ! Les drapeaux

Les drapeaux sont absolument indispensables à une bonne réécriture d'URL. Rien que pour éviter de faire planter notre serveur comme nous l'avons montré au tout début de ce tutoriel.

Le nombre étant là encore assez important, ils ont été traités dans une page séparée. Vous pouvez tous les retrouver ici :


Suivez le guide ! Des exemples au cas par cas

Maintenant que nous sommes en mesure de créer des règles de réécritures complexes, nous allons présenter une série d'exemples très courants et qui devraient (dans le meilleur des cas) être mis en place pendant la création du site. Il n'y a aucun problème à les placer plus tard mais le plus tôt sera le mieux !


URL canoniques : une seule URL pour une même ressource / fichier

Sur de nombreux sites (surtout lorsque vous commencer à utiliser la réécriture d'URL), il existe plusieurs URL pour une même ressource. Une que l'on appelle canonique et qui est utilisée et distribuée et d'autres qui sont juste des raccourcis, des liens internes etc.

Indépendamment de la requête effectuée, on cherche à afficher l'URL canonique (l'URL que l'on souhaite diffuser)

Pour cela, nous allons effectuer une redirection externe HTTP pour toutes les URLs qui ne sont pas canoniques grâce au drapeau de redirection [R]. Le visiteur ne verra donc que l'URL canonique quelle que soit l'adresse entrée.

1 2
3
RewriteEngine On
RewriteRule ^/~([^/]+)/?(.*) /u/$1/$2 [R]
RewriteRule ^/u/([^/]+)$ /$1/$2/ [R]

Dans cet exemple ci-dessus, nous effectuons une redirection HTTP pour toutes les URL non-canoniques afin de les afficher correctement dans le navigateur.
Les règles ci-dessus remplacent « /~user » par l'URL canonique « /u/user » et corrige le problème du slash manquant pour « /u/user ».


Nom d'Hote canonique : avec ou sans www

Le but de cette réécriture est d'afficher un nom de domaine préférentiel par défaut pour un même site. Il faut savoir que les URLs « http://craym.eu » et « http://www.craym.eu » ne sont pas identiques pour les robots. Ils considèrent cela comme du duplicate content ce qui est très mauvais !

Pour corriger le problème, nous allons donc forcer toutes les URLs à afficher l'un ou l'autre des noms de domaine.

 
1 2
3
4
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteRule ^/?(.*) http://www.example.com/$1 [L,R,NE]

 

Contenu dépendant des navigateurs

Une des hantise de tout webmaster est la compatibilité de ses pages avec les différents navigateurs. Une solution possible a ce problème est de détecter les différents navigateurs et d'afficher une page spécialement préparée pour eux. Cela permet d'être sur à 100% de la compatibilité.

Voici le code de la solution :

1 2
3
4
5
6
7
RewriteCond %{HTTP_USER_AGENT} ^Mozilla/3.*
RewriteRule ^foo\.html$ foo.NS.html [L]

RewriteCond %{HTTP_USER_AGENT} ^Lynx/.* [OR]
RewriteCond %{HTTP_USER_AGENT} ^Mozilla/[12].*
RewriteRule ^foo\.html$ foo.20.html [L]
RewriteRule ^foo\.html$ foo.32.html [L]

Nous allons utiliser la variable « HTTP_USER_AGENT » pour détecter les différents navigateurs pour la page « foo.html ». Dans cet exemple, nous détectons l'utilisation de la 3ème version de Firefox et nous la redirigeons sur la page « foo.NS.html » et nous stoppons la réécriture.

Si le navigateur est Linx ou Mozilla version 1 ou 2, nous affichons la page « foo.20.html ». Sinon, on affiche simplement la page « foo.32.html » par défaut.


Racine du site web déplacée

Habituellement, la racine d'un site web est liée à l'URL « / » (identique à http://www.craym.eu/). Mais parfois, on souhaite que nos visiteurs au lieu d'entrer directement sur le site passent par une section particulière du site comme « /dossier/ » par exemple.

Grâce à l'URL Rewriting, nous pouvons faire cela très facilement avec la règle ci-dessous :


1 2
RewriteEngine on
RewriteRule ^/$ /dossier/ [R]


Déplacer les dossiers racines sur un autre serveur

Beaucoup de webmaster ont demandé la solution à la situation suivante : Ils souhaitent rediriger complètement tous les dossiers d'un site sur un autre serveur.

Cette situation est très courante lorsque l'on met en place une nouvelle version d'un site sur un autre serveur et que l'on souhaite rediriger complètement l'ancien site sur le nouveau en une seul fois.

La solution est très simple. Sur l'ancien serveur, on redirige toutes les requêtes sur le nouveau serveur qui se chargera de les traiter :

1 2
RewriteEngine on
RewriteRule ^/~(.+) http://newserver/~$1 [R,L]
 


Bloquer les robots

Tous les robots ne sont pas bénéfiques pour votre site ! Certains d’entre-eux sont des aspirateurs de site, d’autres collectent les adresses email et finissent par remplir votre boîte aux lettres de spam... bref, certains sont vraiment indésirables !
Ils ont tous une caractéristique commune : utiliser les ressources de votre serveur sans vous apporter aucun visiteur « utile ».

Comment peut-on empêcher un robot persistant de référencer nos pages d'un certain emplacement ? Souvent, le fichier robots.txt n'est pas en mesure de le bloquer complètement car il indique juste au robot de ne pas aller dans une certaine zone de votre site, mais rien ne l'en empêche d'y aller !

Pour résoudre ce problème, nous allons bloquer le robot directement depuis le serveur grâce à une série de règles et au drapeau [F] :

1 2
3
4
RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} ^NameOfBadRobot.*
RewriteCond %{REMOTE_ADDR} ^123\.45\.67\.[8-9]$
RewriteRule ^/~quux/foo/arc/.+ - [F]

Dans cet exemple, nous vérifions que le visiteur est bien le robot en question donc on connait l'IP. Si c'est le cas et que celui-ci demande une page se trouvant dans le dossier « /~quux/foo/arc/ » alors on bloque tout simplement l'envoi de la page et on retourne une erreur « Forbidden » au robot qui sera alors réellement incapable d'afficher la page.


Débarrassons-nous des visiteurs indésirables

Le web est souvent théâtre de nombreux conflits cachés aux yeux des internautes mais qui fait bel et bien rage ! Il s'agit souvent de bloquer des spameurs indésirables, de bloquer certains sites qui volent votre contenu ou carrément d'exclure une IP spécifique après la détection d'une tentative d'intrusion sur votre site.

Nous allons présenter ci-dessous quelques règles pour exclure ces nuisibles :

1 2
3
4
5
6
RewriteEngine on
RewriteCond %{REMOTE_HOST}  \.laurion\.(com|net)$  [OR]
RewriteCond %{REMOTE_HOST} \.cn$ [OR]
RewriteCond %{REMOTE_HOST} ^badhost\.baddomain\.com$ [OR]
RewriteCond %{REMOTE_ADDR}  ^123\.45\.67\.12[5-9]$
RewriteRule ^.*$   -   [F]

La première condition interdit toute visite en provenance de « laurion.com » et « laurion.net ». Cela peut sembler un peu brutal comme règle mais ce robot-aspirateur ne respectant pas le protocole d’exclusion et ne se gênant pas pour « pomper » plus de 100 pages/minutes (merci Spip-contrib) nous n’avons pas vraiment eu envie de mettre de gants le concernant.
La deuxième condition élimine encore plus radicalement tout visiteur provenant de Chine.
La troisième bloque un domaine particulier qui ici est « badhost.baddomain.com ».
Enfin, la dernière règle exclu complètement une plage d'IP de visiteurs nuisibles.

Notez que les règles ci-dessus ne sont que des exemples et ne sont pas dictées par une quelconque xénophobie de la part de l’auteur. Elles ont néanmoins contribué à réduire de manière significative la bande passante utilisée.



Attention aux « répertoires virtuels »

Nous allons mettre en lumière un problème qui va très vite vous être très embêtant. Dans les exemples qui précèdent, nous avons toujours effectué des réécritures qui n’impactaient pas l’arborescence apparente de vos pages.

Nous allons vous montrer cela à travers l'arborescence d'articles. Nous effectuons une requête sur la page :
« http://www.unsite.com/article-10-23.html »

Par exemple, si au lieu d'utiliser cette règle :

1 RewriteRule ^article-([0-9]+)-([0-9]+)\.html$  article.php?numero=$1&page=$2  [L]

nous utilisons :

1 RewriteRule ^article/([0-9]+)/([0-9]+)\.html$  article.php?numero=$1&page=$2  [L]

Alors L’URL apparente aurait la forme «  /article/10/23.html » au lieu de « /article-8126-2.html  ».

Dans ce cas, le navigateur va estimer que la page se trouve dans un répertoire « /article/10/ » qui n’a pas d’existence physique sur votre site. C'est pourquoi lorsque celui-ci va utiliser les liens relatifs pour charger les différentes images/objets de la page, il va effectuer la recherche sur un répertoire qui n'existe pas ! Il affichera donc une erreur.

Pour résoudre ce problème, deux solutions se présentent :

- Soit utiliser des liens absolus, ou mieux...
- Faire usage de la balise <base href="http://www.votresite.tld/repertoire/" > à mettre dans l'entête de votre page, entre <head> et  </head>.



Protégeons nos fichier images

Le vol de la bande passante est chose très courante sur le web. Cela passe souvent inaperçu et est toléré pour des petits montants mais parfois cela prend des proportions gigantesques ! Nous allons donc prévenir tous les sites externes de faire des liens sur nos images.

Cela se fait avec les règles suivantes :

1 2
3
4
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://www.votredomaine.net/.*$ [NC]
ReWriteRule .*\.(gif|png|jpe?g)$ - [F]

Dans cet exemple, nous vérifions que le site qui effectue la demande de l'image est différent de notre site (en faisant abstraction de la casse) et si cela est avéré, alors on refuse tout simplement de délivrer la ressource image.

Note : certains navigateurs permettent de masquer le « HTTP_REFERER », et certains proxies ou firewall ne transmettent pas cette référence.
C’est la raison pour laquelle nous avons la première condition testant si la variable « HTTP_REFERER » n’est pas vide. Sans cette règle, les visiteurs derrière certains firewall ou proxies ne verraient pas vos images.
Cette dernière limitation démontre bien qu’il n’est pas possible d’éliminer 100% des liens sauvages vers vos images puisqu’il suffit de masquer le HTTP_REFERER pour éviter l’interdiction. Une élimination de 95-98% des liens représente déjà une économie substantielle de bande passante.

Toutefois, vous souhaiterez parfois autoriser certains domaines amis à faire des liens directs, pour cela, il suffit d’ajouter pour chacun d’eux une condition supplémentaire :

1 RewriteRule RewriteCond %{HTTP_REFERER} !^http://undomaineami.net/.*$ [NC]

Enfin, il existe encore une faille dans cet exemple car l'on peut toujours accéder au images si l'on omet le « www » devant le nom de domaine. Un simple « (www)? » permettra de la corriger !

Piouf ! Quel énorme quantité d'information ! Cela fait presque trop pour une seule lecture !

N'hésitez pas à relire plusieurs fois chaque partie pour vous aider à en saisir toutes les subtilités !

Félicitations ! Vous êtes arrivé à la fin de ce tutoriel ! Merci d'avoir pris le temps de nous lire !