Comment fonctionne RewriteBase dans .htaccess

227

Je l'ai vu dans quelques .htaccessexemples

RewriteBase /

Il semble être quelque peu similaire en termes de fonctionnalités à celui <base href="">de HTML.

Je pense qu'il peut ajouter automatiquement sa valeur au début de RewriteRule déclarations (éventuellement celles sans barre oblique)?

Je ne pouvais pas le faire fonctionner correctement. Je pense que son utilisation pourrait être très utile pour la portabilité du site, car j'ai souvent un serveur de développement différent de celui de production. Ma méthode actuelle me laisse supprimer des parties de monRewriteRule relevés.

Quelqu'un peut-il m'expliquer brièvement comment le mettre en œuvre?

Merci

alex
la source
RewriteBase ne fonctionne que dans le répertoire ou le contexte .htaccess ... reportez-vous au contexte pour le lien @SalmanPK fourni.
Eddie B
1
Voir cette réponse pour une bonne description. stackoverflow.com/a/2137593/292060
goodeye
1
Ceci est une réponse plus approfondie: stackoverflow.com/a/21348047/632951
Pacerier
Ceci est une réponse en 1 ligne: stackoverflow.com/a/46541685/632951
Pacerier

Réponses:

102

Dans mes propres mots, après avoir lu les documents et expérimenté:

Vous pouvez utiliser RewriteBasepour fournir une base pour vos réécritures. Considère ceci

# invoke rewrite engine
    RewriteEngine On
    RewriteBase /~new/

# add trailing slash if missing
    rewriteRule ^(([a-z0-9\-]+/)*[a-z0-9\-]+)$ $1/ [NC,R=301,L]

C'est une vraie règle que j'ai utilisée pour m'assurer que les URL ont une barre oblique de fin. Cela convertira

http://www.example.com/~new/page

à

http://www.example.com/~new/page/

En ayant RewriteBaselà, vous faites sortir le chemin relatif du RewriteBaseparamètre.

alex
la source
10
«Se détacher du paramètre RewriteBase» - vouliez-vous dire le paramètre rewriteRule? :)
Kissaki
1
Je veux clarifier certains détails sur htaccess .. est-ce qu'un ReWriteBase le définit pour toutes les règles dans htaccess après quoi sa déclaration? existe-t-il un moyen de le désactiver, peut-il être réinitialisé?
Damon
3
@Kissaki: Non, le $1correspond au modèle RewriteRule entre parenthèses, mais le chemin relatif pour la substitution se détache du paramètre RewriteBase. Ainsi, la substitution résultante est /~new/$1/.
MrWhite
3
@Damon: Voir cette question concernant plusieurs RewriteBasedirectives. En bref, vous ne pouvez pas en avoir plus d'un - je pense que la dernière RewriteBase directive l'emporte et affecte tout le fichier .htaccess.
MrWhite
24
-1; cette réponse semble avoir aidé les autres, mais elle est totalement opaque pour moi. J'aurais pu deviner que "vous pouvez utiliser RewriteBasepour fournir une base pour vos réécritures" - c'est à peu près juste un réarrangement des mots - mais je n'ai aucune idée de ce qu'une "base" est dans ce contexte, ni comment le sens de la l'exemple que vous avez donné serait différent si la RewriteBaseligne était supprimée. Je vais au manuel ...
Mark Amery
89

RewriteBasen'est appliqué qu'à la cible d'une règle de réécriture relative .

  • Utiliser RewriteBase comme ceci ...

    RewriteBase /folder/
    RewriteRule a\.html b.html
    
  • est essentiellement le même que ...

    RewriteRule a\.html /folder/b.html
    
  • Mais lorsque le fichier .htaccess est à l'intérieur, /folder/cela pointe également vers la même cible:

    RewriteRule a\.html b.html
    

