| <?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: 1934878:1939369 (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="remapping.xml.meta"> | |
| <parentdocument href="./">Rewrite</parentdocument> | |
| <title>Redirection et remise en correspondance avec mod_rewrite</title> | |
| <summary> | |
| <p>Ce document est un complément à la <a | |
| href="../mod/mod_rewrite.html">Documentation de référence</a> de | |
| <module>mod_rewrite</module>. Il montre comment utiliser | |
| <module>mod_rewrite</module> pour rediriger et remettre en | |
| correspondance une requête. Il contient de | |
| nombreux exemples d'utilisation courante de <module>mod_rewrite</module> avec une | |
| description détaillée de leur fonctionnement.</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="htaccess.html">Réécritures par répertoire</a></seealso> | |
| <seealso><a href="flags.html">Drapeaux des règles RewriteRule</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="old-to-new"> | |
| <title>De l'ancienne à la nouvelle URL (en interne)</title> | |
| <dl> | |
| <dt>Description :</dt> | |
| <dd> | |
| <p>Supposons que nous ayons récemment renommé la page | |
| <code>foo.html</code> en <code>bar.html</code>, et voulions | |
| maintenant que l'ancienne URL soit toujours valide à des fins | |
| de compatibilité ascendante. En fait, on voudrait que le | |
| changement de nom soit transparent aux utilisateurs de | |
| l'ancienne URL.</p> | |
| </dd> | |
| <dt>Solution :</dt> | |
| <dd> | |
| <p>On réécrit l'ancienne URL en interne vers la nouvelle via | |
| la règle suivante :</p> | |
| <highlight language="config"> | |
| RewriteEngine on | |
| RewriteRule "^<strong>/foo</strong>\.html$" "<strong>/bar</strong>.html" [PT] | |
| </highlight> | |
| </dd> | |
| </dl> | |
| </section> | |
| <section id="https-redirect"> | |
| <title>Forcer HTTPS</title> | |
| <dl> | |
| <dt>Description :</dt> | |
| <dd> | |
| <p>Rediriger toutes les requêtes HTTP vers HTTPS. C’est un des | |
| emplois les plus courants de <module>mod_rewrite</module>, mais dans la | |
| plupart des cas, on y parvient d’une meilleur façon sans lui.</p> | |
| </dd> | |
| <dt>Solution :</dt> | |
| <dd> | |
| <p>L’approche préférée utilise une directive <directive | |
| module="mod_alias">Redirect</directive> dans un serveur virtuel HTTP | |
| dédié :</p> | |
| <highlight language="config"> | |
| <VirtualHost *:80> | |
| ServerName www.example.com | |
| Redirect permanent "/" "https://www.example.com/" | |
| </VirtualHost> | |
| <VirtualHost *:443> | |
| ServerName www.example.com | |
| # ... emplacement de la configuration SSL | |
| </VirtualHost> | |
| </highlight> | |
| </dd> | |
| <dt>Explication :</dt> | |
| <dd> | |
| <p>Si vous n’avez pas accès à la configuration du serveur et devez | |
| utiliser un fichier <code>.htaccess</code>, <module>mod_rewrite</module> | |
| sera l’outil approprié :</p> | |
| <highlight language="config"> | |
| RewriteEngine On | |
| RewriteCond "%{HTTPS}" !=on | |
| RewriteRule "^(.*)" "https://%{SERVER_NAME}$1" [R=301,L] | |
| </highlight> | |
| <p>La variable <code>%{HTTPS}</code> est définie à <code>on</code> si | |
| la connexion utilise SSL/TLS, et est vide ou à <code>off</code> dans le | |
| cas contraire. Utiliser <code>R=301</code> produit une redirection | |
| permanente qui signale aux moteurs de recherche qu’ils doivent mettre | |
| leur index à jour.</p> | |
| <p>Voir aussi le document <a href="avoid.html#redirect">Quand ne pas | |
| utiliser mod_rewrite</a> pour plus de discussions à propos de l’approche | |
| <code>Redirect</code>.</p> | |
| <note><title>Derrière un répartiteur de charge ou un terminateur SSL</title> | |
| <p>La variable <code>%{HTTPS}</code> n’est pas une variable | |
| d’environnement à usage général — elle interroge directement | |
| <module>mod_ssl</module>. Si la terminaison SSL/TLS est effectuée au | |
| niveau d'un répartiteur de charge ou d'un mandataire inverse en amont, | |
| <module>mod_ssl</module> ne gère pas la connexion et <code>%{HTTPS}</code> | |
| indiquera toujours <code>off</code>, même si le client originel s’est | |
| connecté en HTTPS.</p> | |
| <p>Dans cette situation, il faut plutôt consulter l’en-tête défini par le | |
| mandataire en amont. La plupart des répartiteurs de charge définissent | |
| <code>X-Forwarded-Proto</code> :</p> | |
| </note> | |
| <highlight language="config"> | |
| RewriteEngine On | |
| RewriteCond "%{HTTP:X-Forwarded-Proto}" =http [NC] | |
| RewriteRule "^(.*)" "https://%{SERVER_NAME}$1" [R=301,L] | |
| </highlight> | |
| <note type="warning"> | |
| <p>Ne faites confiance à <code>X-Forwarded-Proto</code> que si vous | |
| contrôlez le mandataire en amont et qu'il écrase l'en-tête à chaque | |
| requête. Un attaquant pourrait corrompre cet en-tête en se connectant | |
| directement à votre serveur. Assurez-vous de restreindre l’accès de façon | |
| que seul votre répartiteur de charge puisse atteindre le serveur dorsal, | |
| ou utilisez <module>mod_remoteip</module> pour valider la source.</p> | |
| </note> | |
| </dd> | |
| </dl> | |
| </section> | |
| <section id="acme-exemption"> | |
| <title>Exempter les requêtes de défi ACME de la redirection HTTPS</title> | |
| <dl> | |
| <dt>Description :</dt> | |
| <dd> | |
| <p>Vous avez forcé tout le trafic à s’effectuer en HTTPS (comme ci-avant), | |
| mais votre client ACME (Let's Encrypt, Certbot, etc.) nécessite un accès | |
| en HTTP à <code>/.well-known/acme-challenge/</code> pour achever la | |
| validation du domaine.</p> | |
| </dd> | |
| <dt>Solution :</dt> | |
| <dd> | |
| <p>Placer une exception <em>avant</em> la règle de redirection HTTPS :</p> | |
| <highlight language="config"> | |
| RewriteEngine On | |
| RewriteRule "^/\.well-known/acme-challenge/" - [L] | |
| RewriteCond "%{HTTPS}" !=on | |
| RewriteRule "^(.*)" "https://%{SERVER_NAME}$1" [R=301,L] | |
| </highlight> | |
| </dd> | |
| <dt>Explication :</dt> | |
| <dd> | |
| <p>La substitution matérialisée par un tiret (<code>-</code>) signifie | |
| « ne pas réécrire ». En combinaison avec le drapeau <code>[L]</code>, elle | |
| arrête le traitement des règles pour toute requête correspondant au chemin | |
| du défi ACME, permettant à cette dernière d’être servie en HTTP. Le | |
| traitement de toutes les autres requêtes continue avec la règle suivante | |
| et les redirige vers HTTPS de la manière habituelle.</p> | |
| <p>Si vous adoptez l’approche par la directive <directive | |
| module="mod_alias">Redirect</directive> dans un serveur virtuel dédié au | |
| port 80, utilisez les directives <directive | |
| module="mod_alias">Alias</directive> et <directive | |
| module="mod_alias">RedirectMatch</directive> à la place :</p> | |
| <highlight language="config"> | |
| <VirtualHost *:80> | |
| ServerName www.example.com | |
| # Permettre les défis ACME sur HTTP | |
| Alias "/.well-known/acme-challenge/" "/var/www/acme/.well-known/acme-challenge/" | |
| <Directory "/var/www/acme/.well-known/acme-challenge"> | |
| Require all granted | |
| </Directory> | |
| # Tout le reste est redirigé vers HTTPS | |
| RedirectMatch permanent "^/(?!\.well-known/acme-challenge/)(.*)$" "https://www.example.com/$1" | |
| </VirtualHost> | |
| </highlight> | |
| </dd> | |
| </dl> | |
| </section> | |
| <section id="trailing-slash"> | |
| <title>Normalisation de la barre oblique de fin</title> | |
| <dl> | |
| <dt>Description :</dt> | |
| <dd> | |
| <p>Vous souhaitez que les URLs pour des répertoires se terminent toujours | |
| par une barre oblique ou, au contraire, que ce ne soit jamais le cas. | |
| Il s’agit d’un prérequis courant pour SEO et pour la gestion cohérente des | |
| URLs par les applications web.</p> | |
| </dd> | |
| <dt>Solution :</dt> | |
| <dd> | |
| <p>Pour ajouter une barre oblique de fin aux URLs qui correspondent à des | |
| répertoires :</p> | |
| <highlight language="config"> | |
| RewriteCond "%{REQUEST_FILENAME}" -d | |
| RewriteCond "%{REQUEST_URI}" "!/$" | |
| RewriteRule "^(.*)$" "$1/" [R=301,L] | |
| </highlight> | |
| <p>Pour supprimer la barre oblique de fin (sauf pour les véritables | |
| répertoires) :</p> | |
| <highlight language="config"> | |
| RewriteCond "%{REQUEST_FILENAME}" !-d | |
| RewriteCond "%{REQUEST_URI}" "(.+)/$" | |
| RewriteRule "^" "%1" [R=301,L] | |
| </highlight> | |
| </dd> | |
| <dt>Explication :</dt> | |
| <dd> | |
| <p>Le module <module>mod_dir</module> de httpd gère déjà les redirections | |
| de barre oblique de fin pour les véritables répertoires lorsque la | |
| directive <directive module="mod_dir">DirectorySlash</directive> est | |
| activée (elle l’est par défaut). Vous n’avez besoin que d’une règle de | |
| <module>mod_rewrite</module> si vous souhaitez imposer un comportement | |
| pour les barres obliques de fin pour les URLs qui ne correspondent pas à | |
| de véritables répertoires sur disque, ou si vous voulez supprimer des | |
| barres obliques de fin.</p> | |
| </dd> | |
| </dl> | |
| </section> | |
| <section id="front-controller"> | |
| <title>Contrôleur frontal / Routage d’pplication</title> | |
| <p>La plupart des cadriciels web modernes routent toutes les requêtes vers un | |
| seul point d’entrée : le contrôleur frontal (« front controller »). La | |
| directive <directive module="mod_dir">FallbackResource</directive> gère cela | |
| plus simplement et efficacement que <module>mod_rewrite</module>. Voir le | |
| document <a href="avoid.html#fallback-resource">Quand ne pas utiliser | |
| mod_rewrite</a> pour l’approche recommandée.</p> | |
| <p>Si vous avez réellement besoin de <module>mod_rewrite</module> pour cela | |
| (par exemple, pour ajouter des conditions plus complexes que « fichier non | |
| existant »), consultez le document <a | |
| href="htaccess.html#rewritebase">Réécritures par répertoire</a> pour un | |
| exemple annoté qui illustre aussi l’utilisation de la directive <directive | |
| module="mod_rewrite">RewriteBase</directive>.</p> | |
| </section> | |
| <section id="old-to-new-extern"> | |
| <title>De l'ancien au nouveau (en externe)</title> | |
| <dl> | |
| <dt>Description :</dt> | |
| <dd> | |
| <p>Supposons toujours que nous ayons récemment renommé la page | |
| <code>foo.html</code> en <code>bar.html</code>, et voulions | |
| maintenant que l'ancienne URL soit toujours valide à des fins | |
| de compatibilité ascendante. En revanche, nous voulons cette | |
| fois que la nouvelle URL soit suggérée aux utilisateurs de | |
| l'ancienne URL, c'est à dire que l'adresse vue depuis leur | |
| navigateur doit également être modifiée.</p> | |
| </dd> | |
| <dt>Solution :</dt> | |
| <dd> | |
| <p>On force une redirection HTTP vers la nouvelle URL, ce qui | |
| entraîne une modification de celle du navigateur et aussi de ce | |
| que voit l'utilisateur :</p> | |
| <highlight language="config"> | |
| RewriteEngine on | |
| RewriteRule "^<strong>foo</strong>\.html$" "<strong>bar</strong>.html" [<strong>R</strong>] | |
| </highlight> | |
| </dd> | |
| <dt>Explication</dt> | |
| <dd> | |
| <p>Dans l'exemple <a | |
| href="#old-to-new-intern">interne</a>, on a utilisé <module>mod_rewrite</module> afin | |
| de dissimuler la redirection au client. Dans cet exemple, en | |
| revanche, on aurait pu se contenter d'une directive Redirect :</p> | |
| <highlight language="config">Redirect "/foo.html" "/bar.html"</highlight> | |
| </dd> | |
| </dl> | |
| </section> | |
| <section id="movehomedirs"> | |
| <title>Ressource déplacée vers un autre serveur</title> | |
| <dl> | |
| <dt>Description :</dt> | |
| <dd> | |
| <p>Si une ressource a été déplacée vers un autre serveur, vous | |
| pouvez faire en sorte que les URLs de l'ancien serveur continuent | |
| de fonctionner pendant un certain temps, afin de laisser au | |
| utilisateurs le temps de modifier leurs favoris.</p> | |
| </dd> | |
| <dt>Solution :</dt> | |
| <dd> | |
| <p>Vous pouvez utiliser <module>mod_rewrite</module> pour | |
| rediriger ces URLs vers le nouveau serveur, mais vous pouvez aussi | |
| utiliser les directives Redirect ou RedirectMatch.</p> | |
| <highlight language="config">#Avec mod_rewrite | |
| RewriteEngine on | |
| RewriteRule "^/docs/(.+)" "http://nouveau.example.com/docs/$1" [R,L] | |
| </highlight> | |
| <highlight language="config">#Avec RedirectMatch | |
| RedirectMatch "^/docs/(.*)" "http://nouveau.example.com/docs/$1" | |
| </highlight> | |
| <highlight language="config">#Avec Redirect | |
| Redirect "/docs/" "http://nouveau.example.com/docs/" | |
| </highlight> | |
| </dd> | |
| <dt>Explication :</dt> | |
| <dd> | |
| <p>Pour une simple redirection vers un autre serveur, il est préférable | |
| d’utiliser les directives <directive | |
| module="mod_alias">Redirect</directive> ou <directive | |
| module="mod_alias">RedirectMatch</directive>, car elles sont plus simples | |
| et plus efficaces.</p> | |
| </dd> | |
| </dl> | |
| </section> | |
| <section id="backward-compatibility"> | |
| <title>Compatibilité ascendante dans le cadre d'une modification | |
| d'extension de nom de fichier</title> | |
| <dl> | |
| <dt>Description :</dt> | |
| <dd> | |
| <p>Comment conférer une compatibilité ascendante aux URLs | |
| (existant encore virtuellement) après avoir migré | |
| <code>document.YYYY</code> vers <code>document.XXXX</code>, | |
| c'est à dire après avoir par exemple traduit un lot de | |
| fichiers <code>.html</code> en fichiers <code>.php</code> | |
| ?</p> | |
| </dd> | |
| <dt>Solution :</dt> | |
| <dd> | |
| <p>L’URL n’est réécrite en remplaçant l’ancienne extension par la | |
| nouvelle que si le fichier cible avec la nouvelle extension existe et | |
| si le fichier originel avec l’ancienne extension n’existe pas. Sinon, | |
| l’URL reste inchangée.</p> | |
| <highlight language="config"> | |
| # jeu de règles assurant une compatibilité ascendante en réécrivant<br /> | |
| # document.html en document.php si et seulement si document.php<br /> | |
| # existe | |
| <Directory "/var/www/htdocs"> | |
| RewriteEngine on | |
| RewriteBase "/var/www/htdocs" | |
| RewriteCond "$1.php" -f | |
| RewriteCond "$1.html" !-f | |
| RewriteRule "^(.*).html$" "$1.php" | |
| </Directory> | |
| </highlight> | |
| </dd> | |
| <dt>Explication</dt> | |
| <dd> | |
| <p>Cet exemple utilise une fonctionnalité souvent méconnue de | |
| <module>mod_rewrite</module>, en tirant avantage de l'ordre d'exécution du jeu de | |
| règles. En particulier, <module>mod_rewrite</module> évalue la partie gauche des | |
| règles de réécriture avant d'évaluer les directives RewriteCond. En | |
| conséquence, $1 est déjà défini au moment où les directives | |
| RewriteCond sont évaluées. Ceci nous permet de tester l'existence du | |
| fichier original (<code>document.html</code>) et du fichier cible | |
| (<code>document.php</code>) en utilisant le même nom de base.</p> | |
| <p>Ce jeu de règles est conçu pour une utilisation dans un contexte | |
| de répertoire (au sein d'une section <Directory> ou d'un | |
| fichier .htaccess), de façon à ce que les vérifications | |
| <code>-f</code> effectuent leurs recherches dans le bon répertoire. | |
| Vous serez peut-être amené à définir une directive <directive | |
| module="mod_rewrite">RewriteBase</directive> pour spécifier le | |
| répertoire de base à partir duquel vous travaillez.</p> | |
| </dd> | |
| </dl> | |
| </section> | |
| <section id="canonicalhost"> | |
| <title>Noms d'hôtes canoniques</title> | |
| <dl> | |
| <dt>Description :</dt> | |
| <dd>Le but de cette règle est de préférer l'utilisation d'un nom | |
| d'hôte particulier à d'autres noms d'hôte utilisables | |
| pour atteindre le même site. Par exemple, si vous voulez | |
| utiliser <strong>www.example.com</strong> à la place de | |
| <strong>example.com</strong>, vous pouvez utiliser une solution | |
| du style :</dd> | |
| <dt>Solution :</dt> | |
| <dd> | |
| <p>Pour y parvenir, il vaut mieux se passer de <module>mod_rewrite</module>, et utiliser | |
| plutôt la directive <directive module="mod_alias">Redirect</directive> dans | |
| une section de serveur virtuel pour le/les noms d'hôte non canoniques.</p> | |
| <highlight language="config"> | |
| <VirtualHost *:80> | |
| ServerName undesired.example.com | |
| ServerAlias example.com notthis.example.com | |
| Redirect "/" "http://www.example.com/" | |
| </VirtualHost> | |
| <VirtualHost *:80> | |
| ServerName www.example.com | |
| </VirtualHost> | |
| </highlight> | |
| <p>Vous pouvez aussi utiliser la directive <directive module="core" | |
| type="section">If</directive> (versions 2.4 et ultérieures) :</p> | |
| <highlight language="config"> | |
| <If "%{HTTP_HOST} != 'www.example.com'"> | |
| Redirect "/" "http://www.example.com/" | |
| </If> | |
| </highlight> | |
| <p>Ou, par exemple, pour rediriger une portion de votre site vers HTTPS | |
| :</p> | |
| <highlight language="config"> | |
| <If "%{SERVER_PROTOCOL} != 'HTTPS'"> | |
| Redirect "/admin/" "https://www.example.com/admin/" | |
| </If> | |
| </highlight> | |
| <p>Si, pour une raison particulière, vous voulez tout de même utiliser | |
| <module>mod_rewrite</module> - dans le cas, par exemple, où vous avez besoin | |
| d'un jeu plus important de règles de réécritures - vous pouvez utiliser | |
| la recette suivante :</p> | |
| <p>Pour les sites écoutant sur un port autre que 80:</p> | |
| <highlight language="config"> | |
| RewriteCond "%{HTTP_HOST}" "!^www\.example\.com" [NC] | |
| RewriteCond "%{HTTP_HOST}" "!^$" | |
| RewriteCond "%{SERVER_PORT}" "!^80$" | |
| RewriteRule "^/?(.*)" "http://www.example.com:%{SERVER_PORT}/$1" [L,R,NE] | |
| </highlight> | |
| <p>Et pour un site écoutant sur le port 80</p> | |
| <highlight language="config"> | |
| RewriteCond "%{HTTP_HOST}" "!^www\.example\.com" [NC] | |
| RewriteCond "%{HTTP_HOST}" "!^$" | |
| RewriteRule "^/?(.*)" "http://www.example.com/$1" [L,R,NE] | |
| </highlight> | |
| <p> | |
| Si vous souhaitez que cette règle s'applique à tous les noms de | |
| domaine - en d'autres termes, si vous voulez rediriger | |
| <strong>example.com</strong> vers | |
| <strong>www.example.com</strong> pour toutes les valeurs | |
| possibles de <strong>example.com</strong>, vous pouvez utiliser | |
| le jeu de règles suivants :</p> | |
| <p>Pour faire l’inverse — supprimer le préfixe <code>www.</code> — inversez la | |
| condition :</p> | |
| <highlight language="config"> | |
| RewriteCond "%{HTTP_HOST}" "^www\.(.+)$" [NC] | |
| RewriteRule "^(.*)" "http://%1/$1" [L,R,NE] | |
| </highlight> | |
| <p>Pour ajouter de manière générique <code>www.</code> à tout nom d’hôte :</p> | |
| <highlight language="config"> | |
| RewriteCond "%{HTTP_HOST}" "!^www\." [NC] | |
| RewriteCond "%{HTTP_HOST}" "!^$" | |
| RewriteRule "^/?(.*)" "http://www.%{HTTP_HOST}/$1" [L,R,NE] | |
| </highlight> | |
| <p> | |
| Vous pouvez utiliser ce jeu de règles aussi bien dans le fichier | |
| de configuration de votre serveur principal que dans un fichier | |
| <code>.htaccess</code> placé dans le répertoire défini par la | |
| directive <directive | |
| module="core">DocumentRoot</directive> du serveur.</p> | |
| </dd> | |
| <dt>Explication :</dt> | |
| <dd> | |
| <p>Si vous avez accès à la configuration globale du serveur, une directive | |
| <directive module="mod_alias">Redirect</directive> dans un <directive | |
| module="core" type="section">serveur virtuel</directive> dédié constitue | |
| l’approche la plus propre. Mettre sous forme canonique le nom d’hôte | |
| permet de s’assurer que les moteurs de recherche traiterons votre site | |
| comme une seule entité, et évite les problèmes de portée de cookie qui | |
| surviennent lorsqu’un même site est accessible sous plusieurs noms.</p> | |
| <p>N’utilisez la directive <directive module="core" | |
| type="section">If</directive> et <module>mod_rewrite</module> comme | |
| compromis que si vous êtes contraint d’utiliser un fichier | |
| <code>.htaccess</code>.</p> | |
| </dd> | |
| </dl> | |
| </section> | |
| <section id="multipledirs"> | |
| <title>Recherche de pages dans plus d'un répertoire</title> | |
| <dl> | |
| <dt>Description:</dt> | |
| <dd> | |
| <p>Une ressource peut exister dans plusieurs répertoires, et nous | |
| voulons rechercher cette ressource dans ces répertoires | |
| lorsqu'elle fait l'objet d'une requête. Il est possible que nous | |
| ayons récemment réorganisé la structure de notre site en | |
| répartissant son contenu dans plusieurs répertoires.</p> | |
| </dd> | |
| <dt>Solution :</dt> | |
| <dd> | |
| <p>Le jeu de règles suivant recherche la ressource dans deux | |
| répertoires, et s'il ne la trouve dans aucun des deux, il tentera | |
| simplement de la servir à partir de l'adresse fournie dans la | |
| requête.</p> | |
| <highlight language="config"> | |
| RewriteEngine on | |
| # on cherche tout d'abord dans dir1/... | |
| # ... et si on trouve, on est content et on arrête : | |
| RewriteCond "%{DOCUMENT_ROOT}/<strong>dir1</strong>/%{REQUEST_URI}" -f | |
| RewriteRule "^(.+)" "%{DOCUMENT_ROOT}/<strong>dir1</strong>/$1" [L] | |
| # on cherche ensuite dans dir2/... | |
| # ... et si on trouve, on est content et on arrête : | |
| RewriteCond "%{DOCUMENT_ROOT}/<strong>dir2</strong>/%{REQUEST_URI}" -f | |
| RewriteRule "^(.+)" "%{DOCUMENT_ROOT}/<strong>dir2</strong>/$1" [L] | |
| # sinon, on continue la recherche avec d'autres directives Alias | |
| # ou ScriptAlias, etc... | |
| RewriteRule "^" "-" [PT] | |
| </highlight> | |
| </dd> | |
| <dt>Explication :</dt> | |
| <dd> | |
| <p>Ce qui précède s’avère utile pendant les migrations lorsque le contenu | |
| est déplacé d’un répertoire vers un autre. Pour une configuration | |
| permanente, utilisez plutôt la directive <directive | |
| module="mod_alias">Alias</directive> ou des liens symboliques.</p> | |
| </dd> | |
| </dl> | |
| </section> | |
| <section id="canonicalurl"> | |
| <title>URLs canoniques</title> | |
| <dl> | |
| <dt>Description :</dt> | |
| <dd> | |
| <p>Sur certains serveurs, une ressource peut posséder plusieurs | |
| URLs. Il y a en général les URLs canoniques (celles qui sont | |
| réellement distribuées et utilisées), et celles qui correspondent à | |
| des raccourcis, les URLs internes, etc... Quelle que soit l'adresse | |
| que l'utilisateur fournit dans la requête, il devrait finalement | |
| voir l'URL canonique dans la barre d'adresse de son navigateur.</p> | |
| </dd> | |
| <dt>Solution :</dt> | |
| <dd> | |
| <p>Nous effectuons une redirection HTTP externe pour toutes les | |
| URLs non canoniques afin de les corriger dans la barre d'adresse | |
| du navigateur, et ceci pour toutes les requêtes futures. Dans le | |
| jeu de règles suivant, nous remplaçons <code>/matous</code> et | |
| <code>/minettes</code> par le canonique <code>/chats</code>.</p> | |
| <highlight language="config">RewriteRule "^/(matous|minettes)/(.*)" "/chats/$2" [R]</highlight> | |
| </dd> | |
| <dt>Discussion :</dt> | |
| <dd>On serait mieux inspiré d'utiliser ici les directives Redirect ou | |
| RedirectMatch : | |
| <highlight language="config"> RedirectMatch "^/(matous|minettes)/(.*)" "/chats/$2" </highlight> | |
| </dd> | |
| </dl> | |
| </section> | |
| <section id="moveddocroot"> | |
| <title>Déplacement du répertoire <code>DocumentRoot</code></title> | |
| <dl> | |
| <dt>Description :</dt> | |
| <dd> | |
| <p>En général, le répertoire <directive | |
| module="core">DocumentRoot</directive> du serveur web correspond à l'URL | |
| "<code>/</code>". Ce répertoire ne contient cependant pas forcément des | |
| ressources de première importance pour l'utilisateur. Par exemple, vous | |
| préférerez peut-être que le répertoire d'accueil d'un visiteur accédant | |
| pour la première fois à votre site soit un répertoire particulier | |
| <code>/a-propos-de/</code>. Pour y parvenir, utilisez le jeu de règles | |
| suivant :</p> | |
| </dd> | |
| <dt>Solution :</dt> | |
| <dd> | |
| <p>On redirige l'URL <code>/</code> vers | |
| <code>/a-propos-de/</code> : | |
| </p> | |
| <highlight language="config"> | |
| RewriteEngine on | |
| RewriteRule "^/$" "/a-propos-de/" [<strong>R</strong>] | |
| </highlight> | |
| <p>Notez que l'on peut aussi y parvenir en utilisant la directive | |
| <directive module="mod_alias">RedirectMatch</directive> :</p> | |
| <highlight language="config">RedirectMatch "^/$" "http://example.com/a-propos-de/"</highlight> | |
| <p>Notez aussi que cet exemple ne réécrit que l'URL racine. En d'autres | |
| termes, il réécrit une requête pour <code>http://example.com/</code>, | |
| mais pas pour une requête <code>http://example.com/page.html</code>. Si | |
| vous avez effectivement modifié la racine de vos documents - c'est à dire | |
| si <strong>tous</strong> vos contenus se trouvent dans un | |
| sous-répertoire, il est largement préférable de modifier simplement | |
| votre directive <directive module="core">DocumentRoot</directive>, ou de | |
| déplacer l'ensemble du contenu vers le répertoire supérieur, plutôt que | |
| de réécrire les URLs.</p> | |
| </dd> | |
| </dl> | |
| </section> | |
| <section id="rewrite-query"> | |
| <title>Rewrite query string</title> | |
| <dl> | |
| <dt>Description :</dt> | |
| <dd>Vous voulez extraire une valeur particulière d'une chaîne de | |
| paramètres d'une URL, et soit la remplacer, soit l'incorporer dans un | |
| autre composant de l'URL.</dd> | |
| <dt>Solutions :</dt> | |
| <dd> | |
| <p>Dans la plupart des solutions de cette section, on utilise la même | |
| condition qui stocke la valeur recherchée dans la référence arrière %2. | |
| %1 est le début de la requête, et %3 ce qui reste. Cette condition est | |
| un peu complexe car elle introduit de la flexibilité et évite les | |
| doubles perluettes '&&' dans les substitutions.</p> | |
| <ul> | |
| <li>Cette solution supprime le couple clé/valeur recherché : | |
| <highlight language="config"> | |
| # Remove mykey=??? | |
| RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$" | |
| RewriteRule "(.*)" "$1?%1%3" | |
| </highlight> | |
| </li> | |
| <li>Cette solution remplace la partie de l'URL qui suit la valeur | |
| recherchée par un '?' : | |
| <highlight language="config"> | |
| # Copy from query string to PATH_INFO | |
| RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$" | |
| RewriteRule "(.*)" "$1/products/%2/?" [PT] | |
| </highlight> | |
| </li> | |
| <li>Cette solution utilise la valeur recherchée dans une deuxième | |
| condition :: | |
| <highlight language="config"> | |
| # Capture the value of mykey in the query string | |
| RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"" | |
| RewriteCond "%2" !=not-so-secret-value | |
| RewriteRule "(.*)" - [F] | |
| </highlight> | |
| </li> | |
| <li>Cette solution produit l'effet inverse des précédentes ; elle copie des | |
| composantes du chemin (peut-être <glossary | |
| ref="pathinfo">PATH_INFO</glossary>) depuis l'URL vers sa chaîne de paramètres | |
| : <highlight language="config"> | |
| # The desired URL might be /products/kitchen-sink, and the script expects | |
| # /path?products=kitchen-sink. | |
| RewriteRule "^/?path/([^/]+)/([^/]+)" "/path?$1=$2" [PT] </highlight> | |
| </li> | |
| </ul> | |
| </dd> | |
| <dt>Explication :</dt> | |
| <dd> | |
| <p>Voir aussi les drapeaux <a href="flags.html#flag_qsa">[QSA]</a> et <a | |
| href="flags.html#flag_qsd">[QSD]</a> qui permettent de contrôler si la chaîne de | |
| paramètres originelle est ajoutée à la fin de la substitution ou supprimée de | |
| cette dernière.</p> | |
| </dd> | |
| </dl> | |
| </section> | |
| <section id="structuredhomedirs"> | |
| <title>Répertoires utilisateur structurés</title> | |
| <dl> | |
| <dt>Description :</dt> | |
| <dd> | |
| <p>Certains sites avec plusieurs milliers d’utilisateurs possèdent une | |
| organisation structurée des répertoires utilisateur, c’est-à-dire que | |
| chaque répertoire utilisateur est dans un sous-répertoire qui commence | |
| (par exemple) par le premier caractère du nom de l’utilisateur. Ainsi, | |
| <code>/~larry/anypath</code> correspond à | |
| <code>/home/<strong>l</strong>/larry/public_html/anypath</code> et | |
| <code>/~waldo/anypath</code> à | |
| <code>/home/<strong>w</strong>/waldo/public_html/anypath</code>.</p> | |
| </dd> | |
| <dt>Solution :</dt> | |
| <dd> | |
| <p>Nous utilisons le jeu de règles suivant pour développer les URLs avec | |
| tilde selon l’organisation ci-dessus.</p> | |
| <highlight language="config"> | |
| RewriteEngine on | |
| RewriteRule "^/~(<strong>([a-z])</strong>[a-z0-9]+)(.*)" "/home/<strong>$2</strong>/$1/public_html$3" | |
| </highlight> | |
| </dd> | |
| <dt>Explication :</dt> | |
| <dd> | |
| <p>Cette technique est principalement utile pour les environnements | |
| d’hébergement de grande capacité avec plusieurs milliers d’utilisateurs. | |
| Pour la plupart des sites, <module>mod_userdir</module> gère les URLs | |
| utilisateur avec tilde sans avoir besoin de <module>mod_rewrite</module>.</p> | |
| </dd> | |
| </dl> | |
| </section> | |
| <section id="redirectanchors"> | |
| <title>Redirection vers une ancre</title> | |
| <dl> | |
| <dt>Description :</dt> | |
| <dd> | |
| <p>Par défaut, la redirection vers une ancre HTML ne fonctionne pas, car | |
| <module>mod_rewrite</module> échappe le caractère <code>#</code> en le | |
| remplaçant par <code>%23</code>, ce qui casse la redirection.</p> | |
| </dd> | |
| <dt>Solution :</dt> | |
| <dd> | |
| <p>Utiliser le drapeau <code>[NE]</code> dans la règle | |
| <code>RewriteRule</code>. NE signifie « No Escape ». | |
| </p> | |
| </dd> | |
| <dt>Explication :</dt> | |
| <dd>Bien entendu, cette technique fonctionne aussi pour d’autres caractères | |
| spéciaux que <module>mod_rewrite</module> encode par défaut pour les URLs.</dd> | |
| </dl> | |
| </section> | |
| <section id="time-dependent"> | |
| <title>Réécriture dépendant du temps</title> | |
| <dl> | |
| <dt>Description :</dt> | |
| <dd> | |
| <p>Nous voulons utiliser <module>mod_rewrite</module> pour servir des | |
| contenus différents en fonction de l’heure du jour.</p> | |
| </dd> | |
| <dt>Solution :</dt> | |
| <dd> | |
| <p>Il esixte de nombreuses variables nommées <code>TIME_xxx</code> à | |
| utiliser dans les conditions de réécriture. En combinaison avec les motifs | |
| de comparaison lexicographique spéciaux <code><STRING</code>, | |
| <code>>STRING</code> et <code>=STRING</code>, nous pouvons configurer | |
| des redirections dépendant du temps :</p> | |
| <highlight language="config"> | |
| RewriteEngine on | |
| RewriteCond "%{TIME_HOUR}%{TIME_MIN}" >0700 | |
| RewriteCond "%{TIME_HOUR}%{TIME_MIN}" <1900 | |
| RewriteRule "^foo\.html$" "foo.day.html" [L] | |
| RewriteRule "^foo\.html$" "foo.night.html" | |
| </highlight> | |
| <p>Cette configuration sert le contenu de <code>foo.day.html</code> sous | |
| l’URL <code>foo.html</code> de <code>07:01</code> à <code>18:59</code> et | |
| le contenu de <code>foo.night.html</code> pendant le temps restant.</p> | |
| <note type="warning"><module>mod_cache</module>, les mandataires | |
| intermédiaires et les navigateurs peuvent chacun mettre en cache les | |
| réponses et provoquer de ce fait l’affichage d’une page en dehors de la | |
| fenêtre de temps configurée. <module>mod_expires</module> permet de | |
| contrôler cet effet. Il est bien entendu préférable de simplement servir | |
| le contenu de manière dynamique et de le personnaliser en fonction de | |
| l’heure du jour.</note> | |
| </dd> | |
| <dt>Explication :</dt> | |
| <dd> | |
| <p>Servir du contenu dynamique par l’intermédiaire de votre application | |
| constitue pratiquement toujours une meilleure approche. La mise en cache | |
| par les navigateurs, les mandataires et <module>mod_cache</module> rend la | |
| réécriture en fonction du temps non fiable en pratique.</p> | |
| </dd> | |
| </dl> | |
| </section> | |
| <section id="on-the-fly-content"> | |
| <title>Régénération du contenu à la volée</title> | |
| <dl> | |
| <dt>Description :</dt> | |
| <dd> | |
| <p>Nous voulons générer dynamiquement du contenu, mais le stocker ensuite | |
| statiquement. La règle suivante va vérifier si le fichier | |
| statique existe, et le générer dans le cas contraire. Les fichiers | |
| statiques peuvent être supprimés périodiquement, si souhaité (par exemple | |
| via cron) et seront régénérés à la demande.</p> | |
| </dd> | |
| <dt>Solution :</dt> | |
| <dd> | |
| Pour ce faire, on utilise le jeu de règles suivant : | |
| <highlight language="config"> | |
| # Cet exemple n’est valable que dans un contexte de répertoire | |
| RewriteCond "%{REQUEST_URI}" !-U | |
| RewriteRule "^(.+)\.html$" "/regenerate_page.cgi" [PT,L] | |
| </highlight> | |
| <p>L’opérateur <code>-U</code> détermine si la chaîne de test (dans ce cas | |
| <code>REQUEST_URI</code>) est un URL valable. Il effectue cette opération | |
| via une sous-requête. Si cette sous-requête échoue — autrement dit, si la | |
| ressource demandée n’existe pas — cette règle invoque le programme CGI | |
| <code>/regenerate_page.cgi</code> qui va générer la ressource demandée et la | |
| sauvegarder dans le répertoire des documents de sorte qu’une copie statique | |
| puissent en être servie la prochaine fois qu’elle sera demandée.</p> | |
| <p>Ainsi, les documents qui ne sont pas souvent mis à jour peuvent être | |
| servis sous forme statique. Si ces documents doivent être rafraîchis, ils | |
| peuvent être supprimés du répertoire des documents ; ils seront alors | |
| régénérés la prochaine fois qu’ils seront demandés.</p> | |
| </dd> | |
| <dt>Explication :</dt> | |
| <dd> | |
| <p>Les approches modernes telles que <module>mod_cache</module>, les | |
| couches de mise en cache CDN ou la mise en cache au niveau de | |
| l’application fournissent des solutions plus robustes et configurables | |
| pour servir du contenu statique pré-généré. Le test de la sous-requête de | |
| l’opérateur <code>-U</code> utilisé ici induit un coût en performance à | |
| chaque requête.</p> | |
| </dd> | |
| </dl> | |
| </section> | |
| </manualpage> |