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

Uso de RewriteMap

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

Este documento complementa la mod_rewrite documentación de referencia. Describe el uso de la directiva RewriteMap, y proporciona ejemplos de cada uno de los diversos tipos de RewriteMap.

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

Introducción

La directiva RewriteMap define una función externa que puede ser llamada en el contexto de directivas RewriteRule o RewriteCond para realizar reescrituras que son demasiado complicadas, o demasiado especializadas para ser realizadas solo con expresiones regulares. La fuente de esta búsqueda puede ser cualquiera de los tipos listados en las secciones siguientes, y enumerados en la documentación de referencia de RewriteMap.

La sintaxis de la directiva RewriteMap es la siguiente:

RewriteMap MapName MapType:MapSource

El MapName es un nombre arbitrario que asigna al mapa, y que usará en directivas más adelante. Los argumentos se pasan al mapa a través de la siguiente sintaxis:

${ MapName : LookupKey }
${ MapName : LookupKey | DefaultValue }

Cuando se encuentra tal construcción, se consulta el mapa MapName y se busca la clave LookupKey. Si la clave se encuentra, la construcción de función de mapa se sustituye por SubstValue. Si la clave no se encuentra entonces se sustituye por DefaultValue o por la cadena vacía si no se especificó DefaultValue.

Por ejemplo, puede definir un RewriteMap como:

RewriteMap examplemap "txt:/path/to/file/map.txt"

Entonces podrá usar este mapa en una RewriteRule de la siguiente manera:

RewriteRule "^/ex/(.*)" "${examplemap:$1}"

Se puede especificar un valor predeterminado en caso de que no se encuentre nada en el mapa:

RewriteRule "^/ex/(.*)" "${examplemap:$1|/not_found.html}"

Contexto per-directorio y .htaccess

La directiva RewriteMap no puede usarse en secciones <Directory> ni en archivos .htaccess. Debe declarar el mapa en contexto de servidor o virtualhost. Puede usar el mapa, una vez creado, en sus directivas RewriteRule y RewriteCond en esos ámbitos. Simplemente no puede declararlo en esos ámbitos.

Las secciones siguientes describen los diversos MapTypes que pueden usarse, y dan ejemplos de cada uno.

top

int: Función Interna

Cuando se usa un MapType de int, el MapSource es una de las funciones internas disponibles de RewriteMap. Los autores de módulos pueden proporcionar funciones internas adicionales registrándolas con la API ap_register_rewrite_mapfunc. Las funciones que se proporcionan por defecto son:

Para usar una de estas funciones, cree un RewriteMap que referencie la función int, y luego úselo en su RewriteRule:

Redirigir una URI a una versión toda en minúsculas de sí misma

RewriteMap lc int:tolower
RewriteRule "(.*)" "${lc:$1}" [R]

Por favor tenga en cuenta que el ejemplo ofrecido aquí es para fines ilustrativos únicamente, y no es una recomendación. Si desea hacer URLs insensibles a mayúsculas/minúsculas, considere usar mod_speling en su lugar.

top

txt: Mapas de texto plano

Cuando se usa un MapType de txt, el MapSource es una ruta del sistema de archivos a un archivo de mapeo de texto plano, que contiene un par clave/valor separado por espacios por línea. Opcionalmente, una línea puede contener un comentario, comenzando con un carácter '#'.

Un archivo de mapa de reescritura de texto válido tendrá la siguiente sintaxis:

# Línea de comentario
MatchingKey SubstValue
MatchingKey SubstValue # comentario

Cuando se invoca el RewriteMap, el argumento se busca en el primer argumento de una línea, y, si se encuentra, se devuelve el valor de sustitución.

Por ejemplo, podemos usar un archivo de mapa para traducir nombres de productos a IDs de productos para URLs más fáciles de recordar, usando la siguiente receta:

Configuración de Producto a ID

RewriteMap product2id "txt:/etc/apache2/productmap.txt"
RewriteRule "^/product/(.*)" "/prods.php?id=${product2id:$1|NOTFOUND}" [PT]

Asumimos aquí que el script prods.php sabe qué hacer cuando recibe un argumento de id=NOTFOUND cuando un producto no se encuentra en el mapa de búsqueda.

El archivo /etc/apache2/productmap.txt entonces contiene lo siguiente:

Mapa de Producto a ID

##
## productmap.txt - Archivo de mapa de Producto a ID
##

television 993
stereo 198
fishingrod 043
basketball 418
telephone 328

Así, cuando se solicita http://example.com/product/television, se aplica la RewriteRule, y la solicitud se mapea internamente a /prods.php?id=993.

