blob: 1f375561c91490952ef73afbeb1d9c53b0a07bbf [file]
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE manualpage SYSTEM "../style/manualpage.dtd">
<?xml-stylesheet type="text/xsl" href="../style/manual.fr.xsl"?>
<!-- English Revision: 1935430 -->
<!-- French translation : Lucien GENTIS -->
<!-- Reviewed by : Vincent Deffontaines -->
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manualpage metafile="tech.xml.meta">
<parentdocument href="./">Rewrite</parentdocument>
<title>Détails techniques sur le module Apache mod_rewrite</title>
<summary>
<p>Ce document passe en revue certains détails techniques à propos du
module <module>mod_rewrite</module> et de la mise en correspondance des URLs</p>
</summary>
<seealso><a href="../mod/mod_rewrite.html">Documentation du module mod_rewrite</a></seealso>
<seealso><a href="intro.html">Introduction à mod_rewrite</a></seealso>
<seealso><a href="remapping.html">Redirection et remise en
correspondance</a></seealso>
<seealso><a href="flags.html">Drapeaux de réécriture</a></seealso>
<seealso><a href="vhosts.html">Serveurs virtuels</a></seealso>
<seealso><a href="rewritemap.html">Utilisation de RewriteMap</a></seealso>
<seealso><a href="htaccess.html">Réécritures en fonction du répertoire</a></seealso>
<seealso><a href="avoid.html">Quand ne pas utiliser mod_rewrite</a></seealso>
<section id="InternalAPI"><title>Phases de l'API</title>
<p>Le traitement des requêtes par le serveur HTTP Apache se
déroule en plusieurs phases. Au cours de chaque phase, un ou
plusieurs modules peuvent être appelés pour traiter la partie
concernée du cycle de vie de la requête. Les différentes phases
peuvent consister en traduction d'URL en nom de fichier,
authentification, autorisation, gestion de contenu ou journalisation (la
liste n'est pas exhaustive).</p>
<p><module>mod_rewrite</module> agit dans deux de ces phases (ou accroches - hooks -
comme on les nomme souvent) pour la réécriture des URLs.</p>
<p>Tout d'abord, il utilise le hook traduction URL vers nom de
fichier qui intervient après la lecture de la requête HTTP, mais
avant le processus d'autorisation. Ensuite, il utilise le hook
Fixup, qui intervient après les phases d'autorisation, après la
lecture des fichiers de configuration de niveau répertoire (fichiers
<code>.htaccess</code>), mais avant l'appel du gestionnaire de
contenu.</p>
<p>Lorsqu'une requête arrive et une fois le serveur
correspondant ou le serveur virtuel déterminé, le moteur de
réécriture commence à traiter toute directive <module>mod_rewrite</module> apparaissant dans la
configuration de niveau serveur (autrement dit dans le
fichier de configuration principal du serveur et les sections
<directive module="core" type="section">Virtualhost</directive>).
Tout ce processus s'exécute au cours de la phase de traduction URL
vers nom de fichier.</p>
<p>Quelques étapes plus loin, une fois les répertoires de données
finaux trouvés, les directives de configuration de niveau répertoire
(fichiers <code>.htaccess</code> et sections <directive module="core"
type="section">Directory</directive>) sont appliquées. Ce processus
s'exécute au cours de la phase Fixup.</p>
<p>Dans tous ces cas, <module>mod_rewrite</module> réécrit le
<code>REQUEST_URI</code> soit vers un nouvel URL, soit vers un
nom de fichier.</p>
<p>Dans un <glossary ref="perdirectory">contexte de répertoire</glossary>,
les règles sont appliquées durant la phase "Fixup" après que l’URL a été
traduit en nom de fichier. Cela modifie ce à quoi correspond le motif et la
manière dont les substitutions sont gérées. Voir le document <a
href="htaccess.html#path-stripping">Réécritures en fonction du
répertoire</a> pour des détails pratiques à propos de la suppression du
chemin, de RewriteBase et de la manière d’éviter un bouclage.</p>
</section>
<section id="order"><title>Module Processing Order</title>
<p><module>mod_rewrite</module> et <module>mod_alias</module> agissent tous
les deux au cours de la phase de traduction de l’URL en nom de fichier, mais
<module>mod_rewrite</module> opère en premier, quel que soit l’ordre
d’apparition des directives dans le fichier de configuration. Ce
comportement est déterminé par la priorité des points d’accroche
qu’enregistre chaque module, pas par l’ordre du code source.</p>
<p>La conséquence pratique : lorsque des directives <directive
module="mod_rewrite">RewriteRule</directive> et <directive
module="mod_alias">Redirect</directive> (ou <directive
module="mod_alias">RedirectMatch</directive>) sont présentent simultanément
dans le même contexte de serveur virtuel ou global au serveur, les règles de
réécriture sont évaluées en premier. Si une règle <code>RewriteRule</code>
correspond et réécrit le chemin d’URL (ou renvoie une redirection),
<code>Redirect</code> ne verra jamais la requête.</p>
<p class="figure">
<img src="../images/rewrite_module_order.png"
alt="Comparaison côte-à-côte des ordres d’opération des modules : dans
un contexte global au serveur, mod_rewrite opère en premier lors de la
phase de traduction du chemin d’URL en nom de fichier, mod_alias
opèrant en second ; dans un contexte de répertoire, mod_alias opère en
premier lors de la phase de traduction du chemin d’URL en nom de
fichier, mod_rewrite opérant plus tard lors de la phase de
correction" /><br />
<dfn>Figure :</dfn> Inversion de l’ordre d’opération des modules entre les
contextes global au serveur et de répertoire
</p>
<highlight language="config">
# Dans cette configuration, le Redirect n’est jamais atteint pour /old,
# car la règle RewriteRule s’applique en premier — même si
# Redirect apparaît plus tôt dans le fichier.
Redirect "/old" "http://example.com/new"
RewriteRule "^/old" "/other" [L]
</highlight>
<note><title>Le contexte de répertoire inverse l’ordre</title>
<p>Dans un <glossary ref="perdirectory">contexte de répertoire</glossary>,
la situation est différente. Les directives de <module>mod_alias</module>
comme <code>Redirect</code> s’appliquent encore dans la phase de traduction
de l’URL en nom de fichier, mais les directives de
<module>mod_rewrite</module> s’appliquent plus tard, lors de la phase de
correction. Cela signifie que dans un contexte de répertoire,
<code>Redirect</code> est évaluée <em>avant</em> l’application des
règles <code>RewriteRule</code>.</p>
</note>
<p>Du fait de l’incohérence entre les contextes, mélanger des directives de
<module>mod_rewrite</module> et de <module>mod_alias</module> dans la même
portée est une source courante de confusion. Un conseil simple : choisissez
un module pour une tâche donnée. Si vous avez besoin de conditions de
réécritures ou de comparaison de motif, utilisez exclusivement
<code>RewriteRule</code>. Si une simple redirection de préfixe suffit,
utilisez la directive <code>Redirect</code> et n’ajoutez pas de règles de
réécritures qui pourraient interagir avec elle.</p>
</section>
<section id="encoding"><title>Encodage et décodage des URLs</title>
<p>Apache httpd supprime l’échappement des caractères encodés pour l’URL
dans le chemin d’URL de la requête avant que toute comparaison de motif de
directive <directive module="mod_rewrite">RewriteRule</directive> ne soit
effectuée. Une requête pour <code>/my%20page/cats%3Fdogs</code> est décodée
en <code>/my page/cats?dogs</code>, et c’est à cette chaîne décodée qu’est
comparé le motif de la directive <code>RewriteRule</code>.</p>
<p>Cela signifie que vous ne pouvez pas écrire un motif correspondant à la
forme littérale de l’URL encodé. Si vous devez distinguer
<code>/horses%2Fponies</code> de <code>/horses/ponies</code>, utilisez la
variable <code>%{THE_REQUEST}</code> dans une directive <directive
module="mod_rewrite">RewriteCond</directive> — cette variable conserve la
requête originelle telle qu’elle a été envoyée par le client, avant tout
décodage :</p>
<highlight language="config">
# Ne correspond qu’au caractère encodé littéral %2F,
# pas au séparateur de chemin réel
RewriteCond "%{THE_REQUEST}" "/horses%2F"
RewriteRule "^/horses/ponies$" "/special-handler" [L]
</highlight>
<p>Après la substitution, <module>mod_rewrite</module> réencode le chemin
d’URL résultant en sortie. Plusieurs drapeaux permettent de contrôler ce
comportement :</p>
<ul>
<li><a href="flags.html#flag_b">[B]</a> : rétablit l’échappement des
références arrières de façon que les caractères spéciaux capturés dans le
chemin d’URL décodé ne soient pas interprétés comme des délimiteurs dans
la substitution.</li>
<li><a href="flags.html#flag_bnp">[BNP]</a> : si [B] est actif, ce drapeau
encode les espaces en <code>%20</code> au lieu de <code>+</code> (convient
pour les éléments du chemin, pas pour la chaîne de paramètres).</li>
<li><a href="flags.html#flag_ne">[NE]</a> : ce drapeau supprime
l’échappement par défaut des caractères spéciaux dans le résultat de la
substitution, permettant la transmission sans modification des littéraux
<code>#</code>, <code>?</code> et d’autres caractères lors des
redirections externes.</li>
</ul>
<section id="allowencodedslashes">
<title>Directive AllowEncodedSlashes</title>
<p>Par défaut, httpd renvoie un code 404 pour tout URL contenant une barre
oblique encodée (<code>%2F</code>). La directive <directive
module="core">AllowEncodedSlashes</directive> permet de modifier ce
comportement :</p>
<ul>
<li><code>Off</code> (valeur par défaut) : rejette <code>%2F</code> avec
un code 404.</li>
<li><code>On</code> : autorise <code>%2F</code> et le décode en
<code>/</code> avant de le transmettre aux gestionnaires.</li>
<li><code>NoDecode</code> : autorise <code>%2F</code>, mais le conserve
sous sa forme encodée de façon que l’application dorsale le distingue d’un
séparateur de chemin réel.</li>
</ul>
<p>Lorsqu’on utilise le drapeau <a href="flags.html#flag_b">[B]</a> avec des
URLs qui peuvent contenir des barres obliques encodées, il est en général
nécessaire d’utiliser <code>AllowEncodedSlashes NoDecode</code> pour éviter
que httpd ne rejette le résultat réencodé.</p>
</section>
</section>
<section id="InternalRuleset"><title>Traitement du jeu de règles</title>
<p>Maintenant, quand <module>mod_rewrite</module> se lance dans ces deux
phases de l'API, il lit le jeu de règles configuré depuis la structure
contenant sa configuration (qui a été elle-même créée soit au démarrage
d'Apache httpd pour le contexte du serveur, soit lors du parcours des
répertoires par le noyau d'Apache httpd pour le contexte de répertoire).
Puis le moteur de réécriture est démarré avec le jeu de règles contenu
(une ou plusieurs règles associées à leurs conditions). En lui-même, le
mode opératoire du moteur de réécriture d'URLs est exactement le même dans
les deux contextes de configuration. Seul le traitement du résultat final
diffère.</p>
<p class="figure">
<img src="../images/mod_rewrite_fig1.png"
alt="Survol du processus de réécriture par requête lors des phases par
serveur et par répertoire" /><br />
<dfn>Figure 1 :</dfn>Le processus de réécriture par requête montrant les
deux phases du traitement des règles (par serveur et par répertoire)
</p>
<p>L'ordre dans lequel les règles sont définies est important car le
moteur de réécriture les traite selon une chronologie particulière (et pas
très évidente). Le principe est le suivant : le moteur de réécriture
traite les règles (les directives <directive
module="mod_rewrite">RewriteRule</directive>) les unes à la suite des
autres, et lorsqu'une règle s'applique, il parcourt les éventuelles
conditions (directives <code>RewriteCond</code>directives) associées.
Pour des raisons historiques, les conditions précèdent les règles, si bien
que le déroulement du contrôle est un peu compliqué. Voir la figure 2 pour
plus de détails.</p>
<p class="figure">
<img src="../images/rewrite_process_uri.png"
alt="Organigramme montrant le flux de contrôle par règle : pour chaque
règle, comparaison du motif avec l’URL, évaluation des conditions
RewriteCond, application de la substitution si les deux opérations
précédentes ont réussi, puis consultation des drapeaux pour déterminer
si l’on doit arrêter le traitement ou continuer avec la règle
suivante" /><br />
<dfn>Figure 2 :</dfn>Le flux de contrôle en parcourant le jeu de règles de
réécriture
</p>
<p>L'URL est tout d'abord comparé au
<em>Modèle</em> de chaque règle. Lorsqu'une règle ne s'applique
pas, <module>mod_rewrite</module> stoppe immédiatement le traitement de cette règle
et passe à la règle suivante. Si l'URL correspond au
<em>Modèle</em>, <module>mod_rewrite</module> recherche la présence de conditions
correspondantes (les directives Rewritecond apparaissant dans la
configuration juste
avant les règles de réécriture). S'il n'y en a pas, <module>mod_rewrite</module> remplace
l'URL par une chaîne élaborée à partir de la chaîne de
<em>Substitution</em>, puis passe à la règle suivante. Si des
conditions sont présentes, <module>mod_rewrite</module> lance un bouclage
secondaire afin de les traiter selon l'ordre dans lequel elles
sont définies. La logique de traitement des conditions est
différente : on ne compare pas l'URL à un modèle. Une chaîne de
test <em>TestString</em> est tout d'abord élaborée en développant
des variables, des références arrières, des recherches dans des
tables de correspondances, etc..., puis cette chaîne de test est
comparée au modèle de condition <em>CondPattern</em>. Si le modèle
ne correspond pas, les autres conditions du jeu ne sont pas
examinées et la règle correspondante ne s'applique pas. Si le
modèle correspond, la condition suivante est examinée et ainsi de
suite jusqu'à la dernière condition. Si toutes les conditions sont
satisfaites, le traitement de la règle en cours se poursuit avec
le remplacement de l'URL par la chaîne de <em>Substitution</em>.</p>
<p class="figure">
<img src="../images/mod_rewrite_fig2.png"
alt="Flux des références arrières entre les directives RewriteRule et
RewriteCond" /><br />
<dfn>Figure 3 :</dfn>Le flux des références arrières dans une règle
Tout d’abord, le motif de la règle RewriteRule est comparé ; ses captures
($1...$9) sont disponibles dans toutes les chaînes de test des conditions
RewriteCond. Les dernières captures du motif de la condition qui
correspondent (%1...%9) sont disponibles dans la substitution.
</p>
</section>
</manualpage>