¿Cómo funciona RewriteBase en .htaccess?

Lo he visto en algunos ejemplos de .htaccess

 RewriteBase / 

Parece ser algo similar en funcionalidad al de HTML.

Creo que puede anteponer automáticamente su valor al comienzo de RewriteRule instrucciones RewriteRule (posiblemente sin una barra diagonal).

No pude hacer que funcione correctamente. Creo que su uso puede ser muy útil para la portabilidad del sitio, ya que a menudo tengo un servidor de desarrollo que es diferente de uno de producción. Mi método actual me deja borrar partes de mis declaraciones RewriteRule .

¿Alguien puede explicarme brevemente cómo implementarlo?

Gracias

En mis propias palabras, después de leer los documentos y experimentar:

Puede usar RewriteBase para proporcionar una base para sus reescrituras. Considera esto

 # invoke rewrite engine RewriteEngine On RewriteBase /~new/ # add trailing slash if missing rewriteRule ^(([a-z0-9\-]+/)*[a-z0-9\-]+)$ $1/ [NC,R=301,L] 

Esta es una regla real que utilicé para asegurar que las URL tengan una barra inclinada. Esto convertirá

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

a

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

Al tener allí RewriteBase , hace que la ruta relativa salga del parámetro RewriteBase .

RewriteBase solo se aplica al objective de una regla de reescritura relativa .

  • Usando RewriteBase como este …

     RewriteBase /folder/ RewriteRule a\.html b.html 
  • es esencialmente lo mismo que …

     RewriteRule a\.html /folder/b.html 
  • Pero cuando el archivo .htaccess está dentro /folder/ , esto también apunta al mismo objective:

     RewriteRule a\.html b.html 

Aunque los documentos implican siempre el uso de RewriteBase , Apache generalmente lo detecta correctamente para las rutas en DocumentRoot a menos que:

  • Está utilizando directivas Alias

  • Está utilizando las reglas de reescritura de .htaccess para realizar redireccionamientos HTTP (en lugar de solo reescritura silenciosa) a URL relativas

En estos casos, puede encontrar que necesita especificar RewriteBase.

Sin embargo, dado que es una directiva confusa, en general es mejor simplemente especificar los URI absolutos (alias ‘raíz relativa’) en sus objectives de reescritura. Otros desarrolladores que lean tus reglas comprenderán esto más fácilmente.


Citando de la excelente respuesta en profundidad de Jon Lin aquí :

En un archivo htaccess, mod_rewrite funciona de forma similar a un contenedor o . y RewriteBase se usa para proporcionar una base de ruta relativa.

Por ejemplo, supongamos que tienes esta estructura de carpetas:

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

Para que pueda acceder:

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

El URI que se envía a través de RewriteRule es relativo al directorio que contiene el archivo htaccess. Entonces si tienes:

 RewriteRule ^(.*)$ - 
  • En la raíz htaccess, y la solicitud es /a/b/c/d , el URI capturado ( $1 ) es a/b/c/d .
  • Si la regla está en subdir2 y la solicitud es /subdir2/e/f/g entonces el URI capturado es e/f/g .
  • Si la regla está en el subsubdir , y la solicitud es /subdir2/subsubdir/x/y/z , entonces el URI capturado es x/y/z .

El directorio en el que se encuentra la regla tiene esa parte desmantelada del URI. La base de reescritura no tiene ningún efecto sobre esto, esto es simplemente cómo funciona por directorio.

Lo que hace la base de reescritura es proporcionar una base de ruta de URL ( no una base de ruta de archivo) para ninguna ruta relativa en el objective de la regla . Entonces di que tienes esta regla:

 RewriteRule ^foo$ bar.php [L] 

El bar.php es una ruta relativa, a diferencia de:

 RewriteRule ^foo$ /bar.php [L] 

donde /bar.php es una ruta absoluta. La ruta absoluta siempre será la “raíz” (en la estructura de directorios anterior). Eso significa que independientemente de si la regla está en “raíz”, “subdir1”, “subsubdir”, etc., la ruta /bar.php siempre se asigna a http://example.com/bar.php .

Pero la otra regla, con la ruta relativa, se basa en el directorio en el que está la regla. Entonces, si

 RewriteRule ^foo$ bar.php [L] 

está en la “raíz” y vas a http://example.com/foo , te sirven http://example.com/bar.php . Pero si esa regla está en el directorio “subdir1” y va a http://example.com/subdir1/foo , se le servirá http://example.com/subdir1/bar.php . Esto a veces funciona y otras veces no, como dice la documentación, se supone que es necesario para trayectos relativos, pero la mayoría de las veces parece funcionar. Excepto cuando está redirigiendo (usando el indicador R , o implícitamente porque tiene http://host en el objective de su regla). Eso significa esta regla:

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

si está en el directorio “subdir2”, y vas a http://example.com/subdir2/foo , mod_rewrite confundirá la ruta relativa como una ruta de archivo en lugar de una ruta URL y debido a la bandera R , Se redirigirá a algo como: http://example.com/var/www/localhost/htdocs/subdir1 . Lo cual obviamente no es lo que quieres.