Nota: archivos .htaccess

El ejemplo dado está diseñado para usarse en contexto de servidor o virtualhost. Si planea usarlo en un archivo .htaccess, necesitará eliminar la barra inicial del patrón de reescritura para que coincida con algo:
RewriteRule "^product/(.*)" "/prods.php?id=${product2id:$1|NOTFOUND}" [PT]

Búsquedas en caché

Las claves buscadas son almacenadas en caché por httpd hasta que el mtime (tiempo de modificación) del archivo de mapa cambia, o el servidor httpd se reinicia. Esto asegura un mejor rendimiento en mapas que son llamados por muchas solicitudes.

top

rnd: Texto Plano Aleatorizado

Cuando se usa un MapType de rnd, el MapSource es una ruta del sistema de archivos a un archivo de mapeo de texto plano, cada línea del cual contiene una clave, y uno o más valores separados por |. Uno de estos valores se elegirá al azar si la clave coincide.

Por ejemplo, puede usar el siguiente archivo de mapa y directivas para proporcionar un balanceo de carga aleatorio entre varios servidores backend, a través de un proxy inverso. Las imágenes se envían a uno de los servidores en el grupo 'static', mientras que todo lo demás se envía a uno del grupo 'dynamic'.

Archivo de mapa de reescritura

##
## map.txt -- mapa de reescritura
##

static www1|www2|www3|www4
dynamic www5|www6

Directivas de configuración

RewriteMap servers "rnd:/path/to/file/map.txt"

RewriteRule "^/(.*\.(png|gif|jpg))" "http://${servers:static}/$1"  [NC,P,L]
RewriteRule "^/(.*)"                "http://${servers:dynamic}/$1" [P,L]

Así, cuando se solicita una imagen y la primera de estas reglas coincide, RewriteMap busca la cadena static en el archivo de mapa, que devuelve uno de los nombres de host especificados al azar, que luego se usa en el destino de la RewriteRule.

Si quisiera que uno de los servidores sea más probable de ser elegido (por ejemplo, si uno de los servidores tiene más memoria que los otros, y por lo tanto puede manejar más solicitudes) simplemente listelo más veces en el archivo de mapa.

static www1|www1|www2|www3|www4

top

dbm: Archivo Hash DBM

Cuando se usa un MapType de dbm, el MapSource es una ruta del sistema de archivos a un archivo de base de datos DBM que contiene pares clave/valor para ser usados en el mapeo. Esto funciona exactamente igual que el mapa txt, pero es mucho más rápido, porque un DBM está indexado, mientras que un archivo de texto no. Esto permite un acceso más rápido a la clave deseada.

Opcionalmente puede especificar un tipo particular de dbm:

RewriteMap examplemap "dbm=sdbm:/etc/apache/mapfile.dbm"

El tipo puede ser sdbm, gdbm, ndbm o db. Sin embargo, se recomienda que simplemente use la utilidad httxt2dbm que se proporciona con Apache HTTP Server, ya que usará la biblioteca DBM correcta, que coincida con la que se usó cuando se compiló httpd mismo.

Para crear un archivo dbm, primero cree un archivo de mapa de texto como se describe en la sección txt. Luego ejecute httxt2dbm:

$ httxt2dbm -i mapfile.txt -o mapfile.map

Luego puede referenciar el archivo resultante en su directiva RewriteMap:

RewriteMap mapname "dbm:/etc/apache/mapfile.map"

Tenga en cuenta que con algunos tipos de dbm, se genera más de un archivo, con un nombre base común. Por ejemplo, puede tener dos archivos llamados mapfile.map.dir y mapfile.map.pag. Esto es normal, y solo necesita usar el nombre base mapfile.map en su directiva RewriteMap.

Búsquedas en caché

Las claves buscadas son almacenadas en caché por httpd hasta que el mtime (tiempo de modificación) del archivo de mapa cambia, o el servidor httpd se reinicia. Esto asegura un mejor rendimiento en mapas que son llamados por muchas solicitudes.

top

prg: Programa de Reescritura Externo

Cuando se usa un MapType de prg, el MapSource es una ruta del sistema de archivos a un programa ejecutable que proporcionará el comportamiento de mapeo. Puede ser un archivo binario compilado, o un programa en un lenguaje interpretado como Python o Perl.