Bien que les documents impliquent toujours d'utiliser un RewriteBase, Apache le détecte généralement correctement pour les chemins sous DocumentRoot, sauf si:

  • Vous utilisez des Aliasdirectives

  • Vous utilisez des règles de réécriture .htaccess pour effectuer des redirections HTTP (plutôt qu'une réécriture silencieuse) vers des URL relatives

Dans ces cas, vous pouvez constater que vous devez spécifier la RewriteBase.

Cependant, comme il s'agit d'une directive déroutante, il est généralement préférable de simplement spécifier des URI absolus (aka 'root relative') dans vos cibles de réécriture. Les autres développeurs lisant vos règles les comprendront plus facilement.



Citant ici l'excellente réponse détaillée de Jon Lin :

Dans un fichier htaccess, mod_rewrite fonctionne comme un <Directory> ou<Location> conteneur. et le RewriteBaseest utilisé pour fournir une base de chemin relatif.

Par exemple, supposons que vous ayez cette structure de dossiers:

DocumentRoot
|-- subdir1
`-- subdir2
    `-- subsubdir

Vous pouvez donc accéder à:

  • http://example.com/ (racine)
  • http://example.com/subdir1 (subdir1)
  • http://example.com/subdir2 (subdir2)
  • http://example.com/subdir2/subsubdir (subsubdir)

L'URI qui est envoyé via un RewriteRuleest relatif au répertoire contenant le fichier htaccess. Donc si vous avez:

RewriteRule ^(.*)$ - 
  • Dans le htaccess racine, et la demande est /a/b/c/d, puis l'URI capturé ($1 ) est a/b/c/d.
  • Si la règle est en place subdir2et que la demande est/subdir2/e/f/g l'URI capturé l'est e/f/g.
  • Si la règle se trouve dans le subsubdir, et que la demande l'est /subdir2/subsubdir/x/y/z, l'URI capturé l'est x/y/z.

Le répertoire dans lequel se trouve la règle a cette partie supprimée de l'URI. La base de réécriture n'a aucun effet sur cela, c'est simplement comment fonctionne le répertoire.

Qu'est - ce que la base de réécriture ne fait, est de fournir une base chemin URL ( pas pour tous les chemins relatifs à la base-chemin du fichier) cible de règle . Alors disons que vous avez cette règle:

RewriteRule ^foo$ bar.php [L]

Le bar.phpest un chemin relatif, par opposition à:

RewriteRule ^foo$ /bar.php [L]

où le /bar.phpest un chemin absolu. Le chemin absolu sera toujours la "racine" (dans la structure de répertoires ci-dessus). Cela signifie que, indépendamment du fait que la règle se trouve dans la "racine", "subdir1", "subsubdir", etc., le /bar.phpchemin correspond toujours àhttp://example.com/bar.php .

Mais l'autre règle, avec le chemin relatif, elle 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 se trouve dans le répertoire "subdir1" et que vous y accédez http://example.com/subdir1/foo, vous êtes servi http://example.com/subdir1/bar.php. etc. Cela fonctionne parfois et parfois non, comme le dit la documentation, il est censé être requis pour les chemins relatifs, mais la plupart du temps cela semble fonctionner. Sauf lorsque vous redirigez (en utilisant l' Rindicateur, ou implicitement parce que vous avez http://hostdans la cible de votre règle). Cela signifie que cette règle:

RewriteRule ^foo$ bar.php [L,R]

s'il se trouve dans le répertoire "subdir2" et que vous y accédez http://example.com/subdir2/foo, mod_rewrite confondra le chemin d'accès relatif avec un chemin de fichier au lieu d'un chemin d'URL et à cause de l' Rindicateur, vous finirez par être 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à RewriteBasequ'intervient. La directive indique à mod_rewrite quoi ajouter au début de chaque chemin relatif. Donc si j'ai:

RewriteBase /blah/
RewriteRule ^foo$ bar.php [L]

dans "subsubdir", aller à http://example.com/subdir2/subsubdir/foo vraiment me servir http://example.com/blah/bar.php. Le "bar.php" est ajouté à la fin de la base. Dans la pratique, cet exemple n'est généralement pas ce que vous voulez, car vous ne pouvez pas avoir plusieurs bases dans le même conteneur de répertoire ou 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 ne devez changer la base qu'au lieu d'un tas 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]
...

de telle sorte que va http://example.com/subdir1/fooservir http://example.com/subdir1/bar.phpetc. Et disons 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/en /subdir2/subsubdir/, vous auriez pu simplement 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 puis, lorsque vous avez dû déplacer ces fichiers et les règles vers un autre répertoire, changez simplement la base:

RewriteBase /subdir2/subsubdir/

et c'est tout.

Simon East
la source
Pour moi, j'ai raté RewriteEngine On. Pas besoin sur 1and1 par exemple mais c'est obligatoire sur mon serveur dédié.
Portekoi
41

AFAIK, RewriteBase est uniquement utilisé pour corriger les cas où mod_rewrite s'exécute dans un .htaccessfichier ne se trouvant pas à la racine d'un site et il devine le mauvais chemin Web (par opposition au chemin du système de fichiers) pour le dossier dans lequel il s'exécute. Donc, si vous avez un RewriteRule dans un .htaccess dans un dossier qui http://example.com/myfoldervous correspond peut utiliser:

RewriteBase myfolder

Si mod_rewrite ne fonctionne pas correctement.

Essayer de l'utiliser pour réaliser quelque chose d'inhabituel, plutôt que de résoudre ce problème, ressemble à une recette pour devenir très confus.

rjmunro
la source
2
Doit-il se terminer par une barre oblique finale?
Pacerier
@self, non testé et sous-expliqué ici: stackoverflow.com/a/11443194/632951
Pacerier
23

RewriteBase n'est utile que dans les situations où vous ne pouvez mettre qu'un .htaccess à la racine de votre site. Sinon, vous feriez mieux de placer vos différents fichiers .htaccess dans différents répertoires de votre site et d'omettre complètement la directive RewriteBase.

Dernièrement, pour les sites complexes, je les ai supprimés, car cela complique le déploiement de fichiers de test pour vivre.

Thomas Hunter II
la source
22
Bien que ce soit un bon conseil, ce n'est pas du tout une réponse à la question. Cela aurait donc dû être un commentaire à la question, ne pas avoir reçu (autant) de votes positifs et certainement pas accepté comme «réponse».
Kissaki
3
"mieux vaut placer vos différents fichiers .htaccess dans différents répertoires" - Je ne suis pas sûr que ce soit un bon conseil? Le fait d'avoir des fichiers .htaccess parsemés sur tout votre site peut faire du débogage / maintenance un cauchemar. J'aurais dit qu'il était préférable d'avoir un fichier .htaccess à la racine de votre site.
MrWhite
1
@ w3d Il y a aussi une question de timing: à chaque accès à un sous-répertoire, plusieurs fichiers .htaccess sont analysés (de la racine au sous-répertoire actuel). Avoir beaucoup de fichiers pourrait réduire la vitesse de la réponse globale à la demande, par opposition à un seul fichier à la racine, même s'il contient beaucoup de règles.
Erenor Paz
19

Quand je développe, c'est sur un domaine différent dans un dossier. Lorsque je mets un site en ligne, ce dossier n'existe plus. L'utilisation de RewriteBase me permet d'utiliser le même fichier .htaccess dans les deux environnements.

En direct:

RewriteBase /
# RewriteBase /dev_folder/

Lors du développement:

# RewriteBase /
RewriteBase /dev_folder/
user1669830
la source
4
Je suis sûr que cela ne fonctionnera pas toujours. Et si vous utilisiez %{REQUEST_URI}une RewriteConddirective par exemple?
MrWhite
1
@ user1669830, Si vous n'avez qu'une seule réécriture, vous auriez pu ajouter la base à la réécriture stackoverflow.com/a/46541685/632951
Pacerier
18

L'explication la plus claire que j'ai trouvée n'était pas dans la documentation actuelle d'Apache 2.4, mais dans la version 2.0 .

#  /abc/def/.htaccess -- per-dir config file for directory /abc/def
#  Remember: /abc/def is the physical path of /xyz, i.e., the server
#            has a 'Alias /xyz /abc/def' directive e.g.

RewriteEngine On

#  let the server know that we were reached via /xyz and not
#  via the physical path prefix /abc/def
RewriteBase   /xyz

Comment ça marche? Pour vous les hackers apache, ce document 2.0 continue de donner "des informations détaillées sur les étapes de traitement internes".

Leçon apprise: Bien que nous ayons besoin de nous familiariser avec le "courant", des gemmes peuvent être trouvées dans les annales.

DWB
la source
3

Cette commande peut définir explicitement l'URL de base pour vos réécritures. Si vous souhaitez commencer à la racine de votre domaine, vous devez inclure la ligne suivante avant votre RewriteRule:

RewriteBase /
Sandeep Goyal
la source
2

Je pense que cet extrait de la documentation Apache complète bien les réponses précédentes:

Cette directive est requise lorsque vous utilisez un chemin relatif dans une substitution dans un contexte par répertoire (htaccess), sauf si l'une des conditions suivantes est remplie:

  • La demande d'origine et la substitution se trouvent sous DocumentRoot (par opposition à accessibles par d'autres moyens, tels que Alias).

  • Le chemin du système de fichiers vers le répertoire contenant la RewriteRule, suffixé par la substitution relative, est également valide comme chemin d'URL sur le serveur (c'est rare).

Comme mentionné précédemment, dans d'autres contextes, il est seulement utile de raccourcir votre règle. De plus, comme mentionné précédemment, vous pouvez obtenir la même chose en plaçant le fichier htaccess dans le sous-répertoire.

alex
la source