1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE manualpage SYSTEM "../style/manualpage.dtd">
<?xml-stylesheet type="text/xsl" href="../style/manual.fr.xsl"?>
<!-- English Revision : 945974 -->
<!-- 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 mod_rewrite 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="access.html">Contrôle d'accès</a></seealso>
<seealso><a href="vhosts.html">Serveurs virtuels</a></seealso>
<seealso><a href="proxy.html">Mise en cache</a></seealso>
<seealso><a href="rewritemap.html">Utilisation de RewriteMap</a></seealso>
<seealso><a href="advanced.html">Techniques avancées et astuces</a></seealso>
<seealso><a href="avoid.html">Quand ne pas utiliser mod_rewrite</a></seealso>
<section id="Internal"><title>Fonctionnement interne</title>
<p>Le fonctionnement interne de ce module est très complexe, mais
il est nécessaire de l'expliquer, même à l'utilisateur "standard",
afin d'éviter les erreurs courantes et de pouvoir exploiter toutes
ses fonctionnalités.</p>
</section>
<section id="InternalAPI"><title>Phases de l'API</title>
<p>Il faut tout d'abord bien comprendre que le traitement d'une
requête HTTP par Apache s'effectue en plusieurs phases. L'API
d'Apache fournit un point d'accroche (hook) pour chacune de ces
phases. Mod_rewrite utilise deux de ces hooks : le hook de
conversion des URLs en noms de fichiers qui est utilisé quand la
requête HTTP a été lue mais avant le démarrage de tout processus
d'autorisation, et le hook "Fixup" qui est déclenché après les
phases d'autorisation et après la lecture des fichiers de
configuration niveau répertoire (<code>.htaccess</code>), mais
avant que le gestionnaire de contenu soit activé.</p>
<p>Donc, lorsqu'une requête arrive et quand Apache a déterminé le
serveur correspondant (ou le serveur virtuel), le moteur de
réécriture commence le traitement de toutes les directives de
mod_rewrite de la configuration du serveur principal dans la phase
de conversion URL vers nom de fichier. Une fois ces étapes
franchies, lorsque les repertoires de données finaux ont été
trouvés, les directives de configuration de mod_rewrite au niveau
répertoire sont éxécutées dans la phase Fixup. Dans les deux cas,
mod_rewrite réécrit les URLs soit en nouvelles URLs, soit en noms
de fichiers, bien que la distinction entre les deux ne soit pas
évidente. Cette utilisation de l'API n'était pas sensée s'opérer
de cette manière lorsque l'API fut conçue, mais depuis Apache 1.x,
c'est le seul mode opératoire possible pour mod_rewrite. Afin de
rendre les choses plus claires, souvenez-vous de ces deux points :</p>
<ol>
<li>Bien que mod_rewrite réécrive les URLs en URLs, les URLs en
noms de fichiers et même des noms de fichiers en d'autres noms
de fichiers, l'API ne propose actuellement qu'un hook URL vers
nom de fichier. Les deux hooks manquants seront ajoutés dans
Apache à partir de la version 2.0 afin de rendre le processus
plus clair. Mais ce point ne présente pas d'inconvénient pour
l'utilisateur, il s'agit simplement d'un fait que vous devez
garder à l'esprit : Apache en fait plus avec le hook URL vers
nom de fichier que l'API n'a la prétention d'en faire.</li>
<li>
Paradoxalement, mod_rewrite permet la manipulation d'URLs dans
un contexte de répertoire, <em>c'est à dire</em> dans les
fichiers <code>.htaccess</code>, bien que ces derniers
soient traités bien longtemps après que les URLs n'aient été
traduites en noms de fichiers. Les choses doivent se dérouler
ainsi car les fichiers <code>.htaccess</code> résident dans le
système de fichiers, et le traitement a déjà atteint
cette étape. Autrement dit, en accord avec les phases de
l'API, à ce point du traitement, il est trop tard pour
effectuer des manipulations d'URLs. Pour résoudre ce problème
d'antériorité, mod_rewrite utilise une astuce : pour effectuer
une manipulation URL/nom de fichier dans un contexte de
répertoire, mod_rewrite réécrit tout d'abord le nom de fichier
en son URL d'origine (ce qui est normalement impossible, mais
voir ci-dessous l'astuce utilisée par la directive
<code>RewriteBase</code> pour y parvenir), puis
initialise une nouvelle sous-requête interne avec la nouvelle
URL ; ce qui a pour effet de redémarrer le processus des
phases de l'API.
<p>Encore une fois, mod_rewrite fait tout ce qui est en son
pouvoir pour rendre la complexité de cette étape complètement
transparente à l'utilisateur, mais vous devez garder ceci à
l'esprit : alors que les manipulations d'URLs dans le contexte
du serveur sont vraiment rapides et efficaces, les réécritures
dans un contexte de répertoire sont lentes et inefficaces à
cause du problème d'antériorité précité. Cependant, c'est la
seule manière dont mod_rewrite peut proposer des manipulations
d'URLs (limitées à une branche du système de fichiers) à
l'utilisateur standard.</p>
</li>
</ol>
<p>Ne perdez pas de vue ces deux points!</p>
</section>
<section id="InternalRuleset"><title>Traitement du jeu de règles</title>
<p>Maintenant, quand mod_rewrite se lance dans ces deux phases de
l'API, il lit le jeu de règles configurées depuis la structure
contenant sa configuration (qui a été elle-même créée soit au
démarrage d'Apache pour le contexte du serveur, soit lors du
parcours des répertoires par le noyau d'Apache 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>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 1 pour plus de
détails.</p>
<p class="figure">
<img src="../images/rewrite_rule_flow.png"
alt="Flux des comparaisons des directives RewriteRule et RewriteCond" /><br />
<dfn>Figure 1:</dfn>Déroulement du contrôle à travers le jeu de
règles de réécriture
</p>
<p>Comme vous pouvez le voir, l'URL est tout d'abord comparée au
<em>Modèle</em> de chaque règle. Lorsqu'une règle ne s'applique
pas, mod_rewrite stoppe immédiatement le traitement de cette règle
et passe à la règle suivante. Si l'URL correspond au
<em>Modèle</em>, mod_rewrite recherche la présence de conditions
correspondantes. S'il n'y en a pas, mod_rewrite remplace
simplement 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, mod_rewrite 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>
</section>
</manualpage>
|