Este programa se inicia una vez, cuando se inicia Apache HTTP Server, y luego se comunica con el motor de reescritura a través de STDIN y STDOUT. Para cada búsqueda de función de mapa, la clave se escribe en el STDIN del programa, seguida de un carácter de nueva línea. El programa debería leer una línea de STDIN (hasta e incluyendo la nueva línea), y escribir su respuesta como una única línea terminada en nueva línea en STDOUT. Las claves nunca contendrán caracteres de nueva línea; si se encuentra una clave que contenga una nueva línea, la búsqueda fallará.

Si no hay un valor de búsqueda correspondiente, el programa de mapa debería devolver la cadena de cuatro caracteres "NULL" para indicar esto. Tenga en cuenta que esta comparación no distingue entre mayúsculas y minúsculas, así que "null", "Null", etc. también se tratan como una búsqueda fallida. Como consecuencia, no es posible que un programa de mapeo devuelva la cadena literal "NULL" como valor mapeado.

El STDERR del programa se hereda del proceso padre de httpd, por lo que cualquier cosa que el programa escriba en STDERR terminará en el mismo lugar que la propia salida de errores de httpd (típicamente el ErrorLog).

Los programas de reescritura externos no se inician si están definidos en un contexto que no tiene RewriteEngine establecido a on.

Por defecto, los programas de reescritura externos se ejecutan como el usuario:grupo que inició httpd. Esto puede cambiarse en sistemas UNIX pasando nombre de usuario y nombre de grupo como tercer argumento a RewriteMap en el formato username:groupname.

Esta característica utiliza el mutex rewrite-map, que es necesario para una comunicación fiable con el programa. El mecanismo de mutex y el archivo de bloqueo pueden configurarse con la directiva Mutex.

Aquí se muestra un ejemplo simple que reemplazará todos los guiones con guiones bajos en una URI de solicitud.

Configuración de reescritura

RewriteMap d2u "prg:/www/bin/dash2under.py" apache:apache
RewriteRule "-" "${d2u:%{REQUEST_URI}}"

dash2under.py

#!/usr/bin/env python3
import sys

for line in sys.stdin:
    print(line.strip().replace('-', '_'), flush=True)

¡Precaución!

  • Mantenga su programa de mapa de reescritura lo más simple posible. Si el programa se cuelga, causará que httpd espere indefinidamente por una respuesta del mapa, lo que a su vez causará que httpd deje de responder a solicitudes.
  • Asegúrese de desactivar el buffering en su programa. En el ejemplo de Python anterior, esto se hace pasando flush=True a print(). La E/S con buffer causará que httpd espere la salida, y por lo tanto se colgará.
  • Recuerde que solo hay una copia del programa, iniciada al arrancar el servidor. Todas las solicitudes necesitarán pasar por este único cuello de botella. Esto puede causar ralentizaciones significativas si muchas solicitudes deben pasar por este proceso, o si el script en sí es muy lento.
  • Si el programa de mapeo termina, no se reiniciará automáticamente. Las búsquedas posteriores fallarán hasta que el servidor sea reiniciado.
  • El programa de mapeo siempre se mata y reinicia en cualquier reinicio del servidor (graceful o de otro tipo), independientemente de si las directivas de configuración relacionadas han cambiado. Al apagar, se envía SIGTERM al programa; si no sale dentro de 3 segundos, se le envía SIGKILL.
top

dbd o fastdbd: Consulta SQL

Cuando se usa un MapType de dbd o fastdbd, el MapSource es una sentencia SQL SELECT que toma un solo argumento y devuelve un solo valor.

mod_dbd necesitará estar configurado para apuntar a la base de datos correcta para que esta sentencia se ejecute.

Hay dos formas de este MapType. Usar un MapType de dbd causa que la consulta se ejecute con cada solicitud de mapa, mientras que usar fastdbd almacena en caché las búsquedas de base de datos internamente. Así, mientras que fastdbd es más eficiente, y por lo tanto más rápido, no reflejará los cambios en la base de datos hasta que el servidor sea reiniciado.

Si una consulta devuelve más de una fila, se usa una fila aleatoria del conjunto de resultados.

Ejemplo

RewriteMap myquery "fastdbd:SELECT destination FROM rewrite WHERE source = %s"

Nota

El nombre de la consulta se pasa al controlador de base de datos como una etiqueta para una sentencia SQL preparada, y por lo tanto necesitará seguir cualquier regla (como sensibilidad a mayúsculas/minúsculas) requerida por su base de datos.

top

Resumen

La directiva RewriteMap puede aparecer más de una vez. Para cada función de mapeo use una directiva RewriteMap para declarar su archivo de mapa de reescritura.

Aunque no puede declarar un mapa en contexto per-directorio (archivos .htaccess o bloques <Directory>) es posible usar este mapa en contexto per-directorio.

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