<?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: 1932819:1934327 (outdated) -->
+<!-- English Revision: 1934327 -->
<!-- French translation : Lucien GENTIS -->
<!-- Reviewed by : Vincent Deffontaines -->
fournit des exemples pour chacun des différents types de
<directive module="mod_rewrite">RewriteMap</directive>.</p>
- <note type="warning">Notez que la plupart de ces exemples ne
- fonctionneront pas en l'état dans le contexte de votre configuration
- particulière ; vous devez donc vous attacher à les
- comprendre, plutôt que de simplement les insérer dans votre
- configuration par copier/coller.</note>
-
- </summary>
+ </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="remapping.html">Redirection et remise en correspondance</a></seealso>
+ <seealso><a href="flags.html">Drapeaux des règles de réécriture</a></seealso>
<seealso><a href="vhosts.html">Serveurs virtuels</a></seealso>
- <seealso><a href="proxy.html">Mise en cache</a></seealso>
- <seealso><a href="advanced.html">Techniques avancées</a></seealso>
+ <seealso><a href="htaccess.html">Réécritures par répertoire</a></seealso>
<seealso><a href="avoid.html">Quand ne pas utiliser mod_rewrite</a></seealso>
+ <seealso><a href="tech.html">Détails techniques</a></seealso>
<section id="introduction">
<title>Introduction</title>
module="mod_rewrite">RewriteRule</directive> :
</p>
- <p> <strong>Redirection d'un URI vers une version en minuscules
+ <p> <strong>Redirection d'un chemin d’URL vers une version en minuscules
d'elle-même</strong></p>
<highlight language="config">
directive <directive module="core">Mutex</directive>.</p>
<p>Voici un exemple simple qui remplace tous les tirets par des
- caractères de soulignement dans l'URI de la requête.</p>
+ caractères de soulignement dans le chemin d’URL de la requête.</p>
<p><strong>Configuration de la réécriture</strong></p>
<highlight language="config">
print(line.strip().replace('-', '_'), flush=True)
</highlight>
+ <p>Un exemple plus complet montre un motif typique pour qu’un programme de
+ correspondance prg: lise une ligne, recherche le résultat et l’affiche. La
+ sortie de diagnostic est écrite sur <code>STDERR</code> et termine sa course
+ dans le journal des erreurs de httpd.</p>
+
+ <p><strong>Configuration de la réécriture</strong></p>
+ <highlight language="config">
+RewriteMap vhost2docroot "prg:/www/bin/vhost_lookup.py"
+RewriteRule "^/(.*)$" "${vhost2docroot:%{HTTP_HOST}}/$1"
+ </highlight>
+
+ <p><strong>vhost_lookup.py</strong></p>
+ <highlight language="python">
+#!/usr/bin/env python3
+"""Associer un nom d’hôte au répertoire racine de ses documents."""
+import sys
+
+VHOSTS = {
+ "example.com": "/srv/www/example",
+ "blog.example.com": "/srv/www/blog",
+}
+
+for line in sys.stdin:
+ host = line.strip().lower()
+ docroot = VHOSTS.get(host)
+ if docroot:
+ print(docroot, flush=True)
+ else:
+ # "NULL" indique à mod_rewrite que la recherche a échoué
+ print("NULL", flush=True)
+ print(f"vhost_lookup: no match for {host!r}", file=sys.stderr)
+ </highlight>
+
<note><title>Mises en garde !</title>
<ul>
-<li>Votre programme doit être le plus
-simple possible. Si le programme se bloque, httpd va attendre
-indéfiniment une réponse de sa part, et par conséquent ne répondra plus
-aux requêtes.</li>
-<li>Assurez-vous de bien désactiver la mise en tampon dans votre
-programme. Dans l'exemple en Python ci-avant, cette opération s'effectue en
-passant <code>flush=True</code> à <code>print()</code>. Si les entrées/sorties sont mises en tampon, httpd va
-attendre une sortie, et va par conséquent se bloquer.</li>
+<li>Votre programme doit être le plus simple possible. Si le programme se
+bloque, httpd va attendre indéfiniment une réponse de sa part, et par conséquent
+ne répondra plus aux requêtes.</li>
+<li>Assurez-vous de bien désactiver la mise en tampon dans votre programme. Dans
+l'exemple en Python ci-avant, cette opération s'effectue en passant
+<code>flush=True</code> à <code>print()</code>. Si les entrées/sorties sont
+mises en tampon, httpd va attendre une sortie, et va par conséquent se bloquer.
+Il s’agit de la cause la plus courante pour laquelle le mappage prg: semble ne
+rien faire — le programme a la réponse mais httpd ne la verra jamais, car
+elle est prisonnière d’un tampon.</li>
<li>Rappelez-vous qu'il n'existe qu'une copie du programme lancé au
démarrage du serveur, et que toutes les requêtes vont devoir passer par
ce goulot d'étranglement. Ceci peut provoquer des ralentissements
règles imposées par votre base de données (comme la sensibilité à la casse).</p></note>
</section>
+
+ <section id="sharding">
+
+ <title>Distribution de la charge (sharding) basée sur l'URL entre plusieurs serveurs dorsaux</title>
+
+ <dl>
+ <dt>Description :</dt>
+
+ <dd>
+ <p>Le « sharding » est une technique courante de distribution de la charge
+ de travail ou de l’espace de stockage. Lorsqu’on utilise cette méthode, un
+ serveur frontal va utiliser l’URL pour distribuer les utilisateurs ou
+ objets à des serveurs dorsaux de manière cohérente.</p>
+ </dd>
+
+ <dt>Solution :</dt>
+
+ <dd>
+ <p>Un mappage entre les utilisateurs et les serveurs cible est entretenu
+ dans des fichiers de mappage. Ces derniers sont sous la forme :</p>
+
+<example>
+utilisateur1 serveur_physique_de_utilisateur1<br />
+utilisateur2 serveur_physique_de_utilisateur2<br />
+# ... et ainsi de suite
+</example>
+
+ <p>Nous inscrivons ceci dans un fichier
+ <code>mappage.utilisateur-vers-serveur</code>. Le but est d’associer</p>
+
+<example>
+/u/utilisateur1/chemin
+</example>
+
+ <p>à</p>
+
+<example>
+http://serveur_physique_de_utilisateur1/u/utilisateur/chemin
+</example>
+
+ <p>de sorte que tous les chemins d’URL n’ont pas besoin d’être valables
+ sur chaque serveur dorsal physique. Le jeu de règles suivant fait cela
+ pour nous avec l’aide des fichiers de mappage, en supposant que server0
+ est un serveur par défaut qui sera utilisé si un utilisateur n’a pas
+ d’entrée dans le mappage :</p>
+
+<highlight language="config">
+RewriteEngine on
+RewriteMap users-to-hosts "txt:/path/to/map.users-to-hosts"
+RewriteRule "^/u/([^/]+)/?(.*)" "http://${users-to-hosts:$1|server0}/u/$1/$2"
+</highlight>
+ </dd>
+
+ <dt>Discussion :</dt>
+
+ <dd>
+ <p>Pour distribuer les requêtes aux différents serveurs dorsaux,
+ <module>mod_proxy_balancer</module> constitue une approche plus robuste et
+ configurable, avec la prise en charge d’un bilan de santé, d’une
+ pondération des charges et de la persistance des sessions. L’approche
+ basée sur un mappage txt: présentée ici est plus simple mais ne prend pas
+ en charge ces fonctionnalités.</p>
+ </dd>
+ </dl>
+
+ <p>Voir la documentation de <directive
+ module="mod_rewrite">RewriteMap</directive> pour une description plus complète
+ de la syntaxe de cette directive.
+</p>
+
+ </section>
+
<section id="summary">
<title>Résumé</title>
<?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: 1934122:1935430 (outdated) -->
+<!-- English Revision: 1935430 -->
<!-- French translation : Lucien GENTIS -->
<!-- Reviewed by : Vincent Deffontaines -->
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 une nouvelle URL, soit vers un
+ <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é
- traduite en nom de fichier. Cela modifie ce à quoi correspond le motif et la
+ 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>
+ 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é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>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="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
+ 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ée au
+ <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
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>
+<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>