Aquí es donde entra RewriteBase . La directiva le dice a mod_rewrite qué agregar al comienzo de cada ruta relativa. Entonces si tengo:

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

en “subsubdir”, ir a http://example.com/subdir2/subsubdir/foo me servirá realmente http://example.com/blah/bar.php . El “bar.php” se agrega al final de la base. En la práctica, este ejemplo generalmente no es lo que desea, porque no puede tener varias bases en el mismo contenedor de directorio o archivo htaccess.

En la mayoría de los casos, se usa así:

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

donde esas reglas estarían en el directorio “subdir1” y

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

estaría en el directorio “subsubdir”.

Esto en parte le permite hacer que sus reglas sean portátiles, para que pueda colocarlas en cualquier directorio y solo necesite cambiar la base en lugar de un conjunto de reglas. Por ejemplo, si tuvieras:

 RewriteEngine On RewriteRule ^foo$ /subdir1/bar.php [L] RewriteRule ^blah1$ /subdir1/blah.php?id=1 [L] RewriteRule ^blah2$ /subdir1/blah2.php [L] ... 

de modo que yendo a http://example.com/subdir1/foo servirá http://example.com/subdir1/bar.php etc. Y digamos que decidió mover todos esos archivos y reglas al directorio “subsubdir” . En lugar de cambiar cada instancia de /subdir1/ a /subdir2/subsubdir/ , podría haber tenido una base:

 RewriteEngine On RewriteBase /subdir1/ RewriteRule ^foo$ bar.php [L] RewriteRule ^blah1$ blah.php?id=1 [L] RewriteRule ^blah2$ blah2.php [L] ... 

Y luego, cuando necesitó mover esos archivos y las reglas a otro directorio, simplemente cambie la base:

 RewriteBase /subdir2/subsubdir/ 

y eso es.

AFAIK, RewriteBase solo se usa para corregir casos donde mod_rewrite se ejecuta en un archivo .htaccess no en la raíz de un sitio y adivina la ruta web incorrecta (en lugar de la ruta del sistema de archivos) para la carpeta en la que se está ejecutando. Entonces, si tener RewriteRule en .htaccess en una carpeta que se asigna a http://example.com/myfolder carpeta que puede usar:

 RewriteBase myfolder 

Si mod_rewrite no funciona correctamente.

Tratar de usarlo para lograr algo inusual, en lugar de solucionar este problema, suena como una receta para confundirse.

RewriteBase solo es útil en situaciones donde solo puedes poner un .htaccess en la raíz de tu sitio. De lo contrario, es mejor que coloque sus diferentes archivos .htaccess en diferentes directorios de su sitio y omita por completo la directiva RewriteBase.

Últimamente, para sitios complejos, los he estado quitando, porque hace que la implementación de archivos de pruebas se convierta en un paso más complicado.

Cuando desarrollo, está en un dominio diferente dentro de una carpeta. Cuando tomo un sitio en vivo, esa carpeta ya no existe. Usar RewriteBase me permite usar el mismo archivo .htaccess en ambos entornos.

Cuando en vivo:

 RewriteBase / # RewriteBase /dev_folder/ 

Al desarrollar:

 # RewriteBase / RewriteBase /dev_folder/ 

La explicación más clara que encontré no estaba en los documentos actuales de 2.4 apache, sino en la versión 2.0 .

 # /abc/def/.htaccess -- per-dir config file for directory /abc/def # Remember: /abc/def is the physical path of /xyz, ie, the server # has a 'Alias /xyz /abc/def' directive eg RewriteEngine On # let the server know that we were reached via /xyz and not # via the physical path prefix /abc/def RewriteBase /xyz 

¿Como funciona? Para los piratas informáticos de Apache, este documento 2.0 continúa proporcionando “información detallada sobre los pasos de procesamiento interno”.

Lección aprendida: Si bien debemos estar familiarizados con las gems “actuales”, podemos encontrarlas en los anales.

Este comando puede establecer explícitamente la URL base para sus reescrituras. Si desea comenzar en la raíz de su dominio, debe incluir la siguiente línea antes de su RewriteRule:

 RewriteBase / 

Creo que este extracto de la documentación de Apache complementa bien las respuestas anteriores:

Esta directiva es necesaria cuando utiliza una ruta relativa en una sustitución en el contexto por directorio (htaccess) a menos que cualquiera de las siguientes condiciones sea verdadera:

  • La solicitud original y la sustitución se encuentran debajo de DocumentRoot (en lugar de accesible por otros medios, como Alias).

  • La ruta del sistema de archivos al directorio que contiene RewriteRule, con el sufijo de la sustitución relativa también es válida como una ruta de URL en el servidor (esto es raro).

Como se mencionó anteriormente, en otros contextos, solo es útil acortar la regla. Además, también como se mencionó anteriormente, puede lograr lo mismo colocando el archivo htaccess en el subdirectorio.