Esta es una pregunta canónica sobre el mod_rewrite de Apache.
El cambio de una URL de solicitud o la redirección de los usuarios a una URL diferente a la que solicitaron originalmente se realiza mediante mod_rewrite. Esto incluye cosas como:
- Cambiar HTTP a HTTPS (o al revés)
- Cambiar una solicitud a una página que ya no existe a un nuevo reemplazo.
- Modificar un formato de URL (como? Id = 3433 a / id / 3433)
- Presentar una página diferente basada en el navegador, en base al referente, en base a todo lo posible bajo la luna y el sol.
- Todo lo que quieras perder con URL
¡Todo lo que siempre quiso saber sobre las reglas Mod_Rewrite, pero tenía miedo de preguntar!
¿Cómo puedo convertirme en un experto en escribir reglas mod_rewrite?
- ¿Cuál es el formato y la estructura fundamentales de las reglas mod_rewrite?
- ¿De qué forma / sabor de las expresiones regulares necesito tener una comprensión sólida?
- ¿Cuáles son los errores / dificultades más comunes al escribir reglas de reescritura?
- ¿Cuál es un buen método para probar y verificar las reglas mod_rewrite?
- ¿Hay implicaciones de SEO o rendimiento de las reglas mod_rewrite que debo tener en cuenta?
- ¿Hay situaciones comunes en las que mod_rewrite puede parecer la herramienta adecuada para el trabajo pero no lo es?
- ¿Cuáles son algunos ejemplos comunes?
Un lugar para probar tus reglas
El sitio web de htaccess tester es un gran lugar para jugar con sus reglas y probarlas. Incluso muestra la salida de depuración para que pueda ver qué coincide y qué no.
apache-2.2
mod-rewrite
redirect
redirection
301-redirect
Kyle Brandt
fuente
fuente
mod-rewrite
búsquedas / filtros de etiquetas.Respuestas:
orden de sintaxis mod_rewrite
mod_rewrite tiene algunas reglas de orden específicas que afectan el procesamiento. Antes de que se haga algo, la
RewriteEngine On
directiva debe ser dada ya que esto activa el procesamiento mod_rewrite. Esto debería ser antes de cualquier otra directiva de reescritura.RewriteCond
el precedenteRewriteRule
hace que UNA regla esté sujeta al condicional. Las siguientes RewriteRules se procesarán como si no estuvieran sujetas a condicionales.En este caso simple, si el referente HTTP es de serverfault.com, redirija las solicitudes de blog a páginas especiales de servidor por defecto (somos así de especiales). Sin embargo, si el bloque anterior tenía una línea RewriteRule adicional:
Todos los archivos .jpg irían a las páginas especiales de servidor por defecto, no solo los que tienen un referente que indica que proviene de aquí. Claramente, esta no es la intención de cómo se escriben estas reglas. Se podría hacer con múltiples reglas RewriteCond:
Pero probablemente debería hacerse con una sintaxis de reemplazo más complicada.
El RewriteRule más complejo contiene los condicionales para el procesamiento. El último paréntesis,
(html|jpg)
le dice a RewriteRule que coincida con unohtml
ojpg
, y que represente la cadena coincidente como $ 2 en la cadena reescrita. Esto es lógicamente idéntico al bloque anterior, con dos pares RewriteCond / RewriteRule, solo lo hace en dos líneas en lugar de cuatro.Múltiples líneas RewriteCond están AND implícitamente y pueden OR explícitamente. Para manejar referencias de ServerFault y Super User (OR explícito):
Para servir páginas referidas por ServerFault con navegadores Chrome (Y implícito):
RewriteBase
también es específico de la orden, ya que especifica cómo las siguientesRewriteRule
directivas manejan su procesamiento. Es muy útil en archivos .htaccess. Si se usa, debería ser la primera directiva bajo "RewriteEngine on" en un archivo .htaccess. Toma este ejemplo:Esto le dice a mod_rewrite que esta URL particular que está manejando actualmente llegó a través de http://example.com/blog/ en lugar de la ruta del directorio físico (/ home / $ Username / public_html / blog) y para tratarla en consecuencia. Debido a esto,
RewriteRule
considera que el inicio de cadena es posterior al "/ blog" en la URL. Aquí está lo mismo escrito de dos maneras diferentes. Uno con RewriteBase, el otro sin:Como puede ver,
RewriteBase
permite que las reglas de reescritura aprovechen la ruta del sitio web al contenido en lugar del servidor web , lo que puede hacerlas más inteligibles para quienes editan dichos archivos. Además, pueden acortar las directivas, lo que tiene un atractivo estético.Sintaxis de coincidencia RewriteRule
RewriteRule tiene una sintaxis compleja para hacer coincidir cadenas. Cubriré las banderas (cosas como [PT]) en otra sección. Como los administradores de sistemas aprenden con el ejemplo con más frecuencia que leyendo una página de manual , daré ejemplos y explicaré lo que hacen.
La
.*
construcción coincide con cualquier carácter individual (.
) cero o más veces (*
). Encerrándolo entre paréntesis le dice que proporcione la cadena que coincidió con la variable $ 1.En este caso, el primer. * NO estaba encerrado en parens, por lo que no se proporciona a la cadena reescrita. Esta regla elimina un nivel de directorio en el nuevo blog-sitio. (/blog/2009/sample.html se convierte en /newblog/sample.html).
En este caso, la primera expresión de paréntesis establece un grupo coincidente. Esto se convierte en $ 1, que no es necesario y, por lo tanto, no se usa en la cadena reescrita.
En este caso, usamos $ 1 en la cadena reescrita.
Esta regla utiliza una sintaxis de paréntesis especial que especifica un rango de caracteres . [0-9] coincide con los números del 0 al 9. Esta regla específica manejará años del 2000 al 2099.
Esto hace lo mismo que la regla anterior, pero la parte {2} le dice que coincida con el carácter anterior (una expresión de paréntesis en este caso) dos veces.
Este caso coincidirá con cualquier letra minúscula en la segunda expresión coincidente, y lo hará para tantos caracteres como sea posible. La
\.
construcción le dice que trate el período como un período real, no el carácter especial que es en los ejemplos anteriores. Sin embargo, se romperá si el nombre de archivo tiene guiones.Esto atrapa nombres de archivo con guiones en ellos. Sin embargo, como
-
es un carácter especial en las expresiones de paréntesis, tiene que ser el primer carácter de la expresión.Esta versión atrapa cualquier nombre de archivo con letras, números o el
-
carácter en el nombre del archivo. Así es como especifica varios conjuntos de caracteres en una expresión de paréntesis.RewriteRule flags
Las banderas en las reglas de reescritura tienen una gran cantidad de significados y casos de uso especiales .
La bandera está
[L]
al final de la expresión anterior. Se pueden usar varias banderas, separadas por una coma. La documentación vinculada describe cada uno, pero aquí están de todos modos:L = último. Deje de procesar RewriteRules una vez que este coincida. ¡El orden cuenta!
C = Cadena. Continúe procesando la próxima RewriteRule. Si esta regla no coincide, la siguiente regla no se ejecutará. Más sobre esto más tarde.
E = Establecer variable ambiental. Apache tiene varias variables ambientales que pueden afectar el comportamiento del servidor web.
F = prohibido. Devuelve un error 403 prohibido si esta regla coincide.
G = ido. Devuelve un error 410-Gone si esta regla coincide.
H = controlador. Obliga a que la solicitud se maneje como si fuera el tipo MIME especificado.
N = Siguiente Obliga a la regla a comenzar de nuevo y volver a coincidir. ¡TEN CUIDADO! Se pueden producir bucles.
NC = Sin caso. Permite
jpg
para que coincida con jpg y JPG.NE = Sin escape. Impide la reescritura de caracteres especiales (.? # Y etc.) en sus equivalentes de código hexadecimal.
NS = Sin subrequests. Si está utilizando el servidor incluye, esto evitará coincidencias con los archivos incluidos.
P = Proxy. Obliga a la regla a ser manejada por mod_proxy. Proporcione contenido de otros servidores de forma transparente, ya que su servidor web lo recupera y lo vuelve a servir. Este es un indicador peligroso, ya que uno mal escrito convertirá su servidor web en un proxy abierto y eso es malo.
PT = Paso a través. Tenga en cuenta las declaraciones de alias en la coincidencia de RewriteRule.
QSA = QSAppend. Cuando la cadena original contiene una consulta ( http://example.com/thing?asp=foo) agrega la cadena de consulta original a la cadena reescrita. Normalmente se descartaría. Importante para contenido dinámico.
R = Redirigir. Proporcione una redirección HTTP a la URL especificada. También puede proporcionar el código de redireccionamiento exacto [R = 303]. Muy similar a
RedirectMatch
, que es más rápido y debe usarse cuando sea posible.S = Saltar. Salta esta regla.
T = Tipo. Especifique el tipo mime del contenido devuelto. Muy similar a la
AddType
directiva.¿Sabes cómo dije que eso se
RewriteCond
aplica a una sola regla? Bueno, puedes evitar eso encadenando.Debido a que la primera RewriteRule tiene el indicador de cadena, la segunda regla de reescritura se ejecutará cuando la primera lo haga, que es cuando la regla anterior RewriteCond coincide. Útil si las expresiones regulares de Apache le duelen el cerebro. Sin embargo, el método todo en una línea que señalo en la primera sección es más rápido desde el punto de vista de la optimización.
Esto se puede simplificar mediante banderas:
Además, algunas banderas también se aplican a RewriteCond. En particular, NoCase.
Coincidirá con "ServerFault.com"
fuente
mod_rewrite
y regex primer. +1.RewriteCond
es realmente transformada después de laRewriteRule
empareje. Es posible que desee decir "más sobre eso más adelante" cerca de la parte superior donde dice "RewriteCond que precede a RewriteRule hace que UNA regla esté sujeta al condicional". Es posible que desee mencionar que las expresiones regulares son expresiones regulares compatibles con Perl. También tiene un apóstrofe extraño en "... la RewriteRule considera que es un inicio de cadena ..."RewriteRule ^/blog/.*/(.*)$ /newblog/$1
no coincide con el primer componente del directorio: las reescrituras son codiciosas por defecto. /.*/(.*) coincide con / 1 / (2) / y / 1/2/3/4/5 / (6) /, por lo que necesita / [^ /] * / para que solo coincida con la PRIMERA ruta componente.Aplazaré la excelente respuesta de sysadmin1138 sobre estos puntos.
Además del orden de sintaxis, la coincidencia de sintaxis / expresiones regulares y los indicadores RewriteRule descritos por sysadmin1138, creo que vale la pena mencionar que mod_rewrite expone variables de entorno de Apache basadas en encabezados de solicitud HTTP y la configuración de Apache.
Recomendaría el tutorial de depuración mod_rewrite de AskApache para obtener una lista completa de las variables que pueden estar disponibles para mod_rewrite.
La mayoría de los problemas con RewriteRule se derivan de un malentendido de la sintaxis PCRE / falla para escapar correctamente caracteres especiales o una falta de conocimiento sobre el contenido de las variables utilizadas para la coincidencia.
Problemas típicos y solución de problemas recomendados:
IfModule
condicional para evitar este escenario), verifique la sintaxis de la directiva, comente las directivas hasta que se identifique el problemaPrimero, mire el contenido de las variables de entorno con las que planea hacer coincidir; si tiene PHP instalado, esto es tan simple como agregar el siguiente bloque a su aplicación:
... luego escriba sus reglas (preferiblemente para probar en un servidor de desarrollo) y observe cualquier coincidencia o actividad inconsistente en su archivo Apache ErrorLog .
Para reglas más complejas, use la
RewriteLog
directiva mod_rewrite para registrar la actividad en un archivo y establecerRewriteLogLevel 3
AllowOverride all
afecta el rendimiento del servidor ya que Apache debe verificar los.htaccess
archivos y analizar las directivas con cada solicitud; si es posible, mantenga todas las directivas en la configuración de VirtualHost para su sitio o habilite las.htaccess
anulaciones solo para los directorios que las necesitan.Las Directrices para webmasters de Google establecen explícitamente: "No engañe a sus usuarios ni presente contenido diferente a los motores de búsqueda que el que muestra a los usuarios, lo que comúnmente se conoce como 'encubrimiento'". Evite crear directivas mod_rewrite que filtren para los robots de los motores de búsqueda.
Los robots de los motores de búsqueda prefieren un contenido 1: 1: mapeo de URI (esta es la base para clasificar los enlaces al contenido): si está utilizando mod_rewrite para crear redireccionamientos temporales o está sirviendo el mismo contenido en múltiples URI, considere especificar un URI canónico dentro sus documentos HTML
Este es un tema enorme (y potencialmente polémico) por derecho propio: mejor (en mi humilde opinión) abordar los usos caso por caso y dejar que quienes preguntan determinen si las resoluciones sugeridas son apropiadas para sus necesidades.
Los trucos y consejos mod_rewrite de AskApache cubren casi todos los casos de uso comunes que aparecen regularmente, sin embargo, la solución "correcta" para un usuario determinado puede depender de la sofisticación de la configuración del usuario y las directivas existentes (por lo que generalmente es un buena idea para ver qué otras directivas tiene un usuario en su lugar cada vez que surge una pregunta mod_rewrite).
fuente
Redirect
o en suRedirectMatch
lugar. Ver también los documentos de Apache: cuándo no usar mod_rewriteAl igual que muchos administradores / desarrolladores, he estado luchando contra las complejidades de las reglas de reescritura durante años y no estoy satisfecho con la documentación existente de Apache, así que decidí, como proyecto personal, llegar al fondo de cómo
mod_rewrite
funciona e interactúa con el resto de Apache. core, así que en los últimos meses he estado instrumentando casos de prueba constrace
+ profundizando en el código fuente para tener una idea de todo esto.Aquí hay algunos comentarios clave que los desarrolladores de reglas de reescritura deben tener en cuenta:
.htaccess
procesamiento PerDir ( ).Me gustaría decir que debido a esto, casi necesita dividir las comunidades de usuarios de reescritura en dos categorías y tratarlas como completamente separadas:
Aquellos con acceso de root a la configuración de Apache . Estos son típicamente admin / desarrollador con un servidor / VM dedicado a la aplicación, y el mensaje aquí es bastante simple: evite usar
.htaccess
archivos si es posible; haga todo en su servidor o configuración de vhost. La depuración es razonablemente fácil ya que el desarrollador puede configurar la depuración y tiene acceso a los archivos rewrite.log.Usuarios de un servicio alojado compartido (SHS) .
.htaccess
procesamiento / Perdir ya que no hay alternativa disponible..htaccess
archivo PerDir está seleccionado y por qué. No explica las complejidades del ciclismo PerDir y cómo evitarlo.Posiblemente haya una tercera comunidad: el personal administrativo y de apoyo en los proveedores de SHS que terminan con un pie en ambos campamentos y tienen que sufrir las consecuencias de lo anterior.
He escrito un par de publicaciones de blog de estilo de artículo (por ejemplo, más sobre el uso de reglas de reescritura en archivos .htaccess ) que cubre muchos puntos detallados que no repetiré aquí para mantener esta publicación breve. Tengo mi propio servicio compartido y también apoyo algunos proyectos dedicados y VM FLOSS. Comencé a usar una máquina virtual LAMP estándar como vehículo de prueba para mi cuenta SHS, pero al final me pareció mejor hacer una máquina virtual espejo adecuada (descrita aquí ).
Sin embargo, en términos de cómo la comunidad de administradores debería apoyar a los
.htaccess
usuarios, creo que necesitamos desarrollar y ofrecer:.htaccess
reglas de reescrituraSugerencias sobre cómo obtener diagnósticos integrados de sus reglas (p. Ej.
[E=VAR:EXPR]
explotar el hecho de queEXPR
expandirá las referencias posteriores ($ N o% N) para que estén disponibles como diagnósticos para el script de destino.Si ordena de forma tópica sus reglas de reescritura utilizando los indicadores [OR], [C], [SKIP] y [L] para que todo el esquema de reescritura funcione sin la necesidad de explotar la redirección interna, puede agregar lo siguiente como regla 1 para evitar todas las molestias de bucle:
fuente
.htaccess
temas y verá. La mayoría de los principiantes se confunden irremediablemente: la mayoría de ellos tienen su primera experiencia de un servicio LAMP y mod_rewrite en un servicio compartido y, por lo tanto, no tienen acceso raíz a las configuraciones del sistema / vhost y tienen que usar el procesamiento por directorio a través de los.htaccess
archivos. Hay diferencias importantes que el principiante tiene que "desangrarse". Me consideraría un usuario avanzado y todavía estoy descubriendo sutilezas. Como ya he dicho, he tenido que usar escaneo de código fuente y escaso para resolver algunos aspectos. No sería necesario. :-(.htaccess
, lo cual es terriblemente frágil, complicado y confuso, incluso para los expertos. Todavía estoy teniendo problemas.Usando rewritemap
Hay muchas cosas que puedes hacer con rewritemaps. Rewritemaps se declara utilizando la directiva Rewritemap, y luego se puede usar tanto en las evaluaciones de RewritCond como en las Subvenciones de RewriteRule.
La sintaxis general para RewriteMap es:
Por ejemplo:
Luego puede usar el nombre del mapa para construcciones como esta:
El mapa contiene pares clave / valor. Si se encuentra la clave, el valor se sustituye. Los mapas simples son solo archivos de texto sin formato, pero puede usar mapas hash e incluso consultas SQL. Más detalles están en los documentos:
http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewritemap
Cuerdas sin escapes.
Hay cuatro mapas internos que puede usar para hacer algunas manipulaciones. Especialmente las cadenas sin escapes pueden ser útiles.
Por ejemplo: quiero probar la cadena "café" en la cadena de consulta. Sin embargo, el navegador escapará de esto antes de enviarlo a mi servidor, por lo que tendré que averiguar cuál es la versión de escape de URL para cada cadena que deseo hacer coincidir, o simplemente puedo dejar de escapar ...
Observe cómo uso un RewriteCond para capturar el argumento del parámetro de la cadena de consulta y luego uso el mapa en el segundo rewriteCond para dejarlo de lado. Esto luego se compara. También tenga en cuenta cómo necesito para nosotros% 2 como clave en el rewritemap, ya que% 1 contendrá "ubicación" o "lugar". Cuando usa paréntesis para agrupar patrones, también se capturarán, ya sea que planee usar el resultado de la captura o no ...
fuente
mod_rewrite
motor regexp admite grupos que no son de captura, por ejemplo,(?:location|place)
y esto solo tendrá una captura en el ejemplo.Una trampa realmente fácil es cuando reescribes URL que alteran la ruta aparente, por ejemplo, de
/base/1234/index.html
a/base/script.php?id=1234
. El cliente no encontrará ninguna imagen o CSS con rutas relativas a la ubicación del script. Se pueden encontrar varias opciones para resolver esto en este faq .fuente
<base>
etiqueta es más fácil de seguir y aún así habilitar rutas relativas.