Redireccionar, cambiar URL o redirigir HTTP a HTTPS en Apache: todo lo que siempre quiso saber sobre las reglas Mod_Rewrite, pero tenía miedo de preguntar

264

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.

Kyle Brandt
fuente
99
La idea detrás de esta pregunta es dar un camino cercano para todas las interminables preguntas mod_rewrite que vuelven locos a nuestros usuarios más habituales. Esto es muy similar a lo que se hizo con subredes en serverfault.com/questions/49765/how-does-subnetting-work .
Kyle Brandt
1
Además, realmente no quiero demasiados votos a favor sobre esta pregunta , sino que deberían ir a la respuesta. No quiero CW esto porque quiero asegurarme de que el póster reciba el crédito completo por lo que espero sea la respuesta mod_rewrite para finalizar todas las preguntas mod_rewrite .
Kyle Brandt
44
Lo siento, voté por la pregunta. ;-) Realmente creo que debe aparecer en (o cerca) en la parte superior de las mod-rewritebúsquedas / filtros de etiquetas.
Steven lunes
Alguien más (tm) debería manejar los casos de uso comunes. No los conozco lo suficiente como para hacerle justicia.
sysadmin1138
Quizás esta pregunta debería estar vinculada a la wiki mod-rewrite tag para acortar aún más la ruta.
beldaz

Respuestas:

224

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 Ondirectiva debe ser dada ya que esto activa el procesamiento mod_rewrite. Esto debería ser antes de cualquier otra directiva de reescritura.

RewriteCondel precedente RewriteRulehace que UNA regla esté sujeta al condicional. Las siguientes RewriteRules se procesarán como si no estuvieran sujetas a condicionales.

RewriteEngine On
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule $/blog/(.*)\.html        $/blog/$1.sf.html

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:

RewriteEngine On
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule $/blog/(.*)\.html        $/blog/$1.sf.html
RewriteRule $/blog/(.*)\.jpg         $/blog/$1.sf.jpg

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:

RewriteEngine On
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.html        /blog/$1.sf.html
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.jpg         /blog/$1.sf.jpg

Pero probablemente debería hacerse con una sintaxis de reemplazo más complicada.

RewriteEngine On
RewriteCond %{HTTP_REFERER}                ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.(html|jpg)        /blog/$1.sf.$2

El RewriteRule más complejo contiene los condicionales para el procesamiento. El último paréntesis, (html|jpg)le dice a RewriteRule que coincida con uno htmlo jpg, 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):

RewriteEngine On
RewriteCond %{HTTP_REFERER}                ^https?://serverfault\.com(/|$)    [OR]
RewriteCond %{HTTP_REFERER}                ^https?://superuser\.com(/|$)
RewriteRule ^/blog/(.*)\.(html|jpg)        /blog/$1.sf.$2

Para servir páginas referidas por ServerFault con navegadores Chrome (Y implícito):

RewriteEngine On
RewriteCond %{HTTP_REFERER}                ^https?://serverfault\.com(/|$)
RewriteCond %{HTTP_USER_AGENT}             ^Mozilla.*Chrome.*$
RewriteRule ^/blog/(.*)\.(html|jpg)        /blog/$1.sf.$2

RewriteBasetambién es específico de la orden, ya que especifica cómo las siguientes RewriteRuledirectivas 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:

RewriteEngine On
RewriteBase /blog
RewriteCond %{HTTP_REFERER}           ^https?://serverfault\.com(/|$)
RewriteRule ^(.*)\.(html|jpg)         $1.sf.$2

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

RewriteEngine On

##Example 1: No RewriteBase##
RewriteCond %{HTTP_REFERER}                                   ^https?://serverfault\.com(/|$)
RewriteRule /home/assdr/public_html/blog/(.*)\.(html|jpg)     $1.sf.$2

##Example 2: With RewriteBase##
RewriteBase /blog
RewriteCond %{HTTP_REFERER}           ^https?://serverfault\.com(/|$)
RewriteRule ^(.*)\.(html|jpg)         $1.sf.$2

Como puede ver, RewriteBasepermite 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.

RewriteRule ^/blog/(.*)$    /newblog/$1

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.

RewriteRule ^/blog/.*/(.*)$  /newblog/$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).

RewriteRule ^/blog/(2008|2009)/(.*)$   /newblog/$2

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.

