URL Rewriting - Les drapeaux


Les règles de réécritures des URL sont nombreuses peuvent être utilisées de manières très différentes ! Ceci est encore plus vrai lorsque l'on ajoute des règles spéciales à celles-ci.

Ce tutoriel vient en appui du de l'URL Rewriting dont nous parlons ici : Tutoriel sur l'URL Rewriting. C'est une seconde partie très importante car les drapeaux dont nous allons parler ci-dessous sont très puissants et permettent de complètement changer le comportement de nos règles de réécriture, de l'optimiser ou de faire complètement planter le serveur il est donc important de comprendre précisément leurs rôles.

Suivez le guide !

Les flags ou drapeaux


A la fin de certaines règles de réécriture, on trouve des petites chaines comme celle-ci : « [C] », « [L] » ou encore « [R=301] ». Que signifient-elles ?

Ces chaînes servent à spécifier des actions que doit suivre le serveur lors de la réécriture. Celles-ci sont particulièrement importantes lorsque vous commencer à réécrire des URLs.

Nous allons détailler-ci-dessous les drapeaux disponibles. Certains sont plus utiles que d'autres mais ils ont tous un pouvoir important. Nous essaierons de ponctuer notre parcours d'exemple afin de bien comprendre l'utilisation de ceux-ci.

Notez que vous pouvez les combiner en les séparants par une virgule simple comme par exemple :[G,NC] ».

Drapeaux de « RewriteRule » :


Drapeaux de « RewriteCond » :

 

Suivez le guide ! Les drapeau de RewriteRule


Tous les drapeaux ci-dessus sont utilisables après une règle « RewriteRule ». Les drapeaux concernant « RewriteCond » sont détaillés plus bas.

Drapeau Description
[B] - Escape

Les URLs doivent être non échappées pour pouvoir être comparées par Apache, si bien que les références arrières renverront une valeur non échappée au moment où elles seront appliquées.
Utiliser le drapeau [B] forcera l'échappement des caractères non alphanumériques des références arrières.

Par exemple, considérons la règle suivante :

1 2 RewriteEngine On
RewriteRule ^(.*)$ index.php?show=$1
 

Si dans la variable « show », nous passons le paramètre « /C++ ». La règle va faire correspondre « /C++ » à « index.php?show=/C++ » mais elle va aussi faire correspondre « /C%2b%2b » à « index.php?show=/C++ », car le caractère « %2b » n'aura pas été échappé.

Par contre, avec le drapeau [B], la substitution s'effectuera bien vers l'URL « index.php?show=/C%2b%2b ».

Ce processus d'échappement est particulièrement nécessaire lorsque l'adresse d'arrière-plan ne fonctionnera pas si elle se présente sous une forme non échappée.

[C] - Chain

Le drapeau [C] ou [chain] indique que la RewriteRule est liée à la suivante. C'est-à-dire que si la règle de réécriture correspond, alors il l'applique et évalue la suivante. Si ce n'est pas le cas, il va tout simplement sauter la règle ainsi que toutes les autres liées à celle-ci.

[CO] - Cookie

Le drapeau [CO] ou [cookie] permet de poser un cookie lorsqu'une règle de réécriture particulière correspond. L'argument correspond à trois champs requis et deux optionnels séparés par des « : »

Les 3 premiers correspondent respectivement au nom du cookie, sa valeur et le domaine auquel il est rattaché. Les deux champs optionnels correspondent au temps de vie du cookie et l'URL ou il sera disponible.

