¿Cómo funciona RewriteBase en .htaccess?

227

He visto esto en algunos .htaccessejemplos.

RewriteBase /

Parece ser algo similar en funcionalidad al <base href="">HTML.

¿Creo que puede anteponer automáticamente su valor al comienzo de las RewriteRuledeclaraciones (posiblemente las que no tienen una barra inclinada)?

No pude hacerlo funcionar correctamente. Creo que su uso podría ser muy útil para la portabilidad del sitio, ya que a menudo tengo un servidor de desarrollo que es diferente a uno de producción. Mi método actual me deja eliminar partes de mis RewriteRuledeclaraciones.

¿Alguien puede explicarme brevemente cómo implementarlo?

Gracias

alex
fuente
RewriteBase solo funciona en el directorio o en el contexto .htaccess ... consulte el contexto para el enlace que @SalmanPK proporcionó.
Eddie B
1
Vea esta respuesta para una buena descripción. stackoverflow.com/a/2137593/292060
goodeye
1
Esta es una respuesta más detallada: stackoverflow.com/a/21348047/632951
Pacerier el
Esta es una respuesta de 1 línea: stackoverflow.com/a/46541685/632951
Pacerier el

Respuestas:

102

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

Puede usar RewriteBasepara 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 garantizar que las URL tengan una barra diagonal final. Esto convertirá

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

a

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

Al tener RewriteBaseallí, hace que la ruta relativa salga del RewriteBaseparámetro.

alex
fuente
10
"Salga del parámetro RewriteBase": ¿se refería al parámetro rewriteRule? :)
Kissaki
1
Quiero aclarar algunos detalles sobre htaccess ... ¿ReWriteBase lo establece para todas las reglas en htaccess después de su declaración? ¿Hay alguna manera de desarmarlo? ¿Se puede restablecer?
Damon
3
@Kissaki: No, $1coincide con el patrón RewriteRule entre paréntesis, pero la ruta relativa para la sustitución proviene del parámetro RewriteBase. Entonces, la sustitución resultante es /~new/$1/.
MrWhite
3
@Damon: vea esta pregunta con respecto a las RewriteBasedirectivas múltiples . En resumen, no puede tener más de uno: creo que la última RewriteBase directiva gana y afecta a todo el archivo .htaccess.
MrWhite
24
-1; Esta respuesta parece haber ayudado a otros, pero es totalmente opaca para mí. Podría haber adivinado que "Se puede utilizar RewriteBasepara proporcionar una base para sus reescrituras" - que es prácticamente sólo una reordenación de las palabras - pero no tengo ni idea de lo que es una "base" es en este contexto, ni cómo el significado de la El ejemplo que ha dado sería diferente si RewriteBasese eliminara la línea. Fuera del manual voy ...
Mark Amery
89

RewriteBasesolo se aplica al objetivo 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 objetivo:

    RewriteRule a\.html b.html
    

Aunque los documentos implican siempre usar un RewriteBase, Apache generalmente lo detecta correctamente para las rutas bajo DocumentRoot a menos que:

  • Estás usando Aliasdirectivas

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

En estos casos, puede encontrar que necesita especificar RewriteBase.

Sin embargo, dado que es una directiva confusa, generalmente es mejor simplemente especificar URI absolutos (también conocidos como 'raíz relativa') en sus objetivos de reescritura. Otros desarrolladores que lean sus reglas las comprenderán más fácilmente.



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

En un archivo .htaccess, mod_rewrite funciona de forma similar a una <Directory>o <Location>contenedor. y RewriteBasese usa para proporcionar una base de ruta relativa.

Por ejemplo, supongamos que tiene esta estructura de carpetas:

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

Para que pueda acceder a:

  • http://example.com/ (raíz)
  • 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 un RewriteRulees 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, entonces el URI capturado ( $1) es a/b/c/d.
  • Si la regla está dentro subdir2y la solicitud es /subdir2/e/f/gentonces, el URI capturado es e/f/g.
  • Si la regla está en subsubdir, y la solicitud está /subdir2/subsubdir/x/y/z, entonces el URI capturado está x/y/z.

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

Lo que la base de reescritura no lo hacen, es proporcionar una base URL-path ( no una base file-path) de las rutas relativas en el objetivo de la regla . Digamos que tienes esta regla:

RewriteRule ^foo$ bar.php [L]

El bar.phpes un camino relativo, en oposición a:

