J'essaie d'apprendre quelques .htaccess
des trucs. Je suis tombé sur la directive RewriteBase
mais je n’ai pas réussi à la faire fonctionner correctement.
Je me demande ce que cette directive fait spécifiquement et comment l'utiliser. Il y a eu des discussions sur RewriteBase
dans StackOverflow et dans la documentation Apache, mais je ne pouvais toujours pas obtenir une réponse claire à ma question.
Quelqu'un pourrait-il me montrer un exemple simple mais efficace où RewriteBase
peut être utilisé?
Dans un fichier htaccess, mod_rewrite fonctionne de la même manière qu'un <Directory>
ou <Location>
récipient. et le RewriteBase
est utilisé pour fournir une base de chemin relatif.
Par exemple, supposons que vous ayez cette structure de dossiers:
root
|-- subdir1
|-- subdir2
|-- subsubdir
Pour que vous puissiez accéder à:
http://example.com/
(racine)http://example.com/subdir1
(subdir1)http://example.com/subdir2
(subdir2)http://example.com/subdir2/subsubdir
(sous-répertoire)L'URI envoyé via RewriteRule
est relatif au répertoire. Donc si vous avez:
RewriteRule ^(.*)$ -
dans la racine, et la requête est /a/b/c/d
, puis l'URI capturé ($1
) est a/b/c/d
. Mais si la règle est en subdir2
et la demande est /subdir2/e/f/g
alors l'URI capturé est e/f/g
. Et si la règle est dans le subsubdir
et que la requête est /subdir2/subsubdir/x/y/z
, l'URI capturé est x/y/z
. Le répertoire dans lequel se trouve la règle a cette partie enlevée de l'URI. La base de réécriture n’a pas d’effet sur ceci, c’est simplement comment fonctionne chaque répertoire.
Ce que fait la base de réécriture , est de fournir une base de chemin d’URL ( non une base de chemin de fichier) pour tous les chemins relatifs dans la cible de la règle. Alors dites que vous avez cette règle:
RewriteRule ^foo$ bar.php [L]
Le bar.php
est un chemin relatif, par opposition à:
RewriteRule ^foo$ /bar.php [L]
où le /bar.php
est un chemin absolu. Le chemin absolu sera toujours la "racine" (dans la structure de répertoires ci-dessus). Cela signifie que si la règle est dans la "racine", "subdir1", "subsubdir", etc. Le /bar.php
chemin correspond toujours à http://example.com/bar.php
.
Mais l’autre règle, avec le chemin relatif, est basée sur le répertoire dans lequel se trouve la règle. Donc, si
RewriteRule ^foo$ bar.php [L]
est dans la "racine" et vous allez à http://example.com/foo
, vous êtes servi http://example.com/bar.php
. Mais si cette règle est dans le répertoire "subdir1", et que vous passez à http://example.com/subdir1/foo
, vous êtes servi http://example.com/subdir1/bar.php
. etc. Cela fonctionne parfois et ne fonctionne parfois pas, comme le dit la documentation, il est supposé être requis pour les chemins relatifs, mais la plupart du temps, cela semble travailler. Sauf lorsque vous redirigez (en utilisant le drapeau R
ou implicitement parce que vous avez http://Host
dans la cible de votre règle). Cela signifie que cette règle:
RewriteRule ^foo$ bar.php [L,R]
si c'est dans le répertoire "subdir2", et que vous allez à http://example.com/subdir2/foo
, mod_rewrite confondra le chemin relatif avec un chemin de fichier plutôt qu’un chemin d’URL et à cause du drapeau R
, vous serez redirigé vers quelque chose comme: http://example.com/var/www/localhost/htdocs/subdir1
. Ce qui n'est évidemment pas ce que vous voulez.
C'est là que RewriteBase
entre. La directive indique à mod_rewrite ce qu'il faut ajouter au début de chaque chemin relatif. Donc si j'ai:
RewriteBase /blah/
RewriteRule ^foo$ bar.php [L]
et cette règle est dans "subsubdir", va à http://example.com/subdir2/subsubdir/foo
me servira réellement http://example.com/blah/bar.php
. Le "bar.php" est ajouté à la fin de la base. En pratique, cet exemple ne correspond généralement pas à ce que vous souhaitez, car vous ne pouvez pas avoir plusieurs bases dans le même conteneur de répertoire ou le même fichier htaccess.
Dans la plupart des cas, il est utilisé comme ceci:
RewriteBase /subdir1/
RewriteRule ^foo$ bar.php [L]
où ces règles seraient dans le répertoire "subdir1" et
RewriteBase /subdir2/subsubdir/
RewriteRule ^foo$ bar.php [L]
serait dans le répertoire "subsubdir".
Cela vous permet en partie de rendre vos règles portables, vous pouvez donc les déposer dans n’importe quel répertoire et n’avoir besoin que de changer la base au lieu d’un ensemble de règles. Par exemple si vous aviez:
RewriteEngine On
RewriteRule ^foo$ /subdir1/bar.php [L]
RewriteRule ^blah1$ /subdir1/blah.php?id=1 [L]
RewriteRule ^blah2$ /subdir1/blah2.php [L]
...
tel que aller à http://example.com/subdir1/foo
servira http://example.com/subdir1/bar.php
etc. Et dites que vous avez décidé de déplacer tous ces fichiers et règles dans le répertoire "subsubdir". Au lieu de changer chaque instance de /subdir1/
à /subdir2/subsubdir/
, vous auriez pu avoir une base:
RewriteEngine On
RewriteBase /subdir1/
RewriteRule ^foo$ bar.php [L]
RewriteRule ^blah1$ blah.php?id=1 [L]
RewriteRule ^blah2$ blah2.php [L]
...
Et ensuite, lorsque vous aviez besoin de déplacer ces fichiers et les règles dans un autre répertoire, changez simplement la base:
RewriteBase /subdir2/subsubdir/
et c'est tout.
RewriteBase
vous permet d'ajuster le chemin que mod_rewrite
préfixe automatiquement le résultat d'un RewriteRule
. Une réécriture dans le contexte de .htaccess est effectuée par rapport au répertoire contenant ce fichier .htaccess. Le résultat immédiat de RewriteRule est toujours relatif au répertoire contenant le fichier .htaccess, mais mod_rewrite ajuste ensuite ce résultat pour le rendre relatif à la racine du document. RewriteBase
vous permet de modifier cette dernière étape, vous permettant ainsi de fournir un chemin arbitraire de base qui est ajouté au début du résultat immédiat de RewriteRule , au lieu de la racine du document.
Pour moi, le point clé pour comprendre la directive RewriteBase
était quand je me suis rendu compte que mod_rewrite appliquait RewriteBase
aux résultats du RewriteRules
, pas à leurs arguments.
Le traitement normal d'un RewriteRule
dans le contexte d'un fichier .htaccess se présente comme suit:
/doc_root/one/.htaccess
, alors le chemin généré sera /two/three
.Ce processus aboutit à un chemin récrit relatif à la racine du document.
Quand il y a une directive RewriteBase
, les étapes 1,2 et 3 restent les mêmes, seule l'étape 4 change. Au lieu de la racine du document, le chemin du système de fichiers du répertoire contenant le fichier .htaccess est supprimé. Ensuite, le RewriteBase
est ajouté.
Exemple:
https://example.com/one/two/three/file.txt
/var/doc_root
/var/doc_root/one/.htaccess
/var/other_location/
Sans le RewriteBase dans le fichier htaccess, cela est traité comme suit:
/two/three/file.txt
/four/rewritten.txt
/var/do_root/one/four/rewritten.txt
one/four/rewritten.txt
Avec RewriteBase dans le fichier .htaccess, cela est traité comme suit:
/two/three/file.txt
/four/rewritten.txt
/var/other_location/four/rewritten.txt