Par défaut, la durée de vie du cookie est la durée de session du navigateur (le cookie disparait lorsque l'on ferme le navigateur)

Voici un exemple :

1 2 RewriteEngine On
RewriteRule ^/index.html - [CO=frontdoor:yes:.craym.eu:1440:/]

Notez que cette règle ne réécrit pas l'URL, le « - » comme cible de réécriture indique qu'il ne faut pas changer l'URL mais poser un cookie appelé « frontdoor » avec comme value « yes ». Il est valide sur le domaine « cryam.eu » et expire dans 1440 minutes (24 heures). Il sera retourné pour n'importe quel URL sur le site.

[E] - Environnement

Avec [E] ou [env], vous pouvez attribuer des valeurs à des variables d'environnement. Notez que certaines variables seront réellement affectées après que la règle ait été appliquée et en conséquence, seront peut-être obsolètes.

Dans l'exemple suivant, nous attribuons une variable d'environnement « image » dont la valeur sera 1 si l'URL demandé est une image. Puis, cette variable est utilisée pour exclure la requête des logs d'accès.

1 2 3 RewriteEngine On
RewriteRule \.(png|gif|jpg) - [E=image:1]
CustomLog logs/access_log combined env=!image

Notez que vous pouvez obtenir le même effet en utilisant « SetEnvIf ». Cette technique est donné à titre d'exemple mais nous ne la recommandons pas.

[F] - Forbidden

Utiliser le drapeau [F] forcera le serveur à retourner une erreur 403 : Accès interdit au client. Vous pouvez obtenir le même comportement en utilisant l'instruction « Deny ». Celle-ci permettra une plus grande flexibilité dans l'accès au fichier.

La règle suivante interdira de télécharger der fichiers « .exe » de votre serveur.

1 2 RewriteEngine On
RewriteRule \.exe - [F]

Comme tout-à-l'heure, nous utilisons le « - » pour ne pas modifier l'URL. De toute manière, nous allons l'interdire d'accès.

[G] - Gone

Le drapeau [G] force le serveur à renvoyer une erreur 410 : La ressource n'est plus disponible et aucune adresse de redirection n'est connue.

Comme le drapeau [F], nous utilisons le « - » pour ne pas modifier l'URL.

1 2 RewriteEngine On
RewriteRule oldproduct - [G,NC]
[H] - Handler

Force la requête à être traitée avec le type spécifié. Par exemple, on peut forcer le serveur à traiter tous les fichiers sans extension comme tétant des fichiers « .php »

1 2 RewriteEngine On
RewriteRule !\. - [H=application/x-httpd-php]

L'expression régulière « !\. » sera valide pour toute requêtes ne contenant pas le caractère point « . »

[L] - Last

Le drapeau [L] Last qui signifie dernier stoppera le processus de réécriture à la fin de l'instruction. La plupart du temps, cela signifie que la règle d'écriture a été trouvée et qu'il n'y a pas besoin d'exécuter les suivantes.

Si vous utilisez les règles de réécriture avec un fichier « .htaccess », il est important de comprendre comment fonctionnent les règles de réécriture. Le plus simple est qu'une fois qu'une règle a été appliquée à l'URL, il est possible que toutes les règles soient revérifiées depuis le début (cela dépend de la configuration du serveur). La nouvelle URL correspondra alors peut-être à une autre règle qui là encore s'appliquera ce que l'on ne souhaite certainement pas.

Il est donc très important pour éviter ces boucles de réécriture de préciser la dernière instruction à exécuter en cas de correspondance.

L'exemple ci-dessous réécrira toutes les requêtes URL comme étant un argument passé au fichier « index.php ». Si la requête est directement « .index.php », cette règle sera sautée.

1 2 3 RewriteEngine On
RewriteCond %{REQUEST_URI} !index\.php
RewriteRule ^(.*) index.php?req=$1 [L]
[N] - Next

Le drapeau [N]ou [next] permet de recommencer la réécriture depuis le début après que la règle ait été appliquée. Attention ! A utiliser avec précision car peut résulter en une boucle infinie !

Il peut-être utilisé par exemple pour remplacer récursivement une lettre dans une requête. L'exemple ci-dessous montre comment A va être remplacé B partout dans la requête.

1 2 RewriteEngine On
RewriteRule (.*)A(.*) $1B$2 [N]

La règle se pense comme ceci : « Tant qu'il existe A dans la requête, le remplacer par B »

[NC] - Nocase

L'utilisation du drapeau [NC] permet d'ignorer la casse d'une règle de réécriture c'est-à-dire que le serveur ne va pas se soucier des lettres en majuscule ou minuscule, tout sera traité en minuscule.

L'exemple ci-dessous montre que toute requête pour une image sur votre site va être redirigé sur le serveur dédié aux images. La casse n'est pas prise en compte de tel manière que « .jpg » et « .JPG » sont identiques.

1 2 RewriteEngine On
RewriteRule (.*\.(jpg|gif|png))$ http://images.example.com$1 [P,NC]
[NE] - No escape

Par défaut, les caractères spéciaux tel que « # » ou « ? » seront convertis par leur code hexadécimal équivalent : « # » deviendra « %23 ». Utiliser le drapeau [NE] permet d'éviter cette conversion.

1 2 RewriteEngine On
RewriteRule ^/anchor/(.+) /bigpage.html#$1 [NE,R]

L'exemple ci-dessus redirigera les fichiers du dossier « anchor » sur « bigpage.html » en ajoutant une ancre qui prend pour valeur ce que l'on cherche dans le dossier « anchor ». On évite de convertir le caractère « # » en « %23 » pour ne pas obtenir une erreur 404 car le fichier « bigpage.html%23...» n'existe pas.

[NS] - Nosubreq

L'utilisation du drapeau [NS] permet d'éviter que la règle ne soit utilisée pour des requêtes secondaires. Par exemple, une page qui est créée en utilisant un SSI (Server Side Include) est une requête secondaire

Les images, fichiers javascript, css sont chargées comme des pages HTML et ne sont pas des requêtes secondaires. Le navigateur va les demander comme des requêtes HTML séparées.

[P] - Proxy

Utiliser le drapeau [P] obligera le serveur à traiter la requête par le module « mod_proxy » qui sera traité et renvoyé à un proxy.

Par exemple, si vous souhaitez que toutes les requêtes d'images soient traitées par un serveur qui traite spécifiquement ces requêtes, vous pouvez utiliser la règle ci-dessous :

1 2 RewriteEngine On
RewriteRule (.*)\.(jpg|gif|png) http://images.example.com$1.$2 [P]

Utiliser le drapeau [P] implique automatiquement l'utilisation du drapeau [L]. La requête sera redirigée sur le proxy et toutes les autres règles seront ignorées.

[PT] - PassThrough

Par défaut, la requête dans la règle de réécriture sera traitée comme étant un chemin de fichier. L'utilisation du drapeau [PT] obligera le serveur à la traiter comme une nouvelle URL c'est-à-dire que l'URL généré sera réévalué. Cela permet que certaines règles comme les « alias » soient traitées.

Pour l'exemple, vous avez un Alias pour « /icons » et une règle de réécriture sur les images. On utilise [PT] pour s'assurer que la règle soit évaluée.

1 2 3 RewriteEngine On
Alias /icons /usr/local/apache/icons
RewriteRule /pics/(.+)\.jpg /icons/$1.gif [PT]

Si on omet ici le [PT], cela provoquera une erreur 404: Fichier non trouvé.

[QSA] - Qsappend

Lorsque l'URL de requête possède des arguments, le comportement par défaut de l'engine de RewritingRule est de supprimer ces arguments et des les remplacer par leurs homologues générés lors de la réécriture.

Le drapeau [QSA] oblige le serveur à combiner ces paramètres à l'URL.

Détaillons l'exemple ci-dessous :

1 2 RewriteEngine On
RewriteRule /pages/(.+) /page.php?page=$1 [QSA]

Grâce au drapeau [QSA], la requête effectuée sur la page « /pages/123?one=two » sera redirigée sur « /pages.php?page=123&one=two ».

Si l'on avait omit le [QSA], le serveur aurait redirigé la page sur « /page.php?page=123 » en supprimant tout simplement les arguments.

[R] - Redirect

L'utilisation du drapeau [R] provoquera une redirection du navigateur. Si l'URL de requête est pleinement renseignée (en incluant le http://servername/ ) alors la redirection sera effectuée sur cette adresse. Sinon, le nom serveur courant (le site sur lequel s'exécute cette règle) sera utilisé pour générer l'URL.

Vous pouvez spécifier un code de statut allant de 300 à 399 comme par exemple « [R=301] ». La liste des erreurs courantes est disponible sur le tutoriel des erreurs du web. Par défaut, s'il n'est pas spécifié, le statut est « [R=302] ».

La plupart du temps, vous utiliserez ce drapeau combiné avec [L] soit [R, L] car utilisé seul, la règle sera appliquée, le code de statut envoyé mais le reste des règles sera évalué ce qui souvent provoque un avertissement : « Invalid URL in request ».

[S] - Skip

Le drapeau [S] est utilisé pour sauter une instruction que vous ne souhaitez pas exécuter. On peut le voir comme étant une instruction « Goto »au milieu de vos règles de réécriture.

1 2 3 4 5 6 7 # On vérifie si le fichier n'existe pas
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Si oui, alors on saute simplement les deux instructions suivantes
RewriteRule .? - [S=2]
RewriteRule (.*\.gif) images.php?$1
RewriteRule (.*\.html) docs.php?$1

Cette technique est très utile car une instruction « RewriteCond » ne prend effet que pour l'instruction « RewriteRule » qui suit. C'est pourquoi, si vous souhaitez qu'une « RewriteCond » s'applique à plusieurs « RewriteRule », une technique possible est de sauter jusqu'à la règle souhaitée en utilisant le drapeau [S]

[T] - Type

Ce drapeau permet de changer le type MIME (Multimedia Internet Media Extension) de la réponse. Il a le même effet que l'instruction « AddType ».

Comme premier exemple, vous pouvez utiliser cette instruction pour retourner du code source Perl comme étant du texte basique :

1 2 RewriteEngine On
RewriteRule \.pl$ - [T=text/plain]

Si vous avez un appareil photo qui produit des images sans extensions, vous pouvez forcer le serveur à vous renvoyer les fichiers sans extension avec le bon type MIME en virtualisant leur nom :

1
2
RewriteEngine On
RewriteRule IMG - [T=image/jpg]

Vous devrez toujours utiliser le « - » pour ce type de réécriture pour éviter la perte du drapeau suite à des processus internes de réécriture. Le drapeau [L] peut aussi être utile pour stopper le processus à la fin de la règle et ainsi s'assurer la bonne mise en oeuvre de celle-ci.



Suivez le guide ! Les drapeau de RewriteCond


Il existe deux drapeaux que vous allez utiliser très souvent lors de vos conditions : [RC] et [OR] :

Drapeau Description
[NC] - No case

Est identique à celui de « RewriteRule ».

[OR] - Ornext

Ce drapeau est très utile car permet de combiner plusieurs conditions avec un « or » au lieu du « and » appliqué par défaut.

Cela signifie que le serveur va évaluer les deux conditions et appliquer la règle si au moins une des deux conditions est respectée alors que normalement, si la première condition n'est pas respectée, le serveur saute tout le bloc et la deuxième condition n'est même pas évaluée.

1 2
3
RewriteEngine On
RewriteCond %{HTTP_HOST} ^localhost [OR]
RewriteCond %{HTTP_HOST} ^remotehost

Ici nous testons si le nom du serveur demandé dans la requête est « localhost » OU « remotehost ».

[NV] - novary

Grâce aux variables d'URL Rewriting, vous pouvez tester si la requête contient un certain en-tête HTTP. Si cela est le cas, la réécriture a pour habitude d'ajouter ce drapeau à la requête réécrite.

Ce drapeau empêche ce dernier d'être ajouté à l'en-tête Vary de la réponse.

Attention tout de même, l'utilisation de ce drapeau peut provoquer une mise en cache incorrecte de la réponse, si la représentation de cette réponse varie avec la valeur de l'en-tête considéré. Ce drapeau ne devrait donc être utilisé que si l'on maîtrise parfaitement le fonctionnement de l'en-tête Vary.


Piouf ! Voilà qui est fait ! Le nombre de drapeaux disponibles est vraiment impressionnant mais rassurez-vous, vous aller très souvent utiliser les mêmes !

Vous pouvez maintenant retourner sur le tutoriel sur l'URL Rewriting ou lire un de nos autres tutoriels ici : Liste des tutoriels.

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