RewriteRule ^foo$ /bar.php [L]

donde el /bar.phpes un camino absoluto. La ruta absoluta siempre será la "raíz" (en la estructura de directorios anterior). Eso significa que independientemente de si la regla está en la "raíz", "subdir1", "subsubdir", etc., la /bar.phpruta siempre se asigna http://example.com/bar.php.

Pero la otra regla, con la ruta relativa, se basa en el directorio en el que se encuentra 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 usted va http://example.com/subdir1/foo, se le servirá http://example.com/subdir1/bar.php. etc. Esto a veces funciona y a veces no, como dice la documentación, se supone que es necesario para rutas relativas, pero la mayoría de las veces parece funcionar. Excepto cuando está redirigiendo (usando la Rbandera, o implícitamente porque tiene http://hosten el objetivo de su regla). Eso significa esta regla:

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

si está en el directorio "subdir2", y te vas a http://example.com/subdir2/foo, mod_rewrite confundirá la ruta relativa como un archivo de ruta en lugar de una dirección URL de la ruta y debido a la Rbandera, que va a terminar siendo redirigido a algo como: http://example.com/var/www/localhost/htdocs/subdir1. Lo cual obviamente no es lo que quieres.

Aquí es donde RewriteBaseentra. 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/foorealmente me servirá 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 múltiples 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, por lo que puede colocarlas en cualquier directorio y solo necesita cambiar la base en lugar de un montón 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]
...

tal que va a http://example.com/subdir1/fooservir, http://example.com/subdir1/bar.phpetc. 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 necesita mover esos archivos y las reglas a otro directorio, simplemente cambie la base:

RewriteBase /subdir2/subsubdir/

y eso es.

Simon East
fuente
Para mí, lo extrañé RewriteEngine On. No es necesario en 1 y 1, por ejemplo, pero es necesario en mi servidor dedicado.
Portekoi
41

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

RewriteBase myfolder

Si mod_rewrite no funciona correctamente.

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

rjmunro
fuente
2
¿Tiene que terminar con una barra inclinada final?
Pacerier
@self, No. Probado y sub explicado aquí: stackoverflow.com/a/11443194/632951
Pacerier el
23

RewriteBase solo es útil en situaciones en las que solo puede poner un .htaccess en la raíz de su 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 eliminando, porque hace que la implementación de archivos de prueba para vivir solo sea un paso más complicado.

Thomas Hunter II
fuente
22
Aunque este puede ser un buen consejo, no es una respuesta a la pregunta. Por lo tanto, debería haber sido un comentario a la pregunta, no haber recibido (tantos) votos a favor y definitivamente no haber sido aceptado como "respuesta".
Kissaki
3
"mejor colocando sus diferentes archivos .htaccess en diferentes directorios" - ¿No estoy seguro de que este sea un buen consejo? Tener archivos .htaccess repartidos por todo su sitio puede hacer que la depuración / mantenimiento sea una pesadilla. Hubiera dicho que era preferible tener un archivo .htaccess en la raíz de su sitio.
MrWhite
1
@ w3d También existe una cuestión de tiempo: cada vez que se accede a un subdirectorio, se analizan múltiples archivos .htaccess (desde el subdirectorio raíz hasta el actual). Tener muchos archivos podría reducir la velocidad de la respuesta general a la solicitud, en lugar de un solo archivo en la raíz, incluso si contiene muchas reglas ...
Erenor Paz
19

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 vivir:

RewriteBase /
# RewriteBase /dev_folder/

Al desarrollar:

# RewriteBase /
RewriteBase /dev_folder/
usuario1669830
fuente
44
Estoy seguro de que esto no siempre funcionará. ¿Qué pasa si usas %{REQUEST_URI}en una RewriteConddirectiva por ejemplo?
MrWhite
1
@ user1669830, si solo tiene una reescritura, podría haber agregado la base a la
reescritura
18

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, 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

¿Como funciona? Para los piratas informáticos de Apache, este documento de 2.0 proporciona "información detallada sobre los pasos de procesamiento interno".

Lección aprendida: si bien debemos estar familiarizados con las "actuales", las gemas se pueden encontrar en los anales.

DWB
fuente
3

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 /
Sandeep Goyal
fuente
2

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 contexto por directorio (htaccess) a menos que se cumpla alguna de las siguientes condiciones:

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

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

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

alex
fuente