Versión 2.5 del Servidor HTTP Apache

Este documento complementa la mod_rewrite
documentación de referencia. Describe
cómo puede usar mod_rewrite para redirigir y remapear
solicitudes. Esto incluye muchos ejemplos de usos comunes de mod_rewrite,
incluyendo descripciones detalladas de cómo funciona cada uno.
De Antiguo a Nuevo (interno)
Reescritura de Antiguo a Nuevo (externo)
Recurso Movido a Otro Servidor
De Estático a Dinámico
Compatibilidad hacia atrás para cambio de extensión de archivo
Nombres de Host Canónicos
Búsqueda de páginas en más de un directorio
Redirección a Servidores Distribuidos Geográficamente
URLs Canónicas
DocumentRoot Movido
Recurso de Respaldo
Reescribir cadena de consultaSupongamos que hemos renombrado recientemente la página
foo.html a bar.html y ahora queremos
proporcionar la antigua URL por compatibilidad hacia atrás. Sin embargo,
queremos que los usuarios de la antigua URL ni siquiera se den cuenta de que
la página fue renombrada - es decir, no queremos que la dirección
cambie en su navegador.
Reescribimos la antigua URL a la nueva internamente mediante la siguiente regla:
RewriteEngine on RewriteRule "^/foo\.html$" "/bar.html" [PT]
Supongamos de nuevo que hemos renombrado recientemente la página
foo.html a bar.html y ahora queremos
proporcionar la antigua URL por compatibilidad hacia atrás. Pero esta
vez queremos que los usuarios de la antigua URL reciban una indicación de
la nueva, es decir, que el campo de Ubicación de su navegador también
cambie.
Forzamos una redirección HTTP a la nueva URL que lleva a un cambio del navegador y por lo tanto de la vista del usuario:
RewriteEngine on RewriteRule "^/foo\.html$" "bar.html" [R]
En este ejemplo, a diferencia del ejemplo interno anterior, podemos simplemente
usar la directiva Redirect. mod_rewrite se usó en ese ejemplo
anterior para ocultar la redirección del cliente:
Redirect "/foo.html" "/bar.html"
Si un recurso se ha movido a otro servidor, puede desear que las URLs continúen funcionando por un tiempo en el antiguo servidor mientras la gente actualiza sus marcadores.
Puede usar mod_rewrite para redirigir estas URLs
al nuevo servidor, pero también podría considerar usar la directiva Redirect
o RedirectMatch.
#With mod_rewrite RewriteEngine on RewriteRule "^/docs/(.+)" "http://new.example.com/docs/$1" [R,L]
#With RedirectMatch RedirectMatch "^/docs/(.*)" "http://new.example.com/docs/$1"
#With Redirect Redirect "/docs/" "http://new.example.com/docs/"
¿Cómo podemos transformar una página estática
foo.html en una variante dinámica
foo.cgi de manera transparente, es decir, sin que
el navegador/usuario lo note.
Simplemente reescribimos la URL al script CGI y forzamos el
manejador a ser cgi-script para que se
ejecute como un programa CGI.
De esta manera, una solicitud a /~quux/foo.html
internamente lleva a la invocación de
/~quux/foo.cgi.
RewriteEngine on RewriteBase "/~quux/" RewriteRule "^foo\.html$" "foo.cgi" [H=cgi-script]
¿Cómo podemos hacer URLs retrocompatibles (aún
existentes virtualmente) después de migrar document.YYYY
a document.XXXX, por ejemplo, después de traducir un
grupo de archivos .html a .php?
La URL se reescribe de la antigua extensión a la nueva solo si el archivo destino con la nueva extensión existe y el archivo original con la antigua extensión no existe. De lo contrario, la URL se deja sin cambios.
# backward compatibility ruleset for
# rewriting document.html to document.php
# when and only when document.php exists
<Directory "/var/www/htdocs">
RewriteEngine on
RewriteBase "/var/www/htdocs"
RewriteCond "$1.php" -f
RewriteCond "$1.html" !-f
RewriteRule "^(.*).html$" "$1.php"
</Directory>
Este ejemplo usa una característica a menudo pasada por alto de mod_rewrite,
aprovechando el orden de ejecución del conjunto de reglas. En
particular, mod_rewrite evalúa el lado izquierdo de la
RewriteRule antes de evaluar las directivas RewriteCond.
En consecuencia, $1 ya está definido para el momento en que las directivas
RewriteCond se evalúan. Esto nos permite probar la existencia
del archivo original (document.html) y destino
(document.php) usando el mismo nombre de archivo base.
Este conjunto de reglas está diseñado para usarse en un contexto per-directorio (en un
bloque <Directory> o en un archivo .htaccess), de modo que las
verificaciones -f busquen en la ruta de directorio correcta.
Puede necesitar establecer una directiva RewriteBase para especificar la
base de directorio en la que está trabajando.
La mejor manera de resolver esto no involucra mod_rewrite en absoluto,
sino que usa la directiva Redirect
colocada en un host virtual para el o los nombres de host no canónicos.
<VirtualHost *:80> ServerName undesired.example.com ServerAlias example.com notthis.example.com Redirect "/" "http://www.example.com/" </VirtualHost> <VirtualHost *:80> ServerName www.example.com </VirtualHost>
Alternativamente puede lograr esto usando la
directiva <If>:
(2.4 y posterior)
<If "%{HTTP_HOST} != 'www.example.com'">
Redirect "/" "http://www.example.com/"
</If>
O, por ejemplo, para redirigir una porción de su sitio a HTTPS, podría hacer lo siguiente:
<If "%{SERVER_PROTOCOL} != 'HTTPS'">
Redirect "/admin/" "https://www.example.com/admin/"
</If>
Si, por cualquier razón, aún desea usar mod_rewrite
- si, por ejemplo, necesita que esto funcione con un conjunto más grande de RewriteRules -
podría usar una de las recetas siguientes.
Para sitios ejecutándose en un puerto distinto al 80:
RewriteCond "%{HTTP_HOST}" "!^www\.example\.com" [NC]
RewriteCond "%{HTTP_HOST}" "!^$"
RewriteCond "%{SERVER_PORT}" "!^80$"
RewriteRule "^/?(.*)" "http://www.example.com:%{SERVER_PORT}/$1" [L,R,NE]
Y para un sitio ejecutándose en el puerto 80
RewriteCond "%{HTTP_HOST}" "!^www\.example\.com" [NC]
RewriteCond "%{HTTP_HOST}" "!^$"
RewriteRule "^/?(.*)" "http://www.example.com/$1" [L,R,NE]
Si quisiera hacer esto genéricamente para todos los nombres de dominio - es decir, si quiere redirigir example.com a www.example.com para todos los valores posibles de example.com, podría usar la siguiente receta:
RewriteCond "%{HTTP_HOST}" "!^www\." [NC]
RewriteCond "%{HTTP_HOST}" "!^$"
RewriteRule "^/?(.*)" "http://www.%{HTTP_HOST}/$1" [L,R,NE]
Estos conjuntos de reglas funcionarán tanto en su archivo de configuración principal
del servidor, como en un archivo .htaccess colocado en el DocumentRoot del servidor.
Un recurso particular podría existir en uno de varios lugares, y queremos buscar en esos lugares el recurso cuando se solicita. Quizás hemos reorganizado recientemente nuestra estructura de directorios, dividiendo el contenido en varias ubicaciones.
El siguiente conjunto de reglas busca en dos directorios para encontrar el recurso, y, si no lo encuentra en ninguno de los dos, intentará simplemente servirlo desde la ubicación solicitada.
RewriteEngine on
# first try to find it in dir1/...
# ...and if found stop and be happy:
RewriteCond "%{DOCUMENT_ROOT}/dir1/%{REQUEST_URI}" -f
RewriteRule "^(.+)" "%{DOCUMENT_ROOT}/dir1/$1" [L]
# second try to find it in dir2/...
# ...and if found stop and be happy:
RewriteCond "%{DOCUMENT_ROOT}/dir2/%{REQUEST_URI}" -f
RewriteRule "^(.+)" "%{DOCUMENT_ROOT}/dir2/$1" [L]
# else go on for other Alias or ScriptAlias directives,
# etc.
RewriteRule "^" "-" [PT]
Tenemos numerosos espejos de nuestro sitio web, y queremos redirigir a la gente al que está ubicado en el país donde se encuentran.
Mirando el nombre de host del cliente solicitante, determinamos de qué país provienen. Si no podemos hacer una búsqueda de su dirección IP, recurrimos a un servidor predeterminado.
Usaremos una directiva RewriteMap
para construir una lista de servidores que deseamos usar.
HostnameLookups on
RewriteEngine on
RewriteMap multiplex "txt:/path/to/map.mirrors"
RewriteCond "%{REMOTE_HOST}" "([a-z]+)$" [NC]
RewriteRule "^/(.*)$" "${multiplex:%1|http://www.example.com/}$1" [R,L]
## map.mirrors -- Mapa de Multiplexación
de http://www.example.de/
uk http://www.example.uk/
com http://www.example.com/
##EOF##
HostNameLookups
esté configurado como on, lo que puede ser
un impacto significativo en el rendimiento.La directiva RewriteCond
captura la última parte del nombre de host del
cliente solicitante - el código de país - y la siguiente RewriteRule
usa ese valor para buscar el host espejo apropiado en el archivo
de mapa.
En algunos servidores web hay más de una URL para un recurso. Generalmente hay URLs canónicas (que son las que realmente se usan y distribuyen) y aquellas que son solo atajos, internas, etc. Independientemente de qué URL proporcionó el usuario con la solicitud, finalmente debería ver la canónica en la barra de direcciones de su navegador.
Hacemos una redirección HTTP externa para todas las
URLs no canónicas para corregirlas en la vista de ubicación del navegador y
para todas las solicitudes posteriores. En el conjunto de reglas de ejemplo
reemplazamos /puppies y /canines
por el canónico /dogs.
RewriteRule "^/(puppies|canines)/(.*)" "/dogs/$2" [R]
RedirectMatch "^/(puppies|canines)/(.*)" "/dogs/$2"
DocumentRoot Movido ¶Generalmente el DocumentRoot
del servidor web se relaciona directamente con la URL "/".
Pero a menudo estos datos no son realmente de máxima prioridad. Por ejemplo,
puede desear que los visitantes, al entrar por primera vez a un sitio, vayan a un
subdirectorio particular /about/. Esto puede lograrse
usando el siguiente conjunto de reglas:
Redirigimos la URL / a
/about/:
RewriteEngine on RewriteRule "^/$" "/about/" [R]
Tenga en cuenta que esto también puede manejarse usando la directiva RedirectMatch:
RedirectMatch "^/$" "http://example.com/about/"
Tenga en cuenta también que el ejemplo solo reescribe la URL raíz. Es decir, reescribe
una solicitud para http://example.com/, pero no una
solicitud para http://example.com/page.html. Si de hecho ha
cambiado la raíz de documentos - es decir, si todo su
contenido está en ese subdirectorio, es muy preferible
simplemente cambiar su directiva DocumentRoot,
o mover todo el contenido un directorio arriba,
en lugar de reescribir URLs.
A partir de la versión 2.2.16, debería usar la directiva FallbackResource para esto:
<Directory "/var/www/my_blog"> FallbackResource index.php </Directory>
Sin embargo, en versiones anteriores de Apache, o si sus necesidades son más complicadas que esto, puede usar una variación del siguiente conjunto de reescritura para lograr lo mismo:
<Directory "/var/www/my_blog">
RewriteBase "/my_blog"
RewriteCond "/var/www/my_blog/%{REQUEST_FILENAME}" !-f
RewriteCond "/var/www/my_blog/%{REQUEST_FILENAME}" !-d
RewriteRule "^" "index.php" [PT]
</Directory>
Si, por otro lado, desea pasar la URI solicitada como un argumento de cadena de consulta a index.php, puede reemplazar esa RewriteRule con:
RewriteRule "(.*)" "index.php?$1" [PT,QSA]
Tenga en cuenta que estos conjuntos de reglas pueden usarse en un archivo .htaccess,
así como en un bloque <Directory>.
Muchas de las soluciones en esta sección usarán la misma condición, que deja el valor coincidente en la referencia inversa %2. %1 es el inicio de la cadena de consulta (hasta la clave de interés), y %3 es el resto. Esta condición es un poco compleja por flexibilidad y para evitar doble '&&' en las sustituciones.
# Remove mykey=???
RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"
RewriteRule "(.*)" "$1?%1%3"
# Copy from query string to PATH_INFO
RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"
RewriteRule "(.*)" "$1/products/%2/?" [PT]
# Capture the value of mykey in the query string
RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"
RewriteCond "%2" !=not-so-secret-value
RewriteRule "(.*)" "-" [F]
# The desired URL might be /products/kitchen-sink, and the script expects # /path?products=kitchen-sink. RewriteRule "^/?path/([^/]+)/([^/]+)" "/path?$1=$2" [PT]