RewriteRule ^/blog/(2008|2009)/(.*)$   /newblog/$1/$2

En este caso, usamos $ 1 en la cadena reescrita.

RewriteRule ^/blog/(20[0-9][0-9])/(.*)$   /newblog/$1/$2

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.

RewriteRule ^/blog/(20[0-9]{2})/(.*)$  /newblog/$1/$2

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.

RewriteRule ^/blog/([0-9]{4})/([a-z]*)\.html   /newblog/$1/$2.shtml

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.

RewriteRule ^/blog/([0-9]{4})/([-a-z]*)\.html  /newblog/$1/$2.shtml

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.

RewriteRule ^/blog/([0-9]{4})/([-0-9a-zA-Z]*)\.html   /newblog/$1/$2.shtml

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 .

RewriteRule ^/blog/([0-9]{4})/([-a-z]*).\html  /newblog/$1/$2.shtml  [L]

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

¿Sabes cómo dije que eso se RewriteCondaplica a una sola regla? Bueno, puedes evitar eso encadenando.

RewriteEngine On
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.html        /blog/$1.sf.html     [C]
RewriteRule ^/blog/(.*)\.jpg         /blog/$1.sf.jpg

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.

RewriteRule ^/blog/([0-9]{4})/([-0-9a-zA-Z]*)\.html   /newblog/$1/$2.shtml

Esto se puede simplificar mediante banderas:

RewriteRule ^/blog/([0-9]{4})/([-0-9a-z]*)\.html   /newblog/$1/$2.shtml   [NC]

Además, algunas banderas también se aplican a RewriteCond. En particular, NoCase.

RewriteCond %{HTTP_REFERER}        ^https?://serverfault\.com(/|$)     [NC]

Coincidirá con "ServerFault.com"

sysadmin1138
fuente
99
Bien hecho. [relleno]
EEAA
3
Muy bonito mod_rewritey regex primer. +1.
Steven lunes
3
A veces es útil saber que el RewriteCondes realmente transformada después de la RewriteRuleempareje. 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 ..."
Dennis Williamson
2
RewriteRule ^/blog/.*/(.*)$ /newblog/$1no 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.
Adaptr
1
@ sysadmin1138, creo que esta respuesta es buena, pero puede ser mejor si elaboras más sobre las banderas E, N, NS, P, PT y S con ejemplos porque esas banderas no son obvias sobre cómo funcionan, etc.
Pacerier
39

¿Cuál es el formato y la estructura fundamentales de las reglas mod_rewrite?

Aplazaré la excelente respuesta de sysadmin1138 sobre estos puntos.

¿De qué forma / sabor de las expresiones regulares necesito tener una comprensión sólida?

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.

¿Cuáles son los errores / dificultades más comunes al escribir reglas de reescritura?

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:

  • 500 - Error interno del servidor - Elimine los controles de carro de Windows en los archivos de configuración si están presentes, asegúrese de que mod_rewrite esté habilitado (ajuste las directivas en IfModulecondicional para evitar este escenario), verifique la sintaxis de la directiva, comente las directivas hasta que se identifique el problema
  • Redirigir bucle : utilice RewriteLog y RewriteLogLevel, comente las directivas hasta que se identifique el problema

¿Cuál es un buen método para probar y verificar las reglas mod_rewrite?

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

<?php
  var_dump($_SERVER);
?>

... 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 RewriteLogdirectiva mod_rewrite para registrar la actividad en un archivo y establecerRewriteLogLevel 3

¿Hay implicaciones de SEO o rendimiento de las reglas mod_rewrite que debo tener en cuenta?

AllowOverride allafecta el rendimiento del servidor ya que Apache debe verificar los .htaccessarchivos 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 .htaccessanulaciones 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

¿Hay situaciones comunes en las que mod_rewrite puede parecer la herramienta adecuada para el trabajo pero no lo es?

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.

¿Cuáles son algunos ejemplos comunes?

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

danlefree
fuente
Gracias por el enlace AskApache. ¡Es lo que estaba buscando!
sica07
El payaso AskApache no está oficialmente respaldado por la ASF. Gran parte de lo que dice es discutible o simplemente incorrecto.
Adaptr
@adaptr Por favor, comparta los recursos superiores que aparentemente conoce.
danlefree
"¿situaciones comunes en las que mod_rewrite puede parecer la herramienta adecuada para el trabajo pero no lo es?" - redireccionamientos simples , donde mod_rewrite aún no se está utilizando. Use mod_alias Redirecto en su RedirectMatchlugar. Ver también los documentos de Apache: cuándo no usar mod_rewrite
MrWhite
21

