blob: 449d9ea5adfb4891abb8c6b6c4eebeb9d8b4d61f [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: 1936255:1939342 (outdated) -->
<!-- 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="flags.xml.meta">
<parentdocument href="./">Rewrite</parentdocument>
<title>Les drapeaux de réécriture</title>
<summary>
<p>Ce document décrit les drapeaux disponibles dans la directive
<directive module="mod_rewrite">RewriteRule</directive>, en fournissant
des explications détaillées et des exemples.</p>
</summary>
<seealso><a href="../mod/mod_rewrite.html">Documentation du module</a></seealso>
<seealso><a href="intro.html">Introduction à mod_rewrite</a></seealso>
<seealso><a href="remapping.html">Redirection and remise en
correspondance</a></seealso>
<seealso><a href="htaccess.html">Réécritures par répertoire</a></seealso>
<seealso><a href="vhosts.html">Serveurs virtuels</a></seealso>
<seealso><a href="rewritemap.html">Utilisation de RewriteMap</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>
<p>Le comportement d'une directive <directive
module="mod_rewrite">RewriteRule</directive> peut être modifié par un ou
plusieurs drapeaux. Les drapeaux sont situés en fin de règle, entourés
de crochets, et séparés le cas échéant par des virgules.</p>
<highlight language="config">RewriteRule pattern target [Flag1,Flag2,Flag3]</highlight>
<p>Chaque drapeau (à quelques exceptions près)
possède une forme courte, comme <code>CO</code>, ainsi qu'une forme longue,
comme <code>cookie</code>. Bien que
la forme courte soit la plus couramment utilisée, nous vous recommandons
de vous familiariser avec les drapeaux sous leur forme longue, afin de
bien mémoriser ce que chaque drapeau est supposé faire.
Certains drapeaux acceptent un ou plusieurs arguments. Les drapeaux ne
sont pas sensibles à la casse.</p>
<p>Les drapeaux qui modifient les métadonnées associées à la requête (T=, H=,
E=) n'ont aucun effet dans un <glossary ref="perdirectory">contexte de
répertoire</glossary> ou de fichier htaccess, lorsqu'une substitution (autre que
'-') est effectuée au cours de la même passe du processus de réécriture. </p>
<p>Chaque drapeau disponible est présenté ici, avec un exemple
d'utilisation.</p>
</section>
<section id="flag_quickref"><title>Référence rapide des drapeaux</title>
<p>Les drapeaux peuvent être combinés : <code>[R=301,L]</code>, <code>[P,QSA]</code>,
<code>[E=VAR:val,L]</code>. Cette table les groupe par fonction et les trie
selon la fréquence de leur utilisation.</p>
<table border="1" style="zebra">
<columnspec><column width=".12"/><column width=".22"/><column width=".38"/><column width=".28"/></columnspec>
<tr>
<th>Drapeau</th>
<th>Fonction</th>
<th>Effet</th>
<th>Combinaisons courantes</th>
</tr>
<tr><td colspan="4"><em><strong>Contrôle de flux</strong></em></td></tr>
<tr>
<td><a href="#flag_l">[L]</a></td>
<td>Dernière règle</td>
<td>Arrête le traitement des règles (pour cette passe)</td>
<td>[R=301,L] [F] [G]</td>
</tr>
<tr>
<td><a href="#flag_end">[END]</a></td>
<td>Arrêt complet</td>
<td>Arrête tout le processus de réécriture (pas de réentrance dans .htaccess)</td>
<td>[R=301,END]</td>
</tr>
<tr>
<td><a href="#flag_s">[S=N]</a></td>
<td>Saut</td>
<td>Sauter les N prochaines règles (logique if/else)</td>
<td></td>
</tr>
<tr>
<td><a href="#flag_n">[N]</a></td>
<td>Instance suivante de la boucle</td>
<td>Redémarrer le traitement du jeu de règles à partir de la première
(attention : risque de boucle infinie)</td>
<td></td>
</tr>
<tr>
<td><a href="#flag_c">[C]</a></td>
<td>Chaînage</td>
<td>Chaîner la règle actuelle à la prochaine ; si la règle actuelle échoue,
sauter les règles chaînées</td>
<td></td>
</tr>
<tr><td colspan="4"><em><strong>Redirection et mandatement</strong></em></td></tr>
<tr>
<td><a href="#flag_r">[R=code]</a></td>
<td>Redirection</td>
<td>Redirection externe (par défaut 302). Utilisez Redirect/RedirectMatch pour
les cas simple</td>
<td>[R=301,L] [R=302,L]</td>
</tr>
<tr>
<td><a href="#flag_p">[P]</a></td>
<td>Mandatement</td>
<td>Mandatement inverse vers une cible (nécessite <module>mod_proxy</module>)</td>
<td>[P,QSA]</td>
</tr>
<tr><td colspan="4"><em><strong>Contrôle d’accès</strong></em></td></tr>
<tr>
<td><a href="#flag_f">[F]</a></td>
<td>Interdiction</td>
<td>Renvoie 403 (implique [L])</td>
<td></td>
</tr>
<tr>
<td><a href="#flag_g">[G]</a></td>
<td>Parti</td>
<td>Renvoie 410 (implique [L])</td>
<td></td>
</tr>
<tr><td colspan="4"><em><strong>URL / chaîne de paramètres</strong></em></td></tr>
<tr>
<td><a href="#flag_qsa">[QSA]</a></td>
<td>Ajout de la chaîne de paramètres</td>
<td>Ajout de la chaîne de paramètres originelle à la substitution</td>
<td>[QSA,L] [P,QSA]</td>
</tr>
<tr>
<td><a href="#flag_qsd">[QSD]</a></td>
<td>Suppression de la chaîne de paramètres</td>
<td>Supprime entièrement la chaîne de paramètres</td>
<td>[R=301,QSD,L]</td>
</tr>
<tr>
<td><a href="#flag_b">[B]</a></td>
<td>Échappement des références arrières</td>
<td>Réencode les caractères spéciaux dans les références arrières</td>
<td>[B,PT]</td>
</tr>
<tr>
<td><a href="#flag_ne">[NE]</a></td>
<td>Pas d’échappement</td>
<td>Pas d’échappement des caractères spéciaux dans la sortie (pass #, ? through)</td>
<td>[R=301,NE,L]</td>
</tr>
<tr><td colspan="4"><em><strong>Metadonnées et gestionnaires</strong></em></td></tr>
<tr>
<td><a href="#flag_e">[E]</a></td>
<td>Définition d’une variable d’environnement</td>
<td>Définit une variable d’environnement</td>
<td>[E=VAR:val,L]</td>
</tr>
<tr>
<td><a href="#flag_t">[T]</a></td>
<td>Type MIME</td>
<td>Forçage du type de contenu</td>
<td></td>
</tr>
<tr>
<td><a href="#flag_h">[H]</a></td>
<td>Gestionnaire</td>
<td>Forçage d’un gestionnaire de contenu</td>
<td></td>
</tr>
<tr>
<td><a href="#flag_pt">[PT]</a></td>
<td>Transmission résultat</td>
<td>Transmission du résultat au gestionnaire suivant (requis pour Alias/ScriptAlias)</td>
<td>[PT,L]</td>
</tr>
<tr><td colspan="4"><em><strong>Cookie</strong></em></td></tr>
<tr>
<td><a href="#flag_co">[CO]</a></td>
<td>Définir un cookie</td>
<td>Définir un cookie HTTP pour la réponse</td>
<td>[CO=name:val:.domain,R=302,L]</td>
</tr>
</table>
</section>
<section id="flag_b"><title>B (échappement dans les références arrières)</title>
<p>Avec le drapeau [B], la directive <directive
module="mod_rewrite">RewriteRule</directive> échappe les caractères
non-alphanumériques avant d'appliquer la transformation.</p>
<p><module>mod_rewrite</module> doit supprimer les séquences d'échappement
des URLs avant leur
mise en correspondance avec le système de fichiers ; les séquences
d'échappement sont donc supprimées des références arrières au moment où
ces dernières sont appliquées. Avec le drapeau B, les caractères
non-alphanumériques des références arrières seront échappés. Considérons
par exemple cette règle :</p>
<p>Pour un échappement similaire des variables du serveur, voir la <a
href="#mapfunc">fonction de mappage</a> "escape".
</p>
<highlight language="config">
RewriteRule "^search/(.*)$" "/search.php?term=$1"
</highlight>
<p>Soit le terme de recherche 'x &amp; y/z' ; un navigateur va le coder
en 'x%20%26%20y%2Fz', transformant la requête en
'search/x%20%26%20y%2Fz'. Sans le drapeau B, cette règle de réécriture
va réécrire la requête en 'search.php?term=x &amp; y/z', ce qui ne
correspond pas à une URL valide et cette dernière sera encodée en
<code>search.php?term=x%20&amp;y%2Fz=</code>, ce qui ne correspond pas à
ce que l'on souhaitait.</p>
<p>Avec le drapeau B, les paramètres sont réencodés avant d'être passés
à l'URL résultante, ce qui fournit une réécriture correcte en
<code>/search.php?term=x%20%26%20y%2Fz</code>.</p>
<highlight language="config">
RewriteRule "^search/(.*)$" "/search.php?term=$1" [B,PT]
</highlight>
<p>Notez que vous devrez peut-être aussi définir la
directive <directive module="core">AllowEncodedSlashes</directive>
à <code>On</code> pour
que cet exemple particulier fonctionne, car httpd ne permet pas les
slashes encodés dans les URLs, et renvoie une erreur 404 s'il en
rencontre un.</p>
<p>Ce processus d'échappement est en particulier nécessaire dans le
contexte d'un mandataire, où l'accès au serveur d'arrière-plan échouera
si on présente à ce dernier une URL non échappée.</p>
<p>Une alternative à ce drapeau consiste à utiliser une directive
<directive module="mod_rewrite">RewriteCond</directive> pour capturer
%{THE_REQUEST}, les chaînes capturées se présentant
alors sous la forme codée.</p>
<p>A partir
de la version 2.4.26, vous pouvez limiter l'échappement dans les
références arrières à une liste de caractères que vous pouvez spécifiez comme
dans cet exemple : <code>[B=#?;]</code>. Notez que l'espace peut faire
partie de la liste des caractères à échapper, mais que vous devez mettre entre
guillemets le troisième argument de la directive <directive
module="mod_rewrite">RewriteRule</directive> et que l'espace ne doit pas
être le dernier caractère de cette liste.
</p>
<highlight language="config">
# Échappement des espaces et des points d'interrogation. Les guillemets autour
# du dernier argument sont obligatoires lorsque l'espace est inclus.
RewriteRule "^search/(.*)$" "/search.php?term=$1" "[B= ?]"
</highlight>
<p>Pour définir la liste des caractères à échapper de cette manière, voir <a
href="#flag_bne">#flag_bne</a> et <a href="#flag_bctls">#flag_bctls</a></p>
<p>Voir <a href="tech.html#encoding">Encodage et décodage des URLs</a> pour une
explication détaillée de la manière dont httpd décode les URIs avant la mise en
correspondance des motifs.</p>
</section>
<section id="flag_bnp"><title>BNP|backrefnoplus (ne pas échapper
l'espace en +)</title>
<p>Si le drapeau [BNP] est spécifié, la directive <directive
module="mod_rewrite">RewriteRule</directive> échappera le caractère
espace en %20 au lieu de '+' dans les références arrières. Ceci s'avère
utile lorsque la référence arrière est utilisée dans la partie chemin,
et non dans les paramètres de la requête.</p>
<highlight language="config">
# Échappe le caractère espace en %20 dans le chemin au lieu de + comme dans la
# soumission de formulaire à l'aide de la chaîne de paramètres
RewriteRule "^search/(.*)$" "/search.php/$1" "[B,BNP]"
</highlight>
<p>Ce drapeau est disponible à partir de la version 2.4.26 du serveur HTTP
Apache.</p>
<p>Voir <a href="tech.html#encoding">Encodage et décodage des URLs</a> pour
découvrir la manière dont l’encodage est géré dans le tube (pipeline) de
réécriture.</p>
</section>
<section id="flag_bctls"><title>BCTLS</title>
<p>Le drapeau [BCTLS] est similaire à [B], à la différence que seuls les espaces
et les caractères de contrôle sont échappés. Il s'agit du même jeu de caractères
rejetés lorsqu'ils sont copiés dans la chaîne de paramètres non codée.
</p>
<highlight language="config">
# Échappe les espaces et les caractères de contrôle
RewriteRule "^search/(.*)$" "/search.php/$1" "[BCTLS]"
</highlight>
<p>Ce drapeau est disponible à partir de la version 2.4.57 du serveur HTTP
Apache.</p>
</section>
<section id="flag_bne"><title>BNE</title>
<p>Les caractères listés dans [BNE=...] sont exclus des listes de caractères
correspondant aux drapeaux [B] ou [BCTLS]. Ils ne seront donc pas échappés.
</p>
<highlight language="config">
# Échappe les caractères par défaut, sauf /
RewriteRule "^search/(.*)$" "/search.php?term=$1" "[B,BNE=/]"
</highlight>
<p>Ce drapeau est disponible à partir de la version 2.4.57 du serveur HTTP
Apache.</p>
</section>
<section id="flag_c"><title>C|chain</title>
<p>Le drapeau [C] ou [chain] indique que la règle <directive
module="mod_rewrite">RewriteRule</directive> est chaînée avec la
suivante. Autrement dit, si la règle s'applique, elle est traitée
normalement et passe le contrôle à la règle suivante. Par contre, si
elle ne s'applique pas, la règle suivante, ainsi que toutes les règles
chaînées qui suivent, seront sautées.</p>
<highlight language="config">
# Réécrire les URLs des anciens produits vers la nouvelle application du
# catalogue, et ajouter un paramètre de traçage — mais seulement pour ceux qui
# sont réécrits.
RewriteRule "^/products/([0-9]+)$" "/catalog/item/$1" [C]
RewriteRule "^/catalog/(.*)$" "/catalog/$1?via=legacy" [QSA]
</highlight>
<p>Sans le drapeau [C], la seconde règle s’appliquerait aux requêtes qui
arrivent directement à <code>/catalog/</code>. Le chaînage des deux règles
permet de s’assurer que la seconde règle ne s’appliquera que si la première
s’applique.</p>
</section>
<section id="flag_co"><title>CO|cookie</title>
<p>Le drapeau [CO], ou [cookie], vous permet de définir un cookie
lorsqu'une règle <directive module="mod_rewrite">RewriteRule</directive>
s'applique. Il possède trois arguments obligatoires et
cinq arguments optionnels.</p>
<p>La syntaxe complète de ce drapeau, avec tous ses attributs, est la
suivante :</p>
<example>
[CO=NAME:VALUE:DOMAIN:lifetime:path:secure:httponly:samesite]
</example>
<p>Si un caractère littéral ':' doit être insérer dans un des champs du
cookie, une autre syntaxe est disponible. Pour utiliser cette syntaxe
alternative, le contenu du champ "Name" doit être précédé du caractère
';', et les sépateurs de champs deviendront des ';'.</p>
<example>
[CO=;NAME;VALUE:MOREVALUE;DOMAIN;lifetime;path;secure;httponly;samesite]
</example>
<p>Vous devez déclarer un nom, une valeur et un domaine pour que
le cookie puisse être défini.</p>
<dl>
<dt>Domain</dt>
<dd>Le domaine pour lequel vous souhaitez que le cookie soit valide. Ce
peut être un nom de serveur, comme <code>www.example.com</code>, ou un
domaine, comme <code>.example.com</code>. Il doit comporter au moins
deux parties séparées par un point. C'est à dire que vous ne pouvez pas
utiliser les valeurs <code>.com</code> ou <code>.net</code>. En effet,
ce style de cookie est interdit par le modèle de sécurité des cookies.</dd>
</dl>
<p>Vous pouvez aussi définir les valeurs suivantes :</p>
<dl>
<dt>Lifetime</dt>
<dd>La durée de vie du cookie, en minutes.</dd>
<dd>Une valeur de 0 indique une durée de vie correspondant à lasession
courante du navigateur. Il s'agit de la valeur par défaut.</dd>
<dd>Une valeur négative indique que la définition du cookie doit être annulée
dans le navigateur.</dd>
<dt>Path</dt>
<dd>Le chemin, sur le site web concerné, pour lequel le cookie est
valide, du style <code>/clients/</code> or
<code>/fichiers/telechargement/</code>.</dd>
<dd>La valeur par défaut est <code>/</code> - c'est à dire l'ensemble du
site web.</dd>
<dt>Secure</dt>
<dd>Si cet argument a pour valeur <code>secure</code>,
<code>true</code>, ou <code>1</code>, le cookie ne pourra être transmis
que dans le cadre d'une connexion sécurisée (https).</dd>
<dt>httponly</dt>
<dd>Si cet argument a pour valeur <code>HttpOnly</code>,
<code>true</code>, ou <code>1</code>, le cookie aura son drapeau
<code>HttpOnly</code> activé, ce qui signifie qu'il sera inaccessible au
code JavaScript pour les navigateurs qui supportent cette
fonctionnalité.</dd>
<dt>samesite</dt>
<dd>S'il est différent de <code>false</code> ou <code>0</code>, l'attribut
<code>SameSite</code> est défini à la valeur spécifiée. Les valeurs typiques
sont <code>None</code>, <code>Lax</code> et <code>Strict</code>. Disponible à
partir de la version 2.5.1 du serveur HTTP Apache.</dd>
</dl>
<p>Voici un exemple :</p>
<highlight language="config">
RewriteEngine On
RewriteRule "^/index\.html" "-" [CO=frontdoor:yes:.example.org:1440:/]
</highlight>
<p>Dans l'exemple ci-dessus, la règle ne réécrit
pas la requête. La cible de réécriture "-"
indique à <module>mod_rewrite</module> de transmettre la requête sans
modification. Par contre, il
définit un cookie nommé 'frontdoor' avec une valeur 'yes'. Le cookie est
valide pour tout hôte situé dans le domaine <code>.example.org</code>. Sa
durée de vie est limitée à 1440 minutes (24 heures), et il sera renvoyé
pour tous les URIs.</p>
</section>
<section id="flag_dpi"><title>DPI|discardpath</title>
<p>Avec le drapeau DPI, la partie <glossary ref="pathinfo">PATH_INFO</glossary>
qui a été ajoutée au <glossary ref="urlpath">chemin d’URL</glossary> réécrit est
supprimée.</p>
<p>Dans un <glossary ref="perdirectory">contexte de répertoire</glossary>, le
<glossary ref="urlpath">chemin d’URL</glossary> que compare chaque
<directive>RewriteRule</directive> est la concaténation des valeurs courantes du
chemin d’URL et de PATH_INFO.</p>
<p>Le chemin d’URL actuel peut être le chemin initial tel qu'il a été fourni par le
client, le résultat d'une passe précédente du processus de réécriture,
ou le résultat de la règle précédente de la passe actuelle du processus de
réécriture.</p>
<p>Par contre, la partie PATH_INFO ajoutée au chemin d’URL avant chaque règle ne
reflète que la valeur de PATH_INFO avant la passe actuelle du processus
de réécriture. En conséquence, si de larges portions du chemin d’URL
correspondent et sont copiées dans une substitution via plusieurs directives
<directive>RewriteRule</directive>, sans prendre en compte
quelles parties du chemin d’URL provenaient du PATH_INFO actuel, le chemin d’URL final
pourra se voir ajouter plusieurs copies de PATH_INFO.</p>
<p>Utilisez ce drapeau pour toute substitution où la présence du PATH_INFO qui
résultait de la mise en correspondance précédente de cette requête avec
le système de fichier n'est pas nécessaire. Avec ce drapeau, le
PATH_INFO établi avant que cette passe du processus de réécriture ne
débute est oublié. PATH_INFO ne sera pas recalculé tant que la passe
courante du processus de réécriture ne sera pas achevée. Les règles
suivantes de cette passe ne verront que le résultat direct des
substitutions, sans aucun PATH_INFO ajouté.</p>
<highlight language="config">
# Requête : /app/script.php/extra/path (PATH_INFO contient /extra/path)
# Sans le drapeau DPI, la substitution serait "script.php/extra/path" et
# pourrait par accident copier PATH_INFO dans le résultat.
RewriteRule "^script\.php(.*)$" "/new-app/handler$1" [DPI]
</highlight>
<p>Le drapeau DPI supprime <code>/extra/path</code>, de sorte que seul le
résultat de la substitution est transmis aux règles suivantes ou à la requête
finale.</p>
</section>
<section id="flag_e"><title>E|env</title>
<p>Avec le drapeau [E], ou [env], vous pouvez définir la valeur d'une
variable d'environnement. Notez que certaines variables d'environnement
peuvent être définies après le traitement de la règle, annulant par
la-même ce que vous avez défini. Voir le <a href="../env.html">document
sur les variables d'environnement</a> pour plus de détails sur le
fonctionnement des variables d'environnement.</p>
<p>La syntaxe complète pour ce drapeau est :</p>
<highlight language="config">
[E=!VAR]
</highlight>
<p><code>VAL</code> peut comporter des références arrières
(<code>$N</code> ou <code>%N</code>) qui seront développées.</p>
<p>En utilisant la version courte</p>
<example>
[E=VAR]
</example>
<p>vous pouvez définir la variable d'environnement nommée
<code>VAR</code> avec une valeur vide.</p>
<p>La forme</p>
<example>
[E=!VAR]
</example>
<p>permet d'annuler la définition de la variable <code>VAR</code>.</p>
<p>Les variables d'environnement s'emploient dans différents contextes,
comme les programmes CGI, d'autres directives RewriteRule, ou des
directives CustomLog.</p>
<p>L'exemple suivant définit une variable d'environnement nommée 'image'
avec une valeur de '1' si le chemin d’URL de la requête correspond à un fichier
image. Cette variable d'environnement est ensuite utilisée pour exclure
une telle requête du journal des accès.</p>
<highlight language="config">
RewriteRule "\.(png|gif|jpg)" "-" [E=image:1]<br />
CustomLog "logs/access_log" combined env=!image
</highlight>
<p>Notez que le même effet peut être obtenu à l'aide de la directive
<directive module="mod_setenvif">SetEnvIf</directive>. Cette technique
est présentée à titre d'exemple et non de recommandation.</p>
<p><strong>Définir des variables d’environnement pour tracer les réécritures</strong></p>
<p>Parfois, nous souhaitons être au courant de l’état de la situation lorsque
nous effectuons une réécriture. Par exemple, vous voudriez prendre note
que vous avez effectué cette réécriture, de sorte que vous pourriez
ultérieurement voir si une requête est arrivée par l’intermédaire de cette
réécriture. Une solution pour y parvenir est la définition d’une variable
d’environnement.</p>
<highlight language="config">
RewriteEngine on
RewriteRule "^/horse/(.*)" "/pony/$1" [E=<strong>rewritten:1</strong>]
</highlight>
<p>Dans la suite de votre jeu de règles, vous pouvez consulter cette variable
d’environnement en utilisant une RewriteCond :</p>
<highlight language="config">
RewriteCond "%{ENV:rewritten}" =1
</highlight>
<p>Notez que les variables d’environnements ne survivent pas à une redirection
externe. Vous devez alors utiliser le drapeau [CO] pour définir un cookie.</p>
<note><title>Préfixe REDIRECT_ après une redirection interne</title>
<p>Dans un <glossary ref="perdirectory">contexte de répertoire</glossary>,
une substitution réussie déclenche une redirection interne. Lorsque cela se
produit, toutes les variables d’environnement définies au cours de la passe
précédente — y compris celles créées avec <code>[E=VAR:VAL]</code> — sont
renommées par l’ajout du préfixe <code>REDIRECT_</code>. Une variable que
vous avez nommée <code>rewritten</code> devient ainsi
<code>REDIRECT_rewritten</code> dans la requête redirigée.</p>
<p>Pour tester la variable renommée, référencez-la avec le préfixe :</p>
</note>
<highlight language="config">
RewriteRule "^/horses/(.*)" "/ponies/$1" [E=rewritten:1]
# À la passe suivante, la variable a été renommée :
RewriteCond "%{ENV:REDIRECT_rewritten}" =1
RewriteRule "^/ponies/(.*)" "-" [E=seen_redirect:1,L]
</highlight>
<p>Si la requête est redirigée plusieurs fois, le préfixe est empilé :
<code>REDIRECT_REDIRECT_rewritten</code>, et ainsi de suite. Voir <a
href="../env.html#redirect-vars">Variables REDIRECT_</a> pour la description
complète de ce mécanisme.</p>
</section>
<section id="flag_end"><title>END</title>
<p>L'utilisation du drapeau [END] permet non seulement de terminer le
processus de réécriture en cours (comme [L]), mais aussi d'empêcher tout
processus de réécriture ultérieur dans un <glossary ref="perdirectory">contexte
de répertoire</glossary>, ce qui en fait le drapeau préféré pour la plupart des
règles de niveau répertoire.</p>
<p>Dans un contexte de serveur virtuel ou global, [END] et [L] se comportent de
manière identique. La différence entre les deux se situe dans un contexte de
répertoire où [L] interrompt la passe actuelle, mais où le jeu de règles est à
nouveau appliqué à l’URL réécrit. Cela peut provoquer des boucles infinies.
[END] empêche tout processus de réécriture ultérieur en interrompant le cycle.</p>
<highlight language="config">
# Dans .htaccess : routage de toutes les requêtes vers un contrôleur frontal
# ici, [L] proquerait une boucle infine, pas [END]
RewriteCond "%{REQUEST_FILENAME}" !-f
RewriteCond "%{REQUEST_FILENAME}" !-d
RewriteRule "^(.*)$" "/index.php" [END]
</highlight>
<p>Ceci ne s'applique pas aux nouvelles requêtes résultant d'une
redirection externe.</p>
<p>Voir la discussion <a href="htaccess.html#loops">Réécritures dans un contexte
de répertoire</a> pour une explication détaillée de la raison pour laquelle [L]
se comporte différemment dans un contexte de répertoire, et des cas où [END]
constitue le bon choix.</p>
</section>
<section id="flag_f"><title>F|forbidden</title>
<p>L'utilisation du drapeau [F] permet de faire envoyer par le serveur au
client un code de statut "403 Forbidden". Le même effet peut être obtenu à
l'aide de la directive <directive module="mod_access_compat">Deny</directive>,
mais ce drapeau offre plus de souplesse dans l'attribution d'un statut
Forbidden.</p>
<p>La règle suivante va interdire la téléchargement de fichiers
<code>.exe</code> depuis votre serveur.</p>
<highlight language="config">RewriteRule "\.exe" "-" [F]</highlight>
<p>Cet exemple utilise la syntaxe "-" pour la cible de réécriture, ce qui
signifie que le chemin d’URL de la requête n'est pas modifié. Il n'y a aucune
raison de réécrire un chemin d’URL, si vous avez l'intention d'interdire la
requête.</p>
<p>Lorsqu'on utilise [F], [L] est implicite - c'est à dire que la
réponse est renvoyée immédiatement, et aucune autre règle n'est évaluée.</p>
</section>
<section id="flag_g"><title>G|gone</title>
<p>Le drapeau [G] permet de faire envoyer par le serveur un code de statut
"410 Gone" avec la réponse. Ce code indique qu'une ressource qui était
disponible auparavant ne l'est plus actuellement.</p>
<p>Comme dans le cas du drapeau [F], on utilise en général la syntaxe
"-" pour la cible de réécriture lorsqu'on utilise le drapeau [G] :</p>
<highlight language="config">RewriteRule "oldproduct" "-" [G,NC]</highlight>
<p>Lorsqu'on utilise [G], [L] est implicite - c'est à dire que la
réponse est renvoyée immédiatement, et aucune autre règle n'est évaluée.</p>
</section>
<section id="flag_h"><title>H|handler</title>
<p>Force le traitement de la requête résultante par le gestionnaire
spécifié. Par exemple, on peut utiliser ce drapeau pour forcer
l'interprétation de tous les fichiers sans extension par le gestionnaire
php :</p>
<highlight language="config">RewriteRule "!\." "-" [H=application/x-httpd-php]</highlight>
<p>
L'expression rationnelle ci-dessus - <code>!\.</code> - correspond à
toute requête qui ne contient pas le caractère <code>.</code>.
</p>
<p>On peut aussi utiliser ce drapeau pour forcer l'utilisation d'un
certain gestionnaire en fonction de certaines conditions. Par exemple,
l'extrait suivant utilisé dans un contexte de niveau serveur permet de
faire en sorte que les fichiers <code>.php</code> soient
<em>affichés</em> par <code>mod_php</code> dans le cas où ils font
l'objet d'une requête avec l'extension <code>.phps</code> :</p>
<highlight language="config">
RewriteRule "^(/source/.+\.php)s$" "$1" [H=application/x-httpd-php-source]
</highlight>
<p>L'expression rationnelle ci-dessus -
<code>^(/source/.+\.php)s$</code> - va correspondre à toute requête qui
débutera par <code>/source/</code>, continuera par 1 ou n caractères
puis par <code>.phps</code>. La référence arrière $1 fait référence à la
correspondance capturée entre parenthèses de l'expression
rationnelle.</p>
</section>
<section id="flag_l"><title>L|last</title>
<p>Lorsque le drapeau [L] est présent, <module>mod_rewrite</module>
arrête le traitement du jeu de règles. Cela signifie dans la plupart des
situations que si la règle s'applique, aucune autre règle ne sera
traitée. Ce drapeau correspond à la commande Perl <code>last</code>, ou
à la commande <code>break</code> en C. Utilisez ce drapeau pour indiquer
que la règle courante doit être appliquée immédiatement, sans tenir
compte des règles ultérieures.</p>
<p>Dans un <glossary ref="perdirectory">contexte de répertoire</glossary>, [L]
arrête la passe actuelle du jeu de règles, mais la requête réécrite peut être
traitée à nouveau depuis le début du jeu de règles — ce qui peut provoquer des
boucles infinies. Pour éviter ce problème, utilisez le drapeau <a
href="#flag_end">[END]</a>, ou consultez le document <a
href="htaccess.html#loops">Réécritures au niveau répertoire</a> pour une
description détaillée du problème et des solutions alternatives.</p>
<p>Dans l'exemple donné ici, toute requête est réécrite en
<code>index.php</code>, la requête originale étant ajoutée comme chaîne
de requête en argument à <code>index.php</code> ; cependant, la
directive <directive
module="mod_rewrite">RewriteCond</directive> permet de s'assurer que si
la requête concerne déjà <code>index.php</code>, la directive <directive
module="mod_rewrite">RewriteRule</directive> sera sautée.</p>
<highlight language="config">
RewriteBase "/"
RewriteCond "%{REQUEST_URI}" !=/index.php
RewriteRule "^(.*)" "/index.php?req=$1" [L,PT]
</highlight>
</section>
<section id="flag_n"><title>N|next</title>
<p>Le drapeau [N] provoque un redémarrage du traitement des règles
depuis le début, en utilisant le résultat du jeu de règles, sous
réserve qu'il existe un point de démarrage ; à utiliser avec précautions
car il peut provoquer un bouclage infini.
</p>
<p>
Le drapeau [Next] peut servir, par exemple,
à remplacer de manière répétitive
une chaîne de caractère ou une lettre dans une requête. Dans l'exemple
suivant, chaque occurence de A sera remplacée par B dans la requête, et
ceci jusqu'il n'y ait plus de A à remplacer.
</p>
<highlight language="config">RewriteRule "(.*)A(.*)" "$1B$2" [N]</highlight>
<p>Vous pouvez vous représenter ce traitement comme une boucle
<code>while</code> : tant que le modèle de la règle correspond (c'est à
dire, tant que le chemin d’URL contient un <code>A</code>),
effectuer la substitution (c'est à dire, remplacer le <code>A</code> par
un <code>B</code>).</p>
<p>A partir de la version 2.5.0, ce module renvoie une erreur après
10000 itérations afin d'éviter les boucles infinies. Ce nombre maximum
d'itération peut être modifié via le drapeau N.</p>
<highlight language="config">
# On veut remplacer 1 caractère à chaque itération de la boucle
RewriteRule "(.+)[&gt;&lt;;]$" "$1" [N=32000]
# ... ou s'arrêter après 10 itérations
RewriteRule "(.+)[&gt;&lt;;]$" "$1" [N=10]
</highlight>
</section>
<section id="flag_nc"><title>NC|nocase</title>
<p>Avec le drapeau [NC], le modèle de la règle <directive
module="mod_rewrite">RewriteRule</directive> est comparé à la requête de
manière insensible à la casse. C'est à dire que cette comparaison
s'effectue sans tenir compte des majuscules/minuscules dans le chemin URL
comparé.</p>
<p>Dans l'exemple suivant, toute requête pour un fichier image sera
transmise par Apache à votre serveur d'images dédié. La correspondance est
insensible à la casse, si bien que par exemple, <code>.jpg</code> aussi
bien que <code>.JPG</code> seront acceptés.</p>
<highlight language="config">RewriteRule "(.*\.(jpg|gif|png))$" "http://images.example.com$1" [P,NC]</highlight>
</section>
<section id="flag_ne"><title>NE|noescape</title>
<p>Par défaut, lorsqu'une directive <directive
module="mod_rewrite">RewriteRule</directive> résulte en une redirection externe,
tout caractère dans la sortie qui ne fait pas partie de l'ensemble sûr suivant
est converti en son code hexa (encodage avec caractère pourcentage) :</p>
<ul>
<li>Caractères alphanumériques : <code>A-Z</code>, <code>a-z</code>,
<code>0-9</code></li>
<li>Caractères spéciaux : <code>$-_.+!*'(),:;@&amp;=/~</code></li>
</ul>
<p>Par exemple, <code>#</code> est converti en <code>%23</code> et
<code>?</code> en <code>%3F</code>. Le caractère <code>%</code> est aussi
échappé (vers <code>%25</code>), ce qui signifie que tout caractère codé avec
pourcentage déjà présent dans la substitution sera doublement encodé.</p>
<p>Utiliser le drapeau [NE] empêche cet échappement, ce qui permet de
transmettre sans modification vers l'URL de redirection des caractères comme
<code>#</code> et <code>?</code>.</p>
<highlight language="config">RewriteRule "^/anchor/(.+)" "/bigpage.html#$1" [NE,R]</highlight>
<p>
Dans l'exemple ci-dessus, <code>/anchor/xyz</code> est réécrit en
<code>/bigpage.html#xyz</code>. En l'absence du drapeau [NE], le #
aurait été converti en son équivalent hexadécimal, <code>%23</code>, ce
qui aurait provoqué un code d'erreur "404 Not Found".
</p>
<p>Voir <a href="tech.html#encoding">Encodage et décodage des URLs</a> pour une
description complète de la manière dont httpd encode et décode les URLs lors de
la réécriture.</p>
</section>
<section id="flag_ns"><title>NS|nosubreq</title>
<p>Le drapeau [NS] empêche la règle de s'appliquer aux sous-requêtes.
Par exemple, une page incluse au moyen d'une SSI (Server
Side Include) est une sous-requête, et vous ne voudrez probablement pas que
la réécriture s'applique à ces sous-requêtes. Ainsi, lorsque
<module>mod_dir</module> recherche des informations à propos des
fichiers par défaut du répertoire (comme les fichiers
<code>index.html</code>), il s'agit d'une sous-requête interne, et vous
ne désirez en général pas que ces sous-requêtes soient réécrites. Cette
réécriture
n'est pas toujours utile pour les sous-requêtes, et peut même causer des
erreurs si l'ensemble du jeu de règles est appliqué. L'utilisation de
ce drapeau permet d'exclure les règles qui peuvent poser problème.</p>
<p>Comment déterminer si vous devez utiliser cette règle ou non : si
vous préfixez les URLs avec des scripts CGI, afin de forcer leur
traitement par le script CGI, vous vous exposez à des problèmes (ou du
moins à une surcharge significative) avec les sous-requêtes. Dans ces
cas, vous devez utiliser ce drapeau.</p>
<p>
Les images, scripts java, ou fichiers css, chargés en tant que partie
d'une page html, ne sont pas des sous-requêtes - le navigateur les
appelle sous forme de requêtes HTTP à part entière.
</p>
<highlight language="config">
# Ne réécrire que les requêtes directes vers le contrôleur frontal, pas les
# sous-requêtes des inclusions SSI ou de mod_dir.
RewriteCond "%{REQUEST_FILENAME}" !-f
RewriteCond "%{REQUEST_FILENAME}" !-d
RewriteRule "^(.*)$" "/app/index.php?page=$1" [NS,L]
</highlight>
</section>
<section id="flag_p"><title>P|proxy</title>
<p>L'utilisation du drapeau [P] entraîne le traitement de la requête par
le module <module>mod_proxy</module>, et ceci via une requête de
mandataire. Par exemple, si vous voulez que toutes les requêtes d'images
soient traitées par un serveur d'images annexe, vous pouvez utiliser
une règle de ce style :</p>
<highlight language="config">RewriteRule "/(.*)\.(jpg|gif|png)$" "http://images.example.com/$1.$2" [P]</highlight>
<p>L'utilisation du drapeau [P] provoque aussi l'effet du drapeau [L] -
autrement dit, la requête est immédiatement envoyée au mandataire, et
toute règle ultérieure sera ignorée.</p>
<p>
Vous devez vous assurer que la chaîne de substitution soit un URL valide
(commençant typiquement par <code>http://</code><em>nom-serveur</em>)
qui puisse être traitée par le module <module>mod_proxy</module>. Dans
le cas contraire, le module mandataire vous renverra une erreur.
L'utilisation de ce drapeau implémente de manière plus puissante la
directive <directive module="mod_proxy">ProxyPass</directive>, pour
faire correspondre le contenu distant à l'espace de nommage du serveur
local.</p>
<note type="warning">
<title>Avertissement à propos de la sécurité</title>
<p>Lors de la construction de l'URL cible de la règle, il convient de
prendre en compte l'impact en matière de sécurité qu'aura le fait de
permettre au client d'influencer le jeu d'URLs pour lesquelles votre
serveur agira en tant que mandataire. Si une partie de l’URL cible est
dérivée de l’entrée de l’utilisateur (références arrières, chaînes de
paramètres, etc.), un attaquant pourra être capable de faire que votre
serveur génère des requêtes vers des hôtes internes ou externes
arbitraires. Cette vulnérabilité est connue sous le nom de falsification
de requête côté serveur (Server-Side Request Forgery — SSRF). Assurez-vous
que la partie protocole://nom-serveur de l'URL soit fixe, ou ne permette
pas au client de l'influencer indument.</p>
</note>
<note type="warning">
<title>Avertissement au sujet des performances</title>
<p>Utiliser ce drapeau fait intervenir <module>mod_proxy</module> sans la
gestion des connexions persistantes car dans ce cas, c'est le worker par
défaut qui est utilisé, et ce dernier ne gère pas la mise en commun et la
réutilisation des connexions.</p>
<p>Pour utiliser les connexions persistantes, vous devez définir un bloc
<directive module="mod_proxy">Proxy</directive>, au moins pour les parties
protocole et hôte de l'URL cible, et contenant une directive <directive
module="mod_proxy">ProxySet</directive> où vous définissez par exemple un
délai.</p>
<p>Si vous le définissez avec une directive <directive
module="mod_proxy">ProxyPass</directive> ou <directive
module="mod_proxy">ProxyPassMatch</directive>, les connexions persistantes
seront automatiquement utilisées.</p>
</note>
<p>Note: <module>mod_proxy</module> doit être activé pour pouvoir
utiliser ce drapeau.</p>
</section>
<section id="flag_pt"><title>PT|passthrough</title>
<p>
Par défaut, la cible (ou chaîne de substitution) d'une règle
RewriteRule est sensée être un chemin de fichier. Avec le drapeau [PT],
par contre, elle est traitée comme un chemin URL. Autrement dit, avec le
drapeau [PT], le résultat de la règle <directive
module="mod_rewrite">RewriteRule</directive> est passé à nouveau au
système de mise en correspondance des URLs avec le système de fichiers,
de façon à ce que les systèmes de mise en correspondance basés sur les
chemins de fichiers, comme la directive <directive
module="mod_alias">Alias</directive>, <directive
module="mod_alias">Redirect</directive>, ou <directive
module="mod_alias">ScriptAlias</directive>, par exemple, puissent avoir une
chance d'accomplir leur tâche.
</p>
<p>
Si par exemple, vous avez un <directive
module="mod_alias">Alias</directive> pour /icons, et une règle <directive
module="mod_rewrite">RewriteRule</directive> qui renvoie vers /icons,
vous devez utiliser le drapeau [PT] pour être sûr que l'<directive
module="mod_alias">Alias</directive> sera bien évalué.
</p>
<highlight language="config">
Alias "/icons" "/usr/local/apache/icons"
RewriteRule "/pics/(.+)\.jpg$" "/icons/$1.gif" [PT]
</highlight>
<p>
Dans l'exemple précédent, en l'absence du drapeau [PT], l'Alias aurait
été ignoré, ce qui aurait provoqué une erreur 'File not found'.
</p>
<p>Avec le drapeau <code>PT</code>, le drapeau <code>L</code> est
implicite : la réécriture s'arrêtera afin de transmettre la requête à la
phase suivante du traitement.</p>
<p>Notez que le drapeau <code>PT</code> est implicite dans des contextes
de répertoire comme les sections <directive type="section"
module="core">Directory</directive> ou les fichiers
<code>.htaccess</code>. Le seul moyen de contourner ceci consiste à
réécrire vers <code>-</code>.</p>
</section>
<section id="flag_qsa"><title>QSA|qsappend</title>
<p>
Quand l'URL de remplacement contient une chaîne de requête, le
comportement par défaut de la règle <directive
module="mod_rewrite">RewriteRule</directive> est de supprimer la <code>
query string</code> (il s'agit des paramètres éventuellement passés dans l'URL après le
caractère <code>?</code>, usuellement pour les formulaires traités par la
méthode HTTP <code>GET</code>) existante, et de la remplacer par celle nouvellement créée.
Avec le drapeau [QSA], les chaînes de requête peuvent être combinées.
</p>
<p>Considérons la règle suivante :</p>
<highlight language="config">RewriteRule "/pages/(.+)" "/page.php?page=$1" [QSA]</highlight>
<p>Avec le drapeau [QSA], une requête pour
<code>/pages/123?one=two</code> sera réécrite en
<code>/page.php?page=123&amp;one=two</code>. Sans le drapeau [QSA], la
même requête sera réécrite en <code>/page.php?page=123</code> -
autrement dit, la chaîne de requête (<code>query string</code>) existante sera supprimée.
</p>
</section>
<section id="flag_qsd"><title>QSD|qsdiscard</title>
<p>
Lorsque l'URL de la requête contient une chaîne de paramètres, et si
l'URI cible n'en contient pas, le comportement par défaut de la
directive <directive module="mod_rewrite">RewriteRule</directive> consiste à copier cette
chaîne de paramètres dans l'URL cible. Avec le drapeau [QSD], la chaîne
de paramètres est supprimée.
</p>
<p>Ce drapeau est disponible dans les versions 2.4.0 et supérieures.</p>
<p>
Lorsque les drapeaux [QSD] et [QSA] sont utilisés ensemble, c'est le
drapeau [QSD] qui l'emporte.
</p>
<p>
Si l'URL cible possède une chaîne de paramètres, le comportement par
défaut sera respecté - c'est à dire que la chaîne de paramètres
originale sera supprimée et remplacée par la chaîne de paramètres de
l'URL cible.
</p>
<highlight language="config">
# Redirection des anciens URLs « search » vers le nouveau chemin en supprimant
# la chaîne de paramètres. /search?q=term&amp;page=2 devient /find (chaîne de
# paramètres supprimée)
RewriteRule "^/search" "/find" [QSD,R=301,L]
</highlight>
</section>
<section id="flag_qsl"><title>QSL|qslast</title>
<p>
Par défaut, le premier (le plus à gauche) point d'interrogation de la
substitution sépare le chemin de la requête de sa chaîne de paramètres. Avec le
drapeau [QSL] au contraire, les deux composants seront séparés en utilisant le
dernier (le plus à droite) point d'interrogation.</p>
<p>
Cela peut s'avérer utile lorsqu'on recherche un fichier dont le nom contient des
points d'interrogation. Si aucune chaîne de paramètre n'est présente dans la
substitution, il est alors possible d'ajouter un point d'interrogation à la fin
et d'utiliser ce drapeau.</p>
<p>Par exemple, si une application patrimoniale attend une chaîne de paramètres
qui contient elle-même un point d’interrogation :</p>
<highlight language="config">
# Associe /lookup/foo?bar à /app?type=foo?bar
# Sans [QSL], le premier ? dans la substitution couperait le chemin, en
# produisant incorrectement /app avec la chaîne de paramètres type=foo?bar.
# Avec [QSL], le DERNIER ? est utilisé comme délimiteur.
RewriteRule "^/lookup/(.*)" "/app?type=$1" [QSL,PT]
</highlight>
<p>Sans [QSL], la substitution <code>/app?type=foo?bar</code> serait coupée au
premier <code>?</code>, perdant de ce fait le point d’interrogation littéral de
la valeur.</p>
<p>Ce drapeau est disponible à partir de la version 2.4.19 du serveur HTTP
Apache.</p>
</section>
<section id="flag_r"><title>R|redirect</title>
<p>
L'utilisation du drapeau [R] provoque l'envoi d'une redirection au
navigateur. Si une URL pleinement qualifiée (FQDN - fully qualified domain name)
est spécifiée (c'est à dire incluant <code>http://nom-du-serveur/</code>),
une redirection sera effectuée vers cette adresse. Dans le cas contraire,
le protocole courant, le nom du serveur et le numéro de port seront
utilisés pour générer l'URL envoyée avec la redirection.
</p>
<p><em>Tout</em> code de statut de réponse HTTP valide peut être
spécifié, en utilisant la syntaxe [R=305], le code de statut 302 étant
utilisé par défaut si aucun code n'est spécifié. Le code de statut
spécifié n'est pas nécessairement un code de statut
de redirection (3xx). Cependant, si le code de statut est en dehors de la plage des codes de
redirection (300-399), la chaîne de substitution est entièrement
supprimée, et la réécriture s'arrête comme si le drapeau <code>L</code>
était utilisé.</p>
<p>En plus des codes de statut de réponse, vous pouvez spécifier les
codes de redirection en utilisant leurs noms symboliques :
<code>temp</code> (défaut), <code>permanent</code>, ou
<code>seeother</code>.</p>
<p>
Vous utiliserez presque toujours [R] en conjonction avec [L] (c'est à
dire [R,L]), car employé seul, le drapeau [R] préfixe le chemin URL avec
<code>http://cet-hôte[:ce-port]</code>, mais passe ensuite cette adresse
à la règle suivante, ce qui provoquera le plus souvent des
avertissements 'Invalid URI in request'.
</p>
<p>Remarque&nbsp;: httpd ne prend en charge que les codes d'état inclus dans la
spécification de HTTP. Utiliser un code d'état non reconnu provoquera une erreur
500 et l'enregistrement d'un message dans le journal des erreurs.</p>
<note type="warning"><title>[R=4xx] ne sert pas la substitution</title>
<p>Lorsqu’un code d’état en dehors de l’intervalle 300-399 est spécifié (par
exemple <code>[R=403]</code> ou <code>[R=410]</code>), la chaîne de substitution
est ignorée. L’URL que vous avez saisi comme cible n’est pas servi au client. À
la place, httpd renvoie le code d’état spécifié et le traite de la manière
habituelle pour les réponses d'erreur (entre autres tout <directive
module="core">ErrorDocument</directive> configuré). Si vous souhaitez interdire
l’accès, les drapeaux <a href="#flag_f">[F]</a> et <a href="#flag_g">[G]</a>
sont des solutions plus adaptées pour exprimer la même intention.</p>
</note>
<highlight language="config">
# Redirection des requêtes pour l’ancien chemin de la documentation vers le
# nouvel emplacement.
RewriteRule "^/docs/(.*)$" "http://docs.example.com/$1" [R=301,L]
</highlight>
</section>
<section id="flag_s"><title>S|skip</title>
<p>Le drapeau [S] sert à sauter des règles que vous ne voulez pas voir exécuter.
La syntaxe du drapeau [S] est [S=<em>N</em>], où <em>N</em> correspond au nombre
de règles à sauter (sous réserve que la règle <directive
module="mod_rewrite">RewriteRule</directive> corresponde et qu'au moins une
condition <directive module="mod_rewrite">RewriteCond</directive> préalable soit
vérifiée). Ceci peut s'interpréter comme une instruction <code>goto</code>
dans votre jeu de règles de réécriture. Dans l'exemple suivant, nous ne voulons
exécuter la règle <directive module="mod_rewrite">RewriteRule</directive> que si
le chemin URL demandé ne correspond pas à un fichier existant.</p>
<highlight language="config">
# La requête concerne-t-elle un fichier qui n'existe pas ?
RewriteCond "%{REQUEST_FILENAME}" !-f
RewriteCond "%{REQUEST_FILENAME}" !-d
# Si c'est la cas, on saute les deux règles de réécriture suivantes
RewriteRule ".?" "-" [S=2]
RewriteRule "(.*\.gif)" "images.php?$1"
RewriteRule "(.*\.html)" "docs.php?$1"
</highlight>
<p>Cette technique trouve son utilité dans le fait qu'une directive
<directive module="mod_rewrite">RewriteCond</directive> ne s'applique
qu'à la règle qui la suit immédiatement. Ainsi, si vous voulez
qu'une directive <code>RewriteCond</code> s'applique à plusieurs règles
<code>RewriteRule</code>, une technique possible consiste à inverser ces
conditions et ajouter une <code>RewriteRule</code> avec le drapeau [Skip]. Cette technique permet
d'élaborer des pseudo-constructions if-then-else : la dernière règle du
bloc then contiendra <code>skip=N</code>, où N est le nombre de règles
contenues dans le bloc else :</p>
<highlight language="config">
# Est-ce que le fichier existe ?
RewriteCond "%{REQUEST_FILENAME}" !-f
RewriteCond "%{REQUEST_FILENAME}" !-d
# Créer une structure conditionnelle if-then-else en sautant 3 lignes si nous
# avions l'intention d'aller au bloc &quot;else&quot;.
RewriteRule ".?" "-" [S=3]
# Si le fichier existe, alors :
RewriteRule "(.*\.gif)" "images.php?$1"
RewriteRule "(.*\.html)" "docs.php?$1"
# Passer le bloc &quot;else&quot;.
RewriteRule ".?" "-" [S=1]
# ELSE...
RewriteRule "(.*)" "404.php?file=$1"
# END
</highlight>
<p>Il est probablement plus aisé de définir ce genre de configuration
via les directives <directive type="section">If</directive>, <directive
type="section">ElseIf</directive>, et <directive
type="section">Else</directive>.</p>
</section>
<section id="flag_t"><title>T|type</title>
<p>Définit le type MIME de la réponse résultante renvoyée. L'effet est
identique à celui de la directive <directive
module="mod_mime">AddType</directive>.</p>
<p>Par exemple, vous pouvez utiliser la technique suivante pour servir
du code source Perl en tant que plein texte, s'il est requis d'une
certaine manière :</p>
<highlight language="config">
# Sert les fichier .pl en tant que plein texte
RewriteRule "\.pl$" "-" [T=text/plain]
</highlight>
<p>Ou encore, si vous possédez une caméra qui produit des fichiers
images jpeg sans extension, vous pouvez forcer le renvoi de ces images
avec le type MIME correct en se basant sur le nom du fichier :</p>
<highlight language="config">
# Les fichiers dont le nom contient 'IMG' sont des images jpg.
RewriteRule "IMG" "-" [T=image/jpg]
</highlight>
<p>Notez cependant qu'il s'agit d'un exemple trivial, et que le problème
aurait pu être résolu en utilisant à la place la directive <directive
type="section" module="core">FilesMatch</directive>. Il faut toujours
envisager la possibilité d'une solution alternative à un problème avant
d'avoir recours à la réécriture, qui sera toujours moins efficace qu'une
solution alternative.</p>
<p>
Dans un contexte de niveau répertoire, n'utilisez que <code>-</code>
(tiret) comme substitution, <em>dans toute la séquence de réécriture de
<module>mod_rewrite</module></em>, sinon le type MIME défini avec ce drapeau
sera perdu suite à un retraitement interne (y compris les séquences de
réécriture suivantes de <module>mod_rewrite</module>). Dans ce contexte, vous pouvez
utiliser le drapeau <code>L</code> pour terminer la séquence
<em>courante</em> de réécriture de <module>mod_rewrite</module>.</p>
</section>
<section id="flag_unsafe_allow_3f"><title>UnsafeAllow3F</title>
<p>Il est nécessaire de définir ce drapeau pour permettre à une réécriture
de continuer si la requête HTTP en cours d'écriture possède un point
d'interrogation encodé, «&nbsp;%3f&nbsp;», et si le résultat réécrit
contient un «&nbsp;?&nbsp;» dans la substitution. Cela protège d'une URL
malveillante tirant avantage d'une capture et d'une resubstitution du point
d'interrogation encodé.</p>
<highlight language="config">
# Un contrôleur frontal PHP qui route toutes les requêtes via un élément de la
# chaîne de paramètres.
# Sans UnsafeAllow3F, une requête comme /page%3Fname=test renverrait 403 Forbidden,
# car le substitution réécrite contient '?' alors que la requête originelle
# contient un caractère encodé '%3F'.
RewriteCond "%{REQUEST_FILENAME}" !-f
RewriteCond "%{REQUEST_FILENAME}" !-d
RewriteRule "(.+)" "index.php?route=$1" [L,QSA,UnsafeAllow3F]
</highlight>
<note type="warning">
L’existence de ce drapeau est due à <a
href="https://www.cve.org/CVERecord?id=CVE-2024-38474">CVE-2024-38474</a>. Ne
l’utilisez que dans les règles pour lesquelles vous êtes certain qu’un
<code>%3F</code> saisi par l’utilisateur dans la requête ne peut pas être
exploité pour manipuler la chaîne de paramètres de la cible de substitution.
Préférez autant que possible la restructuration des URLs pour éviter les points
d’interrogation encodés.
</note>
</section>
<section id="flag_unsafe_prefix_stat"><title>UnsafePrefixStat</title>
<p>La définition de ce drapeau est requise dans les substitutions à
l'échelle du serveur qui commencent par une variable ou une référence
arrière et se résolvent en un chemin du système de fichiers. Ces
substitutions ne sont pas préfixées par la racine des documents. Cela protège
d'un URL malveillant faisant correspondre la substitution développée à un
emplacement non souhaité du système de fichiers.</p>
<p><since>2.5.1</since></p>
<highlight language="config">
# Cette règle lance la substitution avec une référence arrière.
# Depuis la version 2.4.60, cette opération est rejetée par défaut pour empêcher
# le chemin développé de s’échapper de la racine des documents (CVE-2024-38475).
# N’ajoutez UnsafePrefixStat qu’après avoir vérifié que la substitution ne peut
# pas se résoudre en un chemin du système de fichiers en dehors de la racine des
# documents de votre site.
RewriteRule "^/mirror/(.+)$" "$1" [PT,UnsafePrefixStat]
</highlight>
<note type="warning">
L’existence de ce drapeau est due à <a
href="https://www.cve.org/CVERecord?id=CVE-2024-38475">CVE-2024-38475</a>. Sans
lui, une substitution commençant par une référence arrière ou une variable qui
correspond à un chemin existant du système de fichiers pourrait permettre à des
requêtes de s’échapper de la racine des documents. N’utilisez ce drapeau
qu’après avoir confirmé que la substitution est contrainte de manière adéquate.
</note>
</section>
<section id="flag_unc"><title>UNC</title>
<p>Définir ce drapeau empêche la fusion des slashes de début multiples tels
que ceux utilisés dans les chemins UNC de Windows. Ce drapeau n'est pas
nécessaire lorsque la substitution de la règle commence par des slashes
multiples littéraux.</p>
<p><since>2.5.1</since></p>
<highlight language="config">
# Sous Windows, réécriture vers un partage de fichiers UNC
# en utilisant une variable
# Sans [UNC], les barres obliques de tête dans la substitution seraient
# fusionnées (//server/share deviendrait /server/share).
RewriteCond "%{HTTP_HOST}" "^(.+)\.internal$"
RewriteRule "^/shared/(.*)$" "//%1/fileshare/$1" [UNC]
</highlight>
<p>Ce drapeau n’est pertinent que sous Windows. Il empêche httpd de fusionner
les doubles barres obliques de tête (<code>//</code>) qui sont présentes dans un
chemin UNC lorsque ce dernier a été construit à partir d’une référence arrière
ou d’une variable. Si la substitution commence par des doubles barres obliques
littérales, aucun drapeau n’est nécessaire.</p>
</section>
</manualpage>