<-
Apache > Servidor HTTP > Documentación > Versión 2.5 > Rewrite

Redirección y Remapeo con mod_rewrite

Idiomas disponibles:  de  |  en  |  es  |  fr  |  ja  |  ko  |  tr  |  zh-cn 

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.

Tenga en cuenta que muchos de estos ejemplos no funcionarán sin cambios en su configuración particular del servidor, por lo que es importante que los entienda, en lugar de simplemente copiar y pegar los ejemplos en su configuración.

Consulte también

top

De Antiguo a Nuevo (interno)

Descripción:

Supongamos 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.

Solución:

Reescribimos la antigua URL a la nueva internamente mediante la siguiente regla:

RewriteEngine  on
RewriteRule    "^/foo\.html$"  "/bar.html" [PT]
top

Reescritura de Antiguo a Nuevo (externo)

Descripción:

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.

Solución:

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]
Discusión

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"
top

Recurso Movido a Otro Servidor

Descripción:

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.

Solución:

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/"
top

De Estático a Dinámico

Descripción:

¿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.

Solución:

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]
top

Compatibilidad hacia atrás para cambio de extensión de archivo

Descripción:

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

Solución:

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>
Discusión

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.

top

Nombres de Host Canónicos

Descripción:
El objetivo de esta regla es forzar el uso de un nombre de host particular, en preferencia a otros nombres de host que pueden usarse para alcanzar el mismo sitio. Por ejemplo, si desea forzar el uso de www.example.com en lugar de example.com, podría usar una variante de la siguiente receta.
Solución:

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.

top

Búsqueda de páginas en más de un directorio

Descripción:

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.

Solución:

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]
top

Redirección a Servidores Distribuidos Geográficamente

Descripción:

Tenemos numerosos espejos de nuestro sitio web, y queremos redirigir a la gente al que está ubicado en el país donde se encuentran.

Solución:

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

Discusión
Este conjunto de reglas depende de que 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.

top

URLs Canónicas

Descripción:

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.

Solución:

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]
Discusión:
Esto realmente debería lograrse con directivas Redirect o RedirectMatch:
RedirectMatch "^/(puppies|canines)/(.*)" "/dogs/$2"
top

DocumentRoot Movido

Descripción:

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:

Solución:

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.

top

Recurso de Respaldo

Descripción:
Desea que un solo recurso (digamos, un cierto archivo, como index.php) maneje todas las solicitudes que lleguen a un directorio particular, excepto aquellas que deberían ir a un recurso existente como una imagen, o un archivo css.
Solución:

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

top

Reescribir cadena de consulta

Descripción:
Desea capturar un valor particular de una cadena de consulta y reemplazarlo o incorporarlo en otro componente de la URL.
Soluciones:

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.

  • Esta solución elimina la clave y valor coincidentes:
    # Remove mykey=???
    RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"
    RewriteRule "(.*)"            "$1?%1%3"
  • Esta solución usa el valor capturado en la sustitución de URL, descartando el resto de la consulta original añadiendo un '?':
    # Copy from query string to PATH_INFO
    RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"
    RewriteRule "(.*)"            "$1/products/%2/?" [PT]
  • Esta solución verifica el valor capturado en una condición posterior:
    # Capture the value of mykey in the query string
    RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"
    RewriteCond "%2"              !=not-so-secret-value
    RewriteRule "(.*)"            "-" [F]
  • Esta solución muestra lo inverso de las anteriores, copiando componentes de ruta (quizás PATH_INFO) de la URL a la cadena de consulta.
    # The desired URL might be /products/kitchen-sink, and the script expects
    # /path?products=kitchen-sink.
    RewriteRule "^/?path/([^/]+)/([^/]+)" "/path?$1=$2" [PT]

Idiomas disponibles:  de  |  en  |  es  |  fr  |  ja  |  ko  |  tr  |  zh-cn