Al 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_rewritefunciona e interactúa con el resto de Apache. core, así que en los últimos meses he estado instrumentando casos de prueba con strace+ 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:

  • Sin embargo, algunos aspectos de la reescritura son comunes a la configuración del servidor, host virtual, directorio y procesamiento de .htaccess
  • Algunos procesos son muy diferentes para la configuración raíz (configuración del servidor, host virtual y directorio) en comparación con el .htaccessprocesamiento PerDir ( ).
  • Peor aún porque el procesamiento PerDir puede desencadenar casi indiscriminadamente el ciclo de REDIRECCIÓN INTERNA, los elementos de configuración raíz deben escribirse conscientes de que dicho procesamiento PerDir puede desencadenar esto.

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

    • Dichos usuarios tienen que usar el .htaccessprocesamiento / Perdir ya que no hay alternativa disponible.
    • Peor aún, el nivel de habilidad de dichos usuarios (en lo que respecta al uso de la lógica de escalera impulsada por regexp de mod_rewrite) es generalmente significativamente menor que los administradores experimentados.
    • Apache y los proveedores de hosting no ofrecen soporte de depuración / diagnóstico. La única información de diagnóstico es una redirección exitosa, una redirección al URI incorrecto. o un código de estado 404/500. Esto los deja confundidos e indefensos.
    • Apache es extremadamente débil al explicar cómo funciona la reescritura para este caso de uso. Por ejemplo, no proporciona una explicación clara de qué .htaccessarchivo 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 .htaccessusuarios, creo que necesitamos desarrollar y ofrecer:

  • Una descripción coherente de cómo funciona realmente el sistema de reescritura en el procesamiento PerDir
  • Un conjunto de pautas / mejores prácticas sobre cómo escribir .htaccessreglas de reescritura
  • Un simple analizador de guiones de reescritura basado en la web similar a los analizadores html W3C, pero mediante el cual los usuarios pueden ingresar URI de prueba o vectores de prueba del mismo y obtener un registro inmediato del flujo lógico de reescritura /
  • Sugerencias sobre cómo obtener diagnósticos integrados de sus reglas (p. Ej.

    • Utilice [E=VAR:EXPR]explotar el hecho de que EXPRexpandirá 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:

      RewriteCond %{ENV:REDIRECT_STATUS} !=""
      RewriteRule .  -  [L]
      
TerryE
fuente
Esto está bien documentado. ¿Por qué dice que la documentación no explica esto?
Adaptr
2
Todo lo que tiene que hacer es suscribirse a los .htaccesstemas 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 .htaccessarchivos. 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. :-(
TerryE
Estoy totalmente de acuerdo. "Necesitamos dividir las comunidades de usuarios de reescritura en dos categorías y tratarlas como algo completamente separado". Algunos usuarios están utilizando alojamiento compartido y necesitan confiar .htaccess, lo cual es terriblemente frágil, complicado y confuso, incluso para los expertos. Todavía estoy teniendo problemas.
Ryan
15

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:

RewriteMap MapName MapType:MapSource

Por ejemplo:

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

Luego puede usar el nombre del mapa para construcciones como esta:

${examplemap:key}

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

RewriteMap unescape int:unescape

RewriteCond %{QUERY_STRING}  (location|place)=(.*)
RewriteCond ${unescape:%2}   café
RewriteRule ^/find/$         /find/1234? [L,R]

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

Krist van Besien
fuente
La última oración no es del todo cierta. El mod_rewritemotor regexp admite grupos que no son de captura, por ejemplo, (?:location|place)y esto solo tendrá una captura en el ejemplo.
TerryE
12

¿Cuáles son los errores / dificultades más comunes al escribir reglas de reescritura?

Una trampa realmente fácil es cuando reescribes URL que alteran la ruta aparente, por ejemplo, de /base/1234/index.htmla /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 .

beldaz
fuente
1
Gracias por el enlace. Particularmente cuando trabajo con otros miembros del equipo que no están familiarizados con la reescritura, encuentro que agregar una <base>etiqueta es más fácil de seguir y aún así habilitar rutas relativas.
kontur