Ce document complète la documentation de référence du
module
[PT]
si vous utilisez les modules
.htaccess
.
Efforcez-vous toujours de bien comprendre l'effet produit par un jeu
de règles avant de l'utiliser, ce qui pourra vous éviter bien des
problèmes.Sur certains serveurs web, une ressource peut être accessible depuis plusieurs URLs. On trouve en général des URLs canoniques (qui sont réellement utilisables et distribuables), mais aussi des URLs à usage interne, ou celles qui ne sont que des raccourcis, etc... On souhaite que, quelle que soit l'URL que l'utilisateur a fournie avec sa requête, il ne doit en voir en fin de compte que la forme canonique.
On effectue une redirection HTTP externe pour toutes les URLs
non canoniques afin de les rendre compréhensibles au navigateur
et ceci pour toutes les requêtes sous-jacentes. Dans l'exemple de
jeux de règles ci-dessous, /~user
est remplacé par
l'expression canonique /u/user
, et une éventuelle
absence du slash à la fin de /u/user
est corrigée.
RewriteRule ^/~([^/]+)/?(.*) /u/$1/$2 [R] RewriteRule ^/u/([^/]+)$ /$1/$2/ [R]
Pour les sites écoutant sur un port autre que 80:
RewriteCond %{HTTP_HOST} !^www\.exemple\.com [NC] RewriteCond %{HTTP_HOST} !^$ RewriteCond %{SERVER_PORT} !^80$ RewriteRule ^/?(.*) http://www.example.com:%{SERVER_PORT}/$1 [L,R,NE]
Et pour un site écoutant sur le port 80
RewriteCond %{HTTP_HOST} !^www\.exemple\.com [NC] RewriteCond %{HTTP_HOST} !^$ RewriteRule ^/?(.*) http://www.example.com/$1 [L,R,NE]
Si vous souhaitez que cette règle s'applique à tous les noms de domaine - en d'autres termes, si vous voulez rediriger example.com vers www.example.com pour toutes les valeurs possibles de example.com, vous pouvez utiliser le jeu de règles suivants :
RewriteCond %{HTTP_HOST} !^www\. [NC] RewriteCond %{HTTP_HOST} !^$ RewriteRule ^/?(.*) http://www.%{HTTP_HOST}/$1 [L,R,NE]
Vous pouvez utiliser ce jeu de règles aussi bien dans le fichier
de configuration de votre serveur principal que dans un fichier
.htaccess
placé dans le répertoire défini par la
directive
DocumentRoot
déplacéEn général, la directive /
" du serveur web. Mais souvent, les données qui s'y
trouvent ne sont pas de la première priorité. Par exemple, il peut être
intéressant, pour les visiteurs qui entrent sur le site pour la première
fois, d'être redirigés vers un sous-répertoire particulier
/a-propos-de/
. Pour ce faire, on peut utiliser le jeu de
règles suivant :
On redirige l'URL /
vers
/a-propos-de/
:
RewriteEngine on RewriteRule ^/$ /a-propos-de/ [R]
Notez que le même effet peut être obtenu à l'aide de la directive
Notez aussi que cet exemple ne réécrit que l'URL racine. En d'autres
termes, il réécrit une requête pour http://example.com/
,
mais ne réécrira pas une requête pour
http://example.com/page.html
. En fait, si vous avez modifié
la racine de vos documents - c'est à dire si tous vos contenus se
trouvent dans ce sous-répertoire, il vaut mieux simplement modifier
votre directive
La plupart des problèmes de "slash de fin" peuvent être résolus grâce aux techniques décrites dans ce sujet de la FAQ. Cependant, dans certaines situations où l'absence de slash de fin peut rendre une URL inopérante, l'utilisation de mod_rewrite s'avère nécessaire. Le cas peut se présenter, par exemple, après une série complexe de règles de réécriture.
La solution à ce problème subtil consiste à laisser le
serveur ajouter le slash de fin automatiquement. Pour y
parvenir, il faut utiliser une redirection externe, afin que
le navigateur demande correctement les images sous-jacentes,
etc... Une réécriture en interne ne fonctionnerait que pour la
page du répertoire, mais échouerait pour toute image incluse
dans cette page via des liens relatifs, car le navigateur
demanderait un objet inséré. Par exemple, une requête pour
image.gif
dans /~quux/foo/index.html
deviendrait /~quux/image.gif
sans la redirection
externe !
Pour y parvenir, on peut utiliser des règles de ce style :
RewriteEngine on RewriteBase /~quux/ RewriteRule ^foo$ foo/ [R]
Vous pouvez aussi ajouter ce qui suit dans un fichier
.htaccess
situé dans le répertoire contenant la
ressource. Notez cependant que cela augmente la charge du processeur.
RewriteEngine on RewriteBase /~quux/ RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^(.+[^/])$ $1/ [R]
De nombreux webmasters ont demandé comment résoudre le problème suivant : ils voudraient tout simplement rediriger les répertoires home d'un serveur web vers un autre serveur web. Cette situation se présente en général lorsqu'on installe un nouveau serveur web destiné à terme à en remplacer un autre plus ancien.
Avec /~user/chemin
vers
http://nouveau-serveur/~user/chemin
.
RewriteEngine on RewriteRule ^/~(.+) http://nouveau-serveur/~$1 [R,L]
Le serveur web doit parfois rechercher des pages dans plus d'un répertoire. Dans ce cas, les vues multiples ou autres techniques similaires ne sont d'aucun secours.
On définit explicitement un jeu de règles qui recherche les fichiers dans les répertoires.
RewriteEngine on # on cherche tout d'abord dans dir1/... # ... et si on trouve, on est content et on arrête : RewriteCond %{DOCUMENT_ROOT}/dir1/%{REQUEST_URI} -f RewriteRule ^(.+) %{DOCUMENT_ROOT}/dir1/$1 [L] # on cherche ensuite dans dir2/... # ... et si on trouve, on est content et on arrête : RewriteCond %{DOCUMENT_ROOT}/dir2/%{REQUEST_URI} -f RewriteRule ^(.+) %{DOCUMENT_ROOT}/dir2/$1 [L] # sinon, on continue la recherche avec d'autres directives Alias # ou ScriptAlias, etc... RewriteRule ^(.+) - [PT]
Comment conserver des informations d'état d'une requête à l'autre et utiliser l'URL pour les encoder, sans utiliser d'encapsulateur CGI pour toutes les pages pour seulement supprimer ces informations.
On utilise une règle de réécriture pour supprimer
l'information d'état et l'enregistrer dans une variable
d'environnement dont on pourra plus tard extraire la valeur
dans XSSI ou CGI. De cette façon, une URL telle que
/foo/S=java/bar/
sera traduite en
/foo/bar/
et la variable d'environnement
STATUS
aura pour valeur "java".
RewriteEngine on RewriteRule ^(.*)/S=([^/]+)/(.*) $1/$3 [E=STATUS:$2]
Supposons que vous vouliez atteindre la page d'accueil des
utilisateurs sur une même machine au moyen de l'URL
www.nom-utilisateur.hôte.domaine.com
,
en vous basant
seulement sur les enregistrements DNS de type A, et ceci sans qu'aucun
hôte virtuel ne soit installé sur cette machine.
Dans le cas des requêtes HTTP/1.0, il n'y a pas de solution
; par contre, avec une requête HTTP/1.1 qui contient un
en-tête HTTP Host:, on peut utiliser le jeu de règles suivant
pour réécrire en interne
http://www.nom-utilisateur.hôte.com/chemin
vers
/home/nom-utilisateur/chemin
:
RewriteEngine on RewriteCond %{HTTP_HOST} ^www\.([^.]+)\.host\.com$ RewriteRule ^(.*) /home/%1$1
Les parenthèses utilisées dans une directive %1
, %2
, etc..., alors que
les parenthèses utilisées dans une directive $1
, $2
, etc...
On veut rediriger les URLs des répertoires d'accueil vers
un autre serveur www.quelque-part.com
lorsque
l'utilisateur demandeur n'appartient pas au domaine local
notre-domaine.com
. On rencontre parfois cette
situation dans un contexte d'hôtes virtuels.
Juste une condition de réécriture :
RewriteEngine on RewriteCond %{REMOTE_HOST} !^.+\.notre-domaine\.com$ RewriteRule ^(/~.+) http://www.quelque-part.com/$1 [R,L]
Par défaut, la redirection vers un ancrage HTML ne fonctionne
pas, car mod_rewrite échappe le caractère #
en le
transformant en %23
, ce qui rend la redirection
inopérante.
On utilise le drapeau [NE]
dans la règle
RewriteRule
. NE signifie "No Escape".
Lorsqu'il s'agit de distribuer des contenus dont la nature
dépend de l'heure, de nombreux webmasters utilisent encore des
scripts CGI qui redirigent par exemple vers des pages
spécifiques. Comment peut-on y parvenir à tenir compte de
l'heure à l'aide de
Il existe de nombreuses variables nommées
TIME_xxx
utilisables dans les conditions de
réécriture. Utilisées en conjonction avec les modèles de
comparaison lexicographique spéciaux <STRING
,
>STRING
et =STRING
, elles
permettent d'effectuer des redirections dépendant de
l'heure :
RewriteEngine on RewriteCond %{TIME_HOUR}%{TIME_MIN} >0700 RewriteCond %{TIME_HOUR}%{TIME_MIN} <1900 RewriteRule ^foo\.html$ foo.jour.html RewriteRule ^foo\.html$ foo.nuit.html
Avec cet exemple, l'URL foo.html
renvoie
le contenu de foo.jour.html
durant le
créneau horaire 07:00-19:00
, et le contenu de
foo.nuit.html
le reste du temps. Agréable
fonctionnalité pour une page d'accueil...
Comment conférer une compatibilité ascendante aux URLs
(existant encore virtuellement) après avoir migré
document.YYYY
vers document.XXXX
,
c'est à dire après avoir par exemple traduit un lot de
fichiers .html
en fichiers .phtml
?
On réécrit simplement le nom du fichier en son nom de base et vérifie s'il existe aussi avec la nouvelle extension. Si c'est le cas, on utilise ce nom, sinon on réécrit l'URL sous sa forme originale.
# jeu de règles assurant une compatibilité ascendante en réécrivant # document.html en document.phtml si et seulement si document.phtml # existe et document.html n'existe plus RewriteEngine on RewriteBase /~quux/ # réécriture du fichier en son nom de base, # mais garde en mémoire le fait qu'il s'agit # d'un fichier html RewriteRule ^(.*)\.html$ $1 [C,E=WasHTML:yes] # réécrit vers document.phtml s'il existe # Note : il s'agit d'un exemple de niveau répertoire, si bien que # %{REQUEST_FILENAME} contient le chemin complet du système de fichier # tel qu'il a été construit par le serveur. RewriteCond %{REQUEST_FILENAME}.phtml -f RewriteRule ^(.*)$ $1.phtml [S=1] # sinon, restauration du nom de fichier complet original RewriteCond %{ENV:WasHTML} ^yes$ RewriteRule ^(.*)$ $1.html
Supposons que nous ayons récemment renommé la page
foo.html
en bar.html
, 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.
On réécrit l'ancienne URL en interne vers la nouvelle via la règle suivante :
RewriteEngine on RewriteBase /~quux/ RewriteRule ^foo\.html$ bar.html
Supposons toujours que nous ayons récemment renommé la page
foo.html
en bar.html
, et voulions
maintenant que l'ancienne URL soit toujours valide à des fins
de compatibilité ascendante. Par contre, nous voulons cette
fois que les utilisateurs de l'ancienne URL soient redirigés
vers la nouvelle, c'est à dire que l'adresse tapée
dans leur navigateur doit aussi être modifiée.
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 :
RewriteEngine on RewriteBase /~quux/ RewriteRule ^foo\.html$ bar.html [R]
Comment transformer une page statique foo.html
en sa variante dynamique foo.cgi
de manière
transparente, c'est à dire sans en avertir le
navigateur/utilisateur.
On réécrit simplement l'URL en script CGI et force le
gestionnaire de contenu à cgi-script de façon
à ce que le script s'exécute en tant que programme CGI.
Ainsi, une requête vers /~quux/foo.html
conduit
en interne à l'invocation de
/~quux/foo.cgi
.
RewriteEngine on RewriteBase /~quux/ RewriteRule ^foo\.html$ foo.cgi [H=cgi-script]
Comment empêcher un robot vraiment gênant de collecter les
pages d'une partie spécifique du site web ? Un fichier
/robots.txt
comportant les entrées du "Protocole
d'Exclusion des Robots" ne suffit généralement pas à en venir
à bout.
On utilise un jeu de règles qui interdit les URLs de la
partie du site web concernée /~quux/foo/arc/
(peut-être une partie du serveur avec une arborescence très
développée à travers laquelle le parcours du
robot induirait une charge importante pour le serveur). Nous
devons nous assurer de n'interdire l'accès qu'à ce robot
particulier, c'est à dire qu'il ne suffit pas d'interdire
l'accès à l'hôte sur lequel le robot fonctionne, ce qui
bloquerait aussi les utilisateurs de cet hôte. Pour y
parvenir, on tient aussi compte des informations contenues
dans l'en-tête HTTP User-Agent.
RewriteCond %{HTTP_USER_AGENT} ^NameOfBadRobot.* RewriteCond %{REMOTE_ADDR} ^123\.45\.67\.[8-9]$ RewriteRule ^/~quux/foo/arc/.+ - [F]
Cette technique vous permet d'interdire à d'autres sites d'inclure directement vos images dans leurs pages. On fait souvent référence à cette pratique sous le nom de référencement à chaud (Hotlinking) qui entraîne l'utilisation de votre bande passante pour servir des contenus faisant partie du site de quelqu'un d'autre.
Cette technique repose sur la valeur de la variable
optionnelle HTTP_REFERER
. Certaines personnes
pourront donc contourner cette limitation. Pour la plupart des
utilisateurs cependant, la requête échouera, en ce sens que
l'image ne sera pas affichée depuis le site tiers.
Il y a plusieurs manières de gérer cette situation.
Dans le premier exemple, nous rejetons tout simplement la
requête si elle ne provenait pas d'une page appartenant à notre
site. Pour les besoins de cet exemple, nous supposons que le nom
de votre site est www.example.com
.
RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !www.example.com [NC] RewriteRule \.(gif|jpg|png)$ - [F,NC]
Dans le second exemple, plutôt que de rejeter la requête, nous affichons une autre image à la place.
RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !www.example.com [NC] RewriteRule \.(gif|jpg|png)$ /images/go-away.png [R,NC]
Dans le troisième exemple, nous redirigeons la requête vers une image appartenant à un site tiers.
RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !www.example.com [NC] RewriteRule \.(gif|jpg|png)$ http://other.site.com/image.gif [R,NC]
De tous ces exemples, les deux derniers semblent les plus efficaces pour faire en sorte que les gens arrêtent de référencer vos images à chaud, car il ne verront pas les images qu'ils s'attendent à voir.
Comment interdire l'utilisation du mandataire d'Apache à un certain hôte, ou même à un utilisateur d'un certain hôte ?
Nous devons tout d'abord nous assurer que
RewriteCond %{REMOTE_HOST} ^mauvais-hôte\.mon-domaine\.com$ RewriteRule !^http://[^/.]\.mon-domaine.com.* - [F]
...et celle-ci pour une interdiction concernant un utilisateur d'un certain hôte :
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} ^mauvais-sujet@mauvais-hôte\.mon-domaine\.com$ RewriteRule !^http://[^/.]\.mon-domaine.com.* - [F]
Une question de la Faq : comment résoudre le problème
FOO/BAR/QUUX/etc. ?
Utiliser une STDIN
, et restituer l'URL
résultante (en général réécrite) sur STDOUT
(dans
cet ordre !).
RewriteEngine on RewriteMap quux-table prg:/chemin/vers/table.quux.pl RewriteRule ^/~quux/(.*)$ /~quux/${quux-table:$1}
#!/chemin/vers/perl # désactive la mise en tampon des entrées/sorties, qui risque # de provoquer des bouclages infinis pour le serveur Apache $| = 1; # lit les URLs (une par ligne) depuis stdin et # génère l'URL transformée sur stdout # read URLs one per line from stdin and # generate substitution URL on stdout while (<>) { s|^foo/|bar/|; print $_; }
Ceci n'est qu'un exemple de démonstration qui ne fait que
réécrire les URLs du style /~quux/foo/...
vers
/~quux/bar/...
. En fait, vous pouvez programmer
la substitution que vous voulez. Notez cependant que si de
tels programmes peuvent aussi être utilisés
par un utilisateur standard, seul l'administrateur du système
peut les écrire.