web-dev-qa-db-fra.com

Que fait RewriteBase et comment l’utiliser?

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é?

47
Chong Lip Phang

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.

92
Jon Lin

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:

  1. Générez un chemin demandé relatif au répertoire contenant le fichier .htaccess. Si, par exemple, l'URI est https://www.example.com/one/two/three et que le fichier .htaccess a le chemin /doc_root/one/.htaccess, alors le chemin généré sera /two/three.
  2. Les RewriteRules réécrivent ensuite le chemin relatif d’en haut.
  3. Préfixez le chemin réécrit résultant ci-dessus avec le chemin d'accès complet du système de fichiers au fichier .htaccess
  4. Supprimez le chemin d'accès à la racine du document à partir du début du chemin réécrit ci-dessus.

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:

  • Demande - https://example.com/one/two/three/file.txt
  • Document root - /var/doc_root
  • Emplacement de htaccess - /var/doc_root/one/.htaccess
  • RewriteBase - /var/other_location/

Sans le RewriteBase dans le fichier htaccess, cela est traité comme suit:

  1. Obtenir une portion du chemin demandé par rapport à htaccess - /two/three/file.txt
  2. Est-ce que la réécriture - /four/rewritten.txt
  3. Ajoutez le chemin d'accès au fichier .htaccess - /var/do_root/one/four/rewritten.txt
  4. Dénudez la racine du document - one/four/rewritten.txt

Avec RewriteBase dans le fichier .htaccess, cela est traité comme suit:

  1. Obtenir une portion du chemin demandé par rapport à htaccess - /two/three/file.txt
  2. Est-ce que la réécriture - /four/rewritten.txt
  3. Ajoutez le RewriteBase - /var/other_location/four/rewritten.txt
1
Dom