
Une des fonctions les plus puissantes permises par le fichier .htaccess est la réécriture « à la volée » des URL. Sur le site officiel Apache, le module mod_rewrite est présenté à raison comme le couteau suisse de la manipulation.
Il est utile de préciser que certains hébergeurs n’ont pas activé le module de réécriture. Dans ce cas, vous n’avez malheureusement aucune possibilité de l’utiliser, à moins de casser le petit cochon en porcelaine qui traîne chez vous et changer d’hébergeur.
Ce module est implémenté dans le fichier mod_rewrite.c, à partir de la version 1.2 d'Apache. Il fournit un interpréteur de règles dont l'action est de réécrire "au vol" les URL requises. mod_rewrite n'est pas compilé par défaut. Pour exploiter ce module, vous devez ajouter les lignes suivantes dans le fichier Configuration de configuration de compilation :
AddModule modules/standard/mod_rewrite.o
Résumé
Ce module utilise une fonction de réécriture configurable par règles (construit à partir d'un interpréteur d'expressions régulières) pour réécrire au vol des URL.
Il accepte un nombre illimité de règles supplémentaires (qui peuvent apérer sur un grand nombre de variables, dont les en-têtes HTTP) pouvant rechercher ds correspondances granulaires et rechercher des données dans des bases de données externes (soit par des tables plates, des fichiers associatifs DBM ou des processus externes), aboutissant à de puissantes fonctions de substitution d'URL.
Il traite l'URL dansson intégralité (y compris la partie PATH_INFO) à la fois dans le contexte serveur (httpd.conf) que dans chacun des contextes locaux de répertoires (.htaccess) et peut générer des parties QUERY_STRING (arguments de requêtes situés derrière le '?')à partir de ses résultats. L'URL résultante peut alors être conservée pour un nouveau traitement interne, une redirection externe ou un transfert vers un proxy interne.
La première écriture de ce module a été réalisée en Avril 1996 et offerte confidentiellement au groupe Apache en Jullet 1997 par
Directives
- RewriteEngine
- RewriteOptions
- RewriteLog
- RewriteLogLevel
- RewriteMap
- RewriteBase
- RewriteCond
- RewriteRule
Directives de configuration
Directive : RewriteEngine
Défaut :
RewriteEngine offContexte : configuration serveur, hôtes virtuels, répertoire, .htaccess
La directive RewriteEngine active ou désactive le moteur de réécriture. Sur off ce module n'effectue aucun traitement. Il ne modifie pas même les variables d'environnement SCRIPT_URx.
Utilisez cette directive pour désactiver entièrement ce module plutôt que passer en commentaires toutes les directives RewriteRule !
Notez que, par défaut, les configurations de réécriture ne sont pas héritées à partir du serveur principal. Ceci signifie que vous devrez avoir une directive RewriteEngine on pour tous les hôtes virtuels dans lesquels vous souhaiter activer cette fonctionnalité, à moins que l'option RewriteOptions inherit soit définie.
Directive : RewriteOptions
Défaut : Aucun
Contexte : configuration serveur, hôtes virtuels, répertoire, .htaccess
La directive RewriteOptions commute certaines options spéciales pour la configuration de contexte serveur ou répertoire courante. Les chaînes Option peuvent être l'un parmi :
inherit
Ceci force la configuration courante d'hériter de la configuration du parent. Dans un contexte d'hôtes virtuels, ceci signifie que les tables, conditions et règles du serveur principal sont héritées par l'hôte virtuel. Dans un contexte de répertoire, ceci signifie que les conditions et règles sont héritées à partir de celles définies dans le fichier.htaccessdu répertoire père.
Directive : RewriteLog
Défaut : Aucun
Contexte : configuration serveur, hôtes virtuels
La directive RewriteLog déinit le nom du fichier dans lequel le serveur tracera toutes les actions de réécriture qu'il effectuera. Si le nom ne débute pas par un slash ('/') alors le chemin d'accès spécifié l'est relativement à Server Root. Cette directive ne doit apparaître qu'une fois par configuration de serveur.
Pour désactiver la trace des opérations de réécriture, il est déconseillé donner à nomFichier la valeur /dev/null. En effet, bien que le moteur de réécriture ne produise pas le fiochier de trace, il continue à générer ses informations en interne. Le serveur serait donc ralenti, sans rien apporter de plus à l'administrateur !. Pour désactiver complètement la trace, supprimez totalement la directive RewriteLog (ou mettez-la en commentaire), ou utilisez la directive RewriteLogLevel 0 !
Exemple
RewriteLog "/usr/local/var/apache/logs/rewrite.log"
Directive : RewriteLogLevel
Défaut :
RewriteLogLevel 0Contexte : configuration serveur, hôtes virtuels
La directive RewriteLogLevel définit le degré de "bavardise" de la trace d'actions de réécriture. Le degré 0 (par défaut) singifie pas de trace du tout, tandis qu'avec un degré de 9 ou plus, pratiquement toutes les actions seront tracées.
Pour désactiver complètement la trace, d"finissez simplement un degré 0 pour la trace. Aucune trace ne sera générée dans ce cas.
Note : Une très grande valeur du degré ralentira le serveur Apache dramatiquement ! Ces valeurs ne sont proposées que pour des phases de déboguage. Le dégré sur un serveur opérationnel ne devra pas dépasser 2 !
Exemple :
RewriteLogLevel 3
Directive : RewriteMap
RewriteMap nomTable txt|dbm|prg: nomFichierDéfaut : Non utilisé pour le défaut
Contexte : configuration serveur, hôtes virtuels
La directive RewriteMap définit une table de réécriture externe qui peut être exploitée dans les instructions de substitution spécifiées dans les règles de réécriture via des fonctions de correspondance qui insèreront/substitueront des champs sur contrôle d'une clef.
nomTable est le nom de la table qui sera utilisée pour définir une fonction de correspondance utilisée par les chaînes de substitution d'une règle de réécriture via
${nomTable : Clef | DefaultValue }
Lorsqu'une telle directive intervient, la table nomTable est consultée et la clef Clef y est recherchée. Si cette clef est trouvée, la fonction de correspondance utilise la valeur SubstValue (voir ci-dessous) pour la substitution. Si elle n'est pas trouvée, c'est DefaultValue qui sera prise en compte.
NomFichier doit être un chemin d'accès Unix valide, pointant vers un fichier de l'un des formats suivants :
Format texte brut
Un fichier ASCII qui contient des lignes vides, des lignes de commentaires (lorsqu'elles commencent par un '#') ou des paires : Clef SubstValue
à raison de une paire par ligne. Vous pourrez créer ces fichier manuellement, avec votre éditeur favori, ou en utilisant les programmes mapcollect et mapmerge dans le répertoire /support de la distribution du module mod_rewrite.
Pour déclarer une telle table, obtenue à partir d'un fichier nomFichier ASCII écrit ainsi :
# # map.real-to-user -- maps realnames to usernames # Ralf.S.Engelschall rse # Bastard Operator From Hell Dr.Fred.Klabuster fred # Mr. DAU
vous appellerez ce fichier en utilisant le préfixe txt: :
RewriteMap real-to-host txt:/path/to/file/map.real-to-user
Fichier associatif au format DBM
Il s'agit d'un fichier NDBM binaire contenant le même contenu que le fichier texte. Vous pouvez créer un tel fichier avec n'importe quel outil NDBM ou par le programme dbmmanage livré dans le sous-répertoire /support de la distribution Apache.
Pour déclarer un tel fichier, préfixez nomFichier par dbm:.
Format programme
Il s'agit d'un exécutable Unix, et non d'un fichier de données. Vous pouvez l'écrire dans le language de votre choix, pourvu que l'exécutable produit soit un binaire exécutable sous Unix (c'est-à-dire un fichier objet ou un script routé vers son interpréteur par la formule "magique" '#!/chemin/interpreteur' inscrite en première ligne. Ex. #/usr/bin/perl).
Ce programme est démarré une fois au lancement d'Apache et communique avec le moteur de réécriture par ses entrées et sorties standard stdin et stdout. Pour chacune des recherches demandées par une fonction de correspondance, il recevra la clef à rechercher sous forme d'un chaîne terminée par un caractère Newline dans stdin. Il devra retourner la valeur résultat sous la même forme dans stdout ou la chaîne à quatre caractères "NULL" s'il échoue (c'est-à-dire, qu'il n'existe pas de valeur correspondante à cette clef). Un programme trivial implémentant une correspondance 1:1 (c'est-à-dire qu'à une clef correspond une valeur unique) pourrait s'écrire :
#!/usr/bin/perl
$| = 1;
while (<STDIN>) {
# ...implémenter ici toute transformation
# ou recherche...
print $_;
}
Faites cependant très attention
- "Garder ce programme aussi simple que possible, voire stupide" , car si ce programme se bloque, c'est tout le serveur Apache qui peut se bloquer lors de l'examen d'une règle.
- Evitez une erreur courante : n'utilisez jamais le mode bufferisé des I/O sur
stdout! C'est la meilleure manière de tout bloquer ! D'où la ligne "$|=1" de l'exemple ci-dessus...
Pour déclarer un tel fichier, préfixez nomFichier par prg:.
Pour finir
La directive RewriteMap peut être utilisée plusieurs fois. Pour chaque fonction de correspondance, utilisez une directive RewriteMap afin de déclarer sa table de réécriture. Bien que vous ne puissiez pas déclarer ces tables dans le contexte de répertoire, il sera néanmoins bien sûr possible d'utilisez ces tables dans ce niveau de contexte.
Pour les formats texte et DBM, les clefs de recherche restent enregistrées dans la mémoire du noyau jusqu'à ce que la valeur mtime de la table change ou le serveur redémarre. De cette manière vous pouvez définir des fonctions de correspondance de règles qui seront valables toutes les requêtes. Ce n'est pas un problème, car les résolutions externes n'interviennent qu'une fois !
Directive : RewriteBase
RewriteBase BaseURLDéfaut : le chemin d'accès physique
Contexte : répertoire, .htaccess
La directive RewriteBase définit explicitement l'URL de base pour les réécritures par répertoire. Comme vous pourrez le voir ci-après, RewriteRule peut être utilisée dans des fichiers de contexte répertoire par répertoire (.htaccess). Dans ce cas, son action sera localisée, c'est-à-dire, la partie de chemin d'accès correpondant à ce répertoire est enlevée et la règle de réécriture n'agit que sur ce qui reste. Après la réécriture, la partie répertoire est ajoutée de nouveau en tête du résultat.
Lorsqu'une nouvelle URL est substituée, ce module doit réinjecter l'URL dans le serveur. Pour ce faire, il devra savoir quel est le préfixe ou la base. Par défaut, ce préfixe est le chamin d'accès à la ressource elle-même. Mais dansla plupart des sites, les URL NE correspondent PAS directement au chemin physique, et cette supposition "par défaut" sera en général erronée ! C'est dans ce cas que vous devez utiliser la directive RewriteBase pour définir le préfixe URL.
De ce fait, si les URL sur votre site Web NE sont PAS en correspondance directe avec les chemins d'accès physiques des fichiers, vous devrez utiliser une directive RewriteBase dans chacun des fichiers .htaccess où vous souhaitez utiliser des directives RewriteRule.
Exemple : Supposons que nous disposions du fichier de configuration suivant dans un répertoire :
# # /abc/def/.htaccess -- configuration pour le répertoire /abc/def # Se souvenir que : /abc/def est le chemin physique pour /xyz, c'est-à-dire que le # serveur a une directive 'Alias /xyz /abc/def' # RewriteEngine On # indiquons au serveur que nous sommes atteint via /xyz et non par # le préfixe de chemin physique /abc/def RewriteBase /xyz # les règles de réécriture RewriteRule ^oldstuff\.html$ newstuff.html
Dans l'exemple ci-dessus, une requête vers /xyz/oldstuff.html sera réécrite pour pointer sur le fichier d'adresse physique /abc/def/newstuff.html.
Pour les bidouilleurs d'Apache :
La liste suivante donne des informations détaillées sur les étapes de traitement interne :
Requête : /xyz/oldstuff.html Traitement interne : /xyz/oldstuff.html -> /abc/def/oldstuff.html (Aliasing de contexte serveur) /abc/def/oldstuff.html -> /abc/def/newstuff.html (RewriteRule de contexte répertoire) /abc/def/newstuff.html -> /xyz/newstuff.html (RewriteBase de contexte répertoire) /xyz/newstuff.html -> /abc/def/newstuff.html (Aliasing de contexte serveur) Résultat : /abc/def/newstuff.html
Ceci semble bien compliqué mais représente bien le comportement interne d'Apache, parce que la réécriture de niveau répertoire intervient assez tard dans la chaîne de traitement. De plus, lorsque la réécriture intervient, la requête obtenue doit être re-injectée dans le kernel Apache ! En fait, il n'y a pas de réel problème dans la mesure ou cette ré-injection est complètement interne, et que le même mécanisme est déjà utilisé de longue date dans le serveur, pour preuve de sa stabilité.
Directive : RewriteCond
RewriteCond TestString CondPatternDéfaut : Aucun
Contexte : configuration serveur, hôtes virtuels, répertoire, .htaccess
La directive RewriteCond définit une condition d'application de la règle. Vous ferez précéder une directive RewriteRule par une ou plusieurs directives RewriteCond. La règle de réécriture qui suit ces conditions n'est applisuée que si son motif correspond à l'URI de la requête ET si ces conditions supplémentaires ainsi définies sont remplies.
TestString est une chaîne contenant les constructions suivantes et du texte brut :
-
Rétroréférence sur la RewriteRule: Ce sont des références sous la forme
$N(1 <= N <= 9) par lesquelles on peut récupérer la valeur de sous-motif (parenthésé !) du motif défini dans la règle
RewriteRuleassociée (celle qui suit le présent groupe de directivesRewriteCond), après application du motif. -
Rétroréférence sur la RewriteCond: Ce sont des références sous la forme
%N(1 <= N <= 9) par lesquelles on peut récupérer la valeur de sous-motif (parenthésé !) du motif trouvé lors de l'application par la dernière directive
RewriteConddu bloc de conditions courant.NdT : La compréhension de ces deux références demandent une bonne connaissance des expressions régulières et de leur fonctionnement. Une expression régulière permet de définir un motif de correspondance, appliqué à une portion de texte ASCII. Ce motif peut comprendre des sous-motifs, lesquels seront extraits individuellement lors de l'application du motif complet. Le résultat de ces extraction est usuellement rangé (sous Unix) dans des variables prédéfinies notées $1 à $9. Ces deux références utilisent ce principe pour réutiliser les sous-motifs obtenus par les applications successives des motifs de chaque condition (références %N), ou de la règle associée (références $N).
-
Variables-serveur: Ce sont des variables sous la forme
%{NOM_DE_VARIABLE}dans laquelle NOM_DE_VARIABLE peut être une chaîne à prendre dans la liste suivante :
En-têtes HTTP HTTP_USER_AGENT
HTTP_REFERER
HTTP_COOKIE
HTTP_FORWARDED
HTTP_HOST
HTTP_PROXY_CONNECTION
HTTP_ACCEPTconnexion & requête REMOTE_ADDR
REMOTE_HOST
REMOTE_USER
REMOTE_IDENT
REQUEST_METHOD
SCRIPT_FILENAME
PATH_INFO
QUERY_STRING
AUTH_TYPEVariables internes du serveur DOCUMENT_ROOT
SERVER_ADMIN
SERVER_NAME
SERVER_PORT
SERVER_PROTOCOL
SERVER_SOFTWARE
SERVER_VERSIONVariables système TIME_YEAR
TIME_MON
TIME_DAY
TIME_HOUR
TIME_MIN
TIME_SEC
TIME_WDAY
TIMEVariables spéciales API_VERSION
THE_REQUEST
REQUEST_URI
REQUEST_FILENAME
IS_SUBREQCes variables correspondend toutes aux noms de champs d'en-tête HTTP, aux variables C du serveur Apache ou aux champs de la structure
struct tmdu système Unix.
Notes spéciales :
- Les variables SCRIPT_FILENAME et REQUEST_FILENAME contiennent la même valeur, à savoir, la valeur du champ
filenamede la structure C internerequest_recdu serveur Apache. Le premier nom de variable correspond au nom usuel de la variable CGI tandis que le second est la contrepartie de la variable REQUEST_URI (correspondant au contenu du champuridans la structurerequest_rec). - On pourra utiliser le format spécial :
%{ENV:variable}dans lequel variable peut être tout nom de variable d'environnement. Cette variable sera recherchée dans les structures de données internes d'Apache ou (si elle n'y est pas trouvée) via la fonction Cgetenv()exécutée par le processus serveur d'Apapche. - On pourra également utiliser le format spécial :
%{HTTP:header}dans lequel header peut être tout nom MIME de champ d'en-tête HTTP. Sa valeur est obtenue à partir de la requête HTTP. Exemple :%{HTTP:Proxy-Connection}récupère la valeur du champ d'en-tête HTTP "Proxy-Connection:". - On notera un autre format spécial :
%{LA-U:url}pour des résolutions internes sur URL. Son utilisation déclenche une sous-requête interne pour connaître l'URL finale pour l'URL url. - On définit un dernier format spécial :
%{LA-F:fichier}pour des résolutions internes sur fichier. Son utilisation déclenche une sous-requête interne pour connaître la valeur finale de fichier.
CondPattern est le motif définissant la condition, c'est-à-dire une expression régulière à appliquer à la valeur courante de TestString, c'est à dire que TestString sera évaluée et le motif CondPattern y sera recherché.
Souvenez-vous : CondPattern est une expression régulière étendue standard avec quelques ajouts :
- Vous pouvez faire précéder la chaîne de motif par '
!' (point d'exclamation) pour inverser le sens du test (la condition est vraie si le motif n'est pas trouvé). -
Il existe certaines variantes particulières de CondPatterns. A la place d'une chaîne d'expression régulière, vous pourrez utiliser l'une des expression suivantes :
- '<CondPattern' (est lexicographiquement inférieur à)
Traite CondPattern comme une chaîne de texte brut et la compare lexicographiquement à TestString. Le résultat est vrai si TestString est lexicographiquement inférieur à CondPattern. - '>CondPattern' (est lexicographiquement supérieur à)
Traite CondPattern comme une chaîne de texte brut et la compare lexicographiquement à TestString. Le résultat est vrai si TestString est lexicographiquement supérieur à CondPattern. - '=CondPattern' (est lexicographiquement égal à)
Traite CondPattern comme une chaîne de texte brut et la compare lexicographiquement à TestString. Le résultat est vrai si TestString est lexicographiquement égal à CondPattern, c'est-à-dire que les deux chaînes sont rigoureusement églaes (caractère par caractère). Si CondPattern se limite à""(la chaîne vide), TestString est comparé (logiquement) à la chaîne vide. - '-d' (est un répertoire : ddirectory)
Considère TestString comme un chemin d'accès et teste si l'objet existe et est un répertoire. - '-f' (est un fichier normal : file)
Considère TestString comme un chemin d'accès et teste si l'objet existe et est un fichier normal (c'est à dire ni un répertoire, ni un lien symbolique). - '-s' (est un fichier normal non vide : sized file)
Considère TestString comme un chemin d'accès et teste si l'objet existe et est un fichier normal (c'est à dire ni un répertoire, ni un lien symbolique) et est de taille non nulle. - '-l' (est un lien symbolique : link)
Considère TestString comme un chemin d'accès et teste si l'objet existe et est un lien symbolique. - '-F' (est un fichier existant, via une sous-requête)
Vérifie si TestString représente un fichier valide et accessible compte tenues toutes les restrictions d'accès configurées pour ce serveur et ce chemin d'accès. Cette expression lance une sous-requête interne pour tester cet état, et il est prudent de l'utiliser avec parcimonie car elle diminue les performances globales du serveur ! - '-U' (is existing URL via subrequest)
Vérifie si TestString représente une URL valide et accessible compte tenues toutes les restrictions d'accès configurées pour ce serveur et ce chemin d'accès. Cette expression lance une sous-requête interne pour tester cet état, et il est prudent de l'utiliser avec parcimonie car elle diminue les performances globales du serveur !
Note : Tous ces tests peuvent être préfixés du caractère ('!') pour en inverser le sens d'interprétation. - '<CondPattern' (est lexicographiquement inférieur à)
Vous pouvez de plus ajouter certains commutateurs au CondPattern en ajoutant un troisième argument :
[flags]à la directive RewriteCond. Flags est une liste de commutateurs ci-après définis séparés par des virgules :
- '
nocase|NC' (Pas de casse : no case)
La casse est indiférente dans ce cas, c'est-à-dire qu'il n'y aura aucune différence entre les lettres 'A-Z' et 'a-z', que ce soit dans la chaîne TestString ou CondPattern. -
'
ornext|OR' (ou condition suivante)
Utilisez ce commutateur pour lier deux conditions dans un OU local plutôt que le ET implicite. Exemple typique :RewriteCond %{REMOTE_HOST} ^hôte1.* [OR] RewriteCond %{REMOTE_HOST} ^hôte2.* [OR] RewriteCond %{REMOTE_HOST} ^hôte3.* RewriteRule ...la règle vaut pour l'un de ces trois hôtes...Sans l'existance de ce commutateur vous auriez du écrire trois fois l'ensemble des conditions plus la règle.
Exemple :
Pour réécrire la Homepage d'un site suivant la valeur du champ User-Agent: de la requête, vous pouvez utiliser les écritures suivantes :
RewriteCond %{HTTP_USER_AGENT} ^Mozilla.*
RewriteRule ^/$ /homepage.max.html [L]
RewriteCond %{HTTP_USER_AGENT} ^Lynx.*
RewriteRule ^/$ /homepage.min.html [L]
RewriteRule ^/$ /homepage.std.html [L]
Interprétation : si vous utilisez Netscape Navigator (qui s'identifie lui-même sous le nom 'Mozilla'), alors vous récupérerez la version "haute définition" de la homepage, avec les cadres, les images, etc. Si vous utilisez le navigateur Lynx (basé sur une approche Terminal), alors vous serez routé vers la Homepage "basse définition", qui est écrite sans images, sans tables, etc. Si vous utilisez n'importe quel autre navigateur, on vous routera sur une version "moyenne".
Directive : RewriteRule
RewriteRule motif substitutionDéfaut : Aucun
Contexte : configuration serveur, hôtes virtuels, répertoire, .htaccess
La directive RewriteRule est le véritable cheval de trait de la réécriture. Elle peut apparaître plus d'une fois. Chque directive définit alors une règle unique de réécriture. L'ordre dans lequel les définitions de ces règles est faite a une grande importance, car cet ordre conditionne celui dans lequel les règles sont appliquées à l'exécution.
Motif peut être une expression régulière (Système V8 pour Apache 1.1.x et POSIX pour Apache 1.2.x) qui sera appliquée sur l'URL courante. Ici, "courante" signifie la valeur de l'URL au moment ou la règle est appliquée. Celle-ci n'est pas nécéssairement l'URL initialement demandée, car plusieurs directives de réécriture auront pu altérer cette URL avant que celle-ci soit applicable.
Voici quelques notes au sujet de la syntaxe d'expressions régulières :
^ Recherche en début de ligne $ Recherche en fin de ligne . Un caractère quelque soit sa valeur [chars] Un caractère dans la liste [^chars] Un caractère autre que ceux de a liste ?< 0 ou 1 fois le caractère qui précède * 0 à N fois le caractère qui précède + 1 à N fois le caracère qui précède \char despécialise le métacaractère qui suit (ex. pour mentionner les caractères litéraux ".[]()" etc.) (string) sous-motif (le Nième sous-motif peut être réutilisé dans l'expression de substitution par la variable prédéfinie $N)
En plus des règles standard d'expressions régulières, l'opérateur de négation unaire ('!') peut être préfixé au motif. Ceci permet de demander la condition inverse (logiquement) pour dire par exemple : "si l'URL courante NE CORRESPOND PAS à ce motif". Ceci peut être utilisé lorsqu'il est plus facile d'exprimr les conditions inverses ou comme dernière règle par défaut.
Attention ! Lorsque vous utilisez l'opérateur ! pour inverser la signification du motif, vous ne pouvez pas définir de sous motif dans ce motif. C'est effectivement incohérent du fait que comme le motif n'est pas trouvé dans la chaîne analysée, les sous-motifs ne peuvent pas recevoir décemment de contenu. Donc, lorsque vous utilisez cet opérateur, vous ne pouvez utiliser les variables $N dans l'expression de substitution !
L'expression de Substitution d'une règle de réécriture est une chaîne qui définit par quoi est substituée (ou remplacée) l'URL qui correspond au motif. Beside plain text you can use
- Des rétro-références
$Nsur des sous-motifs de la condition de règle - Des rétro-références
%Nsur les sous-motifs de la RewriteCond précédente - Des variables "serveur" de la même façon que dans les expressions de condition (
%{VARNAME}) - Des appels à des fonctions de correspondance (
${nomTable:clef|défaut})
Les rétro-références $N (N=1..9) sont des "variables prédéfinies" qui permettent d'accéder au contenu du Nième sous-motif du motif trouvé. Les variables "serveur" sont les mêmes que celles utilisées dans les directives TestString ou RewriteCond. Les fonctions de correspondance sont déduites des directives RewriteMap et sont expliquées dans le paragraphe qui s'y rapporte. Ces trois types de variables sont interprétées dans l'ordre ci-dessous exposé.
Comme il y a déjà été fait allusion, toutes les règles de réécriture sont appliquées à la Substitution précédente (dans l'ordre où elles sont définies dans le fichier de configuration). L'URL est complètement remplacée par l'expression de substitution et le traitement de recomposition de l'URL finale continue tant qu'il reste encore des règles à appliquer (où alors explicitement lorsque le commutateur spécial L est marqué en fin de ligne - voir ci-dessous).
Il est défini une expression de substitution spéciale '-' qui signifie : PAS de substitution ! Bizarre, non ? Non, il est utile de disposer de règles de réécriture qui "déclenchent" sur une certaine URL tout en n'effectuant aucune modification, par exemple, en conjonction avec le commutateur C (chaînage) qui permet à plusieurs motifs succéssifs d'être testés sur la même URL avant que toute modification n'y soit portée.
Une dernière note : Vous pouvez même, par une expression de substitution, réécrire une URL contenant des paramètres de requête. Il suffit pour celà d'ajouter le célèbre point d'interrogation ('?') qui sépare habituellement la partie URI de la partie argument de requête lequel sera passé à la variable QUERY_STRING. Si vous voulez effacer une chaîne de requête déjà présente dans l'URL originale, terminez l'expression de substitution par un point d'interrogation seul.
Attention : Voici une fonctionnalité spéciale. Lorsque vous préfixez une expression de substitution par http://cetHôte[:cePort] alors le module mod_rewrite arrête automatiquement son traitement. Cette auto-réduction en cas d'URL redirigées implicitement en externe est une fonction utile et importante lorsque'elle vient en combinaison d'une fonction de correspondance qui génère la partie "hôte" de l'adresse. Voir le premier exemple dans la section d'exemples ci après pour comprendre pourquoi.
Souvenez-vous : Une redirection externe inconditionnelle vers votre propre serveur ne fonctionnera pas lorsque le préfixe http://cetHôte apparaît, à cause de ce principe. pour effectuer une telle auto-redirection, Vous devrez utiliser le commutateur R (voir ci-dessous).
Vous pouvez de plus ajouter certains commutateurs au champ substitution en ajoutant un troisième argument sous la forme :
[flags]à la directive RewriteRule. Flags est une liste de commutateurs ci-après définis séparés par des virgules :
- '
redirect|R[=code]' (force la redirection)
Prefixez substitution par une chaîne de typehttp://cetHôte[:cePort]/(qui fait de cette nouvelle URL une URI) pour forcer une redirection externe. Si aucun code n'est mentionné, un code de réponse HTTP 302 (MOVED TEMPORARILY) sera utilisé par défaut. Si vous souhaîtez renvoyer un autre code de réponse, dans les séries 300 ou 400, mentionnez ce code sous forme numérique ou utilisez l'une des constantes symboliques ci-après :temp(défaut),permanent,seeother. Utilisez cette fonction pour des règles qui auraient tendance à canoniser les URL et les renvoyer ainsi au client, ex. qui traduisent "/~" en "/u/" ou ajoutent systématiquement un slash à/u/user, etc.
Attention : Lorsque vous marquez ce commutateur, assurez-vous que l'expression de substitution est bien une URL valide ! Si ce n'est pas le cas, vous redirigez la requête vers un document qui n'existe pas ! Souvenez-vous aussi que l'action de ce commutateur ne fait que préfixer l'URL parhttp://cetHôte[:cePort]/, et c'est la procédé classique de réécriture qui fait le reste. Vous souhaiterez de plus arrêter, en général, le traitement de réécriture à ce moment et déclencher la redirection immédiatement. Vous devrez pour ce faire marquer en plus le commutateur 'L'. - '
forbidden|F' (force l'URL à apparaître comme interdite : forbidden)
Ceci force l'URL courante sur l'URL interdite, c'est à dire que le serveur enverra immédiatemment une réponse HTTP de code 403 (FORBIDDEN). Utilisez ce commutateur en conjonction avec des directives RewriteConds appropriées pour bloquer l'accès à certaines URL sous certaines conditions. - '
gone|G' (force l'URL à apparaître come une redirection définitive : gone)
Ceci force une réponse HTTP de code 410 (GONE). Utilisez ce commutateur pour marquer que les ressources demandées ont définitvement "déménagé". - '
proxy|P' (force la redirection sur proxy)
Ce commutateur force l'URL substituée être redirigée en interne au titre de requête proxy (et arrête de ce fait tout processus de réécriture) et passe immédiatement le résultat au module proxy. Vous devez vous assurer que l'expression de substitution est bien une URI valide (ex. typiquehttp://) qui peut être traitée par le module proxy d'Apache. Sinon, vous génèrerez une erreur dans le gestionnaire proxy. Utilisez ce commutateur pour obtenir une implémentation plus puissante de la directiveProxyPassdu modulemod_proxy, permettant d'intégrer des ressources distantes à l'espace du serveur local.
Attention : Il vous faut nécessairement mentionnerProxyRequests Ondansla configuration de votre serveur pour éviter que des requêtes proxy ne se terminent en un "core-dump" du kernel Apache. Si vous n'avez pas compilé le module proxy dans Apache, alors vous n'avez pas ce problème, car le modulemod_rewritevérifie auparavent la disponibilité du module proxy et ignore les redirections proxy si ce module se révèle indisponible. - '
last|L' (dernière règle : last rule)
Arrête le traitement de réécriture en ce point et n'applique plus aucune règle de réécriture postérieure. Ceci correspond à l'instruction Perllastou aubreakdu C dans une boucle. Utilisez ce commutateur pour éviter que l'URL réécrite par cette règle ne soit à son tour modifiée une nouvelle fois par d'autres règles pour lesquelles le motif pourrait correspondre. Par exemple, vouspouvez l'utiliser pour réécrire l'URL d'accès à root ('/') vers une URL opérationnelle, comme '/e/www/'. - '
next|N' (rebouclage : next round)
Re-exécute le traitement de réécriture (en recommençant par la première règle), mais à partir de l'URL obtenue par application de la règle courante (et non à partir de l'URL originale, d'où on ne sortirait pas). Ceci correspond à l'instruction Perlnextoucontinuedu langage C. Utilisez ce commutateur pour recommencer le traitement de réécriture, c'est-à-dire pour immédiatement reboucler au début de la boucle.
Faîtes très attention de ne pas créer de boucle infinie ! - '
chain|C' (chainage à la règle suivante)
Ce commutateur chaîne la règle courante à la règle suivante (laquelle peut à son tour être chaînée à la régle encore suivante etc.). Ceci à l'effet suivant : si une règle est "déclenchée", alors le traitement se continue comme d'habitude, c'est-à-dire que ce commutateur n'a pas d'effet particulier. Si la règle n'est pas activée, alors toutes les règles chaînées qui suivent sont ignorées. Par exemple, vous pourriez l'utiliser pour éliminer la partie ".www" dans une règle de contexte répertoire définie pour des cas de redirection externe (où la partie ".www" ne doit pas apparaître !). - '
type|T=type-mime' (force le type MIME)
Force le type MIME du fichier cible à la valeur spécifiée par mime-type. Par exemple, il peut permettre le simuler l'ancienne directiveScriptAliasdu modulemod_aliaspar laquelle on attribuerait à tous les fichiers d'un répertoire un type MIME "application/x-httpd-cgi", quelle que soit leur extension. - '
nosubreq|NS' (utilisé uniquement si la requête n'est pas une sous requête interne : no internal sub-request)
Ce commutateur force le moteur de réécriture à sauter la règle si la requête courante est une sous-requête interne. Un exemple d'utilisation de sous-requêtes intervient lorsque le modulemod_included'Apache essaie de rechercher des informations sur l'existence éventuelle de fichiers par défaut dans les répertoires (index.xxx). Lors de ces sous-requêtes, il n'est pas toujours utile, voir parfois même carrément néfaste d'appliquer une nouvelle fois tout l'ensemble de règles de réécriture. Vous utiliserez alors ce commutateur pour exclure ces règles pouvant conduire à une erreur de traitement.
Vous pouvez vous appuyer sur la règle suivante pour prendre votre décision : lorsque vous préfixez certaines URL vers des scripts CGI, pour les forcer à exécutées en tant que CGI, il y a de fortes chances que vous tombiez sur un os (ou même sur une défaillance générale) lors des sous-requêtes. Dans ce cas, utilisez ce commutateur. - '
qsappend|QSA' (Ajout de chaîne de requête : query string append)
Ce commutateur force l'ajout d'une chaîne argument de requête dans l'URL substituée à l'argument existant, au lieu de remplacer purement et simplement cet argument comme dans le cas normal. Vous utiliserez cecommutateur lorsque vouzs voudrez ajouter des paramètres à une requête argumentée par une opération de réécriture. -
'
passthrough|PT' (pass through)
Ce commutateur force le moteur de réécriture à renseigner le champuride la structure internerequest_recavec la valeur du champfilename. Ce commutateur est juste une "bidouille" pour permettre un post-traitement de la sortie de directivesRewriteRulepar des directivesAlias,ScriptAlias,Redirect, et autres translateurs URI-vers-fichier. Voici un exemple trivial pour en décrire la sémantique :
Si vous souhaitez translater/abcen/defvia le moteur de réécriture du modulemod_rewritepuis/defen/ghipar une directive demod_alias:RewriteRule ^/abc(.*) /def$1 [PT] Alias /def /ghi
Si vous omettez le commutateurPTalorsmod_rewritefera le travail attendu, c'est-à-dire transformerauri=/abc/...enfilename=/def/...comme n'importe quel translateur URI-vers-fichier conforme à l'API Apache l'aurait fait. Puismod_aliasintervient et essaie d'effectuer sa translation dans laquelle elle échouera, essayant de se baser sur l'URL originale et non l'URL modifiée par la précédente.Attention : Vous DEVEZ utiliser ce commutateur si vous souhaitez mélanger des directives de différents modules actionnant des translateurs URL-vers-fichier. L'exemple typique est cette utilisation demod_aliasetmod_rewrite.Pour les bidouilleurs d'Apache :
Si l'API actuelle d'Apache pouvait fournir une translation fichier-vers-fichier en plus de la translation URI-vers-fichier alors nous n'aurions pas besoin de ce commutateur ! Mais sans cette dérivation, ce commutateur est la seule solution. Le groupe Apache a discuté de ce problème et prévoit d'implémenter cette translation dans la future version 2.0 d'Apache. - '
skip|S=num' (sauter la prochaine(s) règle(s))
Ce commutateur force le moteur de réécriture à sauter les num règles suivantes lorsque la règle courante s'applique. Vous pouvez l'utiliser pour simuler des pseudo structures de contrôle de type SI-ALORS-SINON : La dernière règle de la section ALORS doit devenir une règle sautant N nouvelles règles (skip=N), ces N règles suivantes constituant ainsi la section SINON de la structure. (Ceci est différent du comportement du commutateur 'chain|C' !). - '
env|E=VAR:VAL' (définir unevariable d'environnement)
Force la définition d'une variable d'environnement VAR à la valeur VAL. VAL peut être exprimée par une expression contenant des rétroréférences$Net%Nqui seront substituées à l'initialisation de la variable. Vouspouvez utiliser ce commutateur plusieurs fois pour définir plusieurs variables en même temps. Ces variables pourront être par la suite réutilisées dans de nombreuses situations, dont les plus courantes sont à l'intérieur d'un traitement XSSI (via la commande<!--#echo var="VAR"-->) ou d'un CGI (ex.$ENV{'VAR'}). Vous pourrez aussi l'atteindre dans un motif deRewriteCondultérieur via l'écriture%{ENV:VAR}. Vous pouvez utilsier cette fonctionnalité lorsque vous souhaitez enlever des portions d'URLs, tout en mémorisant les morceaux enlevés.
Souvenez-vous : N'oubliez jamais que le motif est appliqué à l'URL entière lorsque les conditions sont écrites dans un contexte de configuration serveur. Par contre, dans un contexte de répertoire, le préfixe de chemin d'accès (le chemin partiel vers ce répertoire, qui devrait toujours être le même !) est d'abord retiré de l'URL avant que le motif ne soit appliqué, puis rajouté de nouveau tel que après la substitution. Ce comportement est fondamental dans de nombreuses programmation de réécriture, dans la mesure où, sans cette opération sur le chemin d'accès partiel, il vous faudrait un motif complet prenant en compte l'arborescence aïeule, ce qui n'est pas toujours possible.
Une exception à cela : lorsqu'une expression de substitution commence par "http://" alors le préfixe indiquant le chemin partiel au répertoire courant ne sera pas rajouté, et une redirection externe ou un transfert au proxy (si le commutateur P est marqué !) est opérée.
Attention ! Pour pouvoir exploiter le moteur de réécriture sur une base de configuration de contexte répertoire, vous devrez inscrire RewriteEngine On dans les fichiers de configuration .htaccess et avoir l'Option FollowSymLinks disponible. Si votre administrateur a désactivé la surcharge des options FollowSymLinks pour votre répertoire utilisateur, vous ne pourrez pas utiliser le moteur de réécriture. Cette restriction est nécessaire pour des raisons de sécurité.
Ci dessous sont données les diverses combinaisons de substitution et leur signification :
Dans une configuration de niveau "serveur" (httpd.conf)
pour une requête "GET /unChemin/uneInfo":
Règle Substitution résultante ---------------------------------------------- ---------------------------------- ^/unChemin(.*) autreChemin$1 non supporté, car non valide ! ^/unChemin(.*) autreChemin$1 [R] non supporté, car non valide ! ^/unChemin(.*) autreChemin$1 [P] non supporté, car non valide ! ---------------------------------------------- ---------------------------------- ^/unChemin(.*) /autreChemin$1 /autreChemin/uneInfo ^/unChemin(.*) /autreChemin$1 [R] http://cetHôte/autreChemin/uneInfo via une redirection externe ^/unChemin(.*) /autreChemin$1 [P] non supporté ! ---------------------------------------------- ---------------------------------- ^/unChemin(.*) http://cetHôte/autreChemin$1 /autreChemin/uneInfo ^/unChemin(.*) http://cetHôte/autreChemin$1 [R] http://cetHôte/autreChemin/uneInfo via une redirection externe ^/unChemin(.*) http://cetHôte/autreChemin$1 [P] non supporté ! ---------------------------------------------- ---------------------------------- ^/unChemin(.*) http://autreHôte/autreChemin$1 http://autreHôte/autreChemin/uneInfo via une redirection externe ^/unChemin(.*) http://autreHote/autreChemin$1 [R] http://autreHôte/autreChemin/uneInfo via une redirection externe (le flag [R] est redondant) ^/unChemin(.*) http://autreHôte/autreChemin$1 [P] http://autreHôte/autreChemin/uneInfo via proxy interne
Dans un fichier de configuration pour le répertoire /unChemin
(c-à-d. un fichier /.htaccess dans le répertoire /chemin/physique/vers/unChemin contenant une directive RewriteBase /unChemin)
pour une requête "GET /somepath/localpath/uneInfo" :
Règle Substitution résultante ------------------------------------------------- ---------------------------------- ^cheminLocal(.*) autreChemin$1 /unChemin/autreChemin/uneInfo ^cheminLocal(.*) autreChemin$1 [R] http://cetHôte/unChemin/autreChemin/uneInfo via une redirection externe ^cheminLocal(.*) autreChemin$1 [P] non supporté ! ------------------------------------------------- ---------------------------------- ^cheminLocal(.*) /autreChemin$1 /autreChemin/uneInfo ^cheminLocal(.*) /autreChemin$1 [R] http://cetHôte/autreChemin/uneInfo via une redirection externe ^cheminLocal(.*) /autreChemin$1 [P] non supporté ! ------------------------------------------------- ---------------------------------- ^cheminLocal(.*) http://cetHôte/autreChemin$1 /autreChemin/uneInfo ^cheminLocal(.*) http://cetHôte/autreChemin$1 [R] http://cetHôte/autreChemin/uneInfo via une redirection externe ^cheminLocal(.*) http://cetHôte/autreChemin$1 [P] not supporté ! ------------------------------------------------- ---------------------------------- ^cheminLocal(.*) http://autreHôte/autreChemin$1 http://autreHôte/autreChemin/uneInfo via une redirection externe ^cheminLocal(.*) http://autreHôte/autreChemin$1 [R] http://autreHôte/autreChemin/uneInfo via une redirection externe (le flag [R] est redondant) ^cheminLocal(.*) http://autreHôte/autreChemin$1 [P] http://autreHôte/autreChemin/uneInfo via proxy interne
Exemple :
Mettons que nous souhaitions réécrire des URL de la forme /Language/~Realname/.../File en /u/Username/.../File.Language
Nous déduirions la table de correspondance des règles ci-dessus et l'enregistrerions dans le fichier /nimportou/map.real-vers-hote. Il ne nous resterait plus qu'à écrire les lignes suivantes dans le fichier de configuration d'Apache :
RewriteLog /nimportou/reecriture.log
RewriteMap real-vers-user txt:/nimportou/map.real-vers-hote
RewriteRule ^/([^/]+)/~([^/]+)/(.*)$ /u/${real-vers-user:$2|nobody}/$3.$1
Fonctionnalités additionnelles
Variables d'Environnement
Ce module garde la trace de deux variables d'environnement CGI/SSI supplémentaires (non standard) nommées SCRIPT_URL et SCRIPT_URI . Elles contiennent l'adresse logique de la ressource courante "vue du navigateur", tandis que les variables CGI/SSI standard SCRIPT_NAME et SCRIPT_FILENAME contiennent l'adresse physique de la même ressource "vue du système".
Attention : Ces variables contiennent les URI/URL telles qu'elles sont inscrites dans la requête initiale, c'est-à-dire leur expression avant toute opération de réécriture. Ceci a une certazine importance car le procédé de réécriture est principalement utilisé pour transcrire ces adresses logiques en adresses physiques.
Exemple :
SCRIPT_NAME=/v/sw/free/lib/apache/global/u/rse/.www/index.html SCRIPT_FILENAME=/u/rse/.www/index.html SCRIPT_URL=/u/rse/ SCRIPT_URI=http://en2.en.sdm.de/u/rse/