rewriterule mod_rewrite ifmodule htaccess ejemplos apache .htaccess mod-rewrite

apache - ifmodule - mod_rewrite htaccess



Consejos para depurar reglas de reescritura.htaccess (14)

Muchos carteles tienen problemas para depurar sus declaraciones RewriteRule y RewriteCond dentro de sus archivos .htaccess . La mayoría de estos utilizan un servicio de alojamiento compartido y, por lo tanto, no tienen acceso a la configuración del servidor raíz. No pueden evitar el uso de archivos .htaccess para la reescritura y no pueden habilitar un RewriteLogLevel ", como sugieren muchos encuestados. También hay muchos errores y limitaciones específicas de .htaccess no se cubren bien. La configuración de una pila de LAMP de prueba local implica demasiado curva de aprendizaje para la mayoría.

Así que mi Q aquí es cómo recomendaríamos que depuren sus reglas ellos mismos . Proporciono algunas sugerencias a continuación. Otras sugerencias serían apreciadas.

  1. Comprenda que el motor mod_rewrite recorre los archivos .htaccess . El motor ejecuta este bucle:

    do execute server and vhost rewrites (in the Apache Virtual Host Config) find the lowest "Per Dir" .htaccess file on the file path with rewrites enabled if found(.htaccess) execute .htaccess rewrites (in the user''s directory) while rewrite occurred

    Por lo tanto, sus reglas se ejecutarán repetidamente y si cambia la ruta de URI, entonces puede terminar ejecutando otros archivos .htaccess si existen. Así que asegúrese de terminar este bucle, si es necesario, agregando RewriteCond adicional para detener el encendido de las reglas. También elimine cualquier conjunto de reglas de reescritura .htaccess nivel inferior a menos que intente explícitamente usar conjuntos de reglas de múltiples niveles.

  2. Asegúrese de que la sintaxis de cada Regexp sea correcta al realizar pruebas contra un conjunto de patrones de prueba para asegurarse de que sea una sintaxis válida y haga lo que pretende con un rango completo de URI de prueba. Vea la respuesta a continuación para más detalles.

  3. Construye tus reglas de forma incremental en un directorio de prueba. Puede usar "ejecutar el archivo .htaccess más profundo en la función de la ruta" para configurar un directorio de prueba (árbol) por separado y depurar los conjuntos de reglas aquí sin arruinar sus reglas principales y dejar de funcionar su sitio. Debe agregarlos uno por uno, ya que esta es la única manera de localizar fallas en reglas individuales.

  4. Utilice un código auxiliar de prueba ficticio para volcar las variables de entorno y servidor . (Consulte el Listado 2 ) Si su aplicación usa, digamos, blog/index.php entonces puede copiar esto en test/blog/index.php y usarlo para probar las reglas de su blog en el subdirectorio de test . También puede usar variables de entorno para asegurarse de que el motor de reescritura interpreta correctamente las cadenas de sustitución, por ejemplo

    RewriteRule ^(.*) - [E=TEST0:%{DOCUMENT_ROOT}/blog/html_cache/$1.html]

    y busque estas variables REDIRECT_ * en el volcado phpinfo. Por cierto, utilicé este y descubrí en mi sitio que tenía que usar %{ENV:DOCUMENT_ROOT_REAL} lugar. En el caso de redireccionamiento en bucle, las variables REDIRECT_REDIRECT_ * listan el pase anterior. Etc.

  5. Asegúrese de no ser mordido por el navegador que almacena en caché las redirecciones 301 incorrectas . Ver respuesta a continuación . Mi agradecimiento a Ulrich Palha por esto.

  6. El motor de reescritura parece ser sensible a las reglas en cascada dentro de un contexto .htaccess , (es decir, cuando RewriteRule produce una sustitución y esto se RewriteRule a otras reglas), ya que encontré errores con las solicitudes internas (1) y el procesamiento incorrecto de PATH_INFO. que a menudo se puede evitar mediante el uso de las banderas [NS], [L] y [PT].

¿Algún comentario o sugerencia más?

Listado 1 - phpinfo

<?php phpinfo(INFO_ENVIRONMENT|INFO_VARIABLES);


Asegúrese de que la sintaxis de cada Regexp es correcta

realizando pruebas contra un conjunto de patrones de prueba para asegurarse de que sea una sintaxis válida y que cumpla con su objetivo con un rango completo de URI de prueba.

Vea regexpCheck.php a continuación para ver un script simple que puede agregar a un directorio privado / de prueba en su sitio para ayudarlo a hacer esto. He mantenido esto breve en lugar de bonito. Simplemente regexpCheck.php esto a un archivo regexpCheck.php en un directorio de prueba para usarlo en su sitio web. Esto le ayudará a construir cualquier expresión regular y a probarla en una lista de casos de prueba a medida que lo haga. Estoy usando el motor PHP PCRE aquí, pero después de haber visto la fuente de Apache, esto es básicamente idéntico al utilizado en Apache. Hay muchos HowTos y tutoriales que proporcionan plantillas y pueden ayudarlo a desarrollar sus habilidades de expresión regular.

Listado 1 - regexpCheck.php

<html><head><title>Regexp checker</title></head><body> <?php $a_pattern= isset($_POST[''pattern'']) ? $_POST[''pattern''] : ""; $a_ntests = isset($_POST[''ntests'']) ? $_POST[''ntests''] : 1; $a_test = isset($_POST[''test'']) ? $_POST[''test''] : array(); $res = array(); $maxM=-1; foreach($a_test as $t ){ $rtn = @preg_match(''#''.$a_pattern.''#'',$t,$m); if($rtn == 1){ $maxM=max($maxM,count($m)); $res[]=array_merge( array(''matched''), $m ); } else { $res[]=array(($rtn === FALSE ? ''invalid'' : ''non-matched'')); } } ?> <p>&nbsp; </p> <form method="post" action="<?php echo $_SERVER[''SCRIPT_NAME''];?>"> <label for="pl">Regexp Pattern: </label> <input id="p" name="pattern" size="50" value="<?php echo htmlentities($a_pattern,ENT_QUOTES,"UTF-8");;?>" /> <label for="n">&nbsp; &nbsp; Number of test vectors: </label> <input id="n" name="ntests" size="3" value="<?php echo $a_ntests;?>"/> <input type="submit" name="go" value="OK"/><hr/><p>&nbsp;</p> <table><thead><tr><td><b>Test Vector</b></td><td>&nbsp; &nbsp; <b>Result</b></td> <?php for ( $i=0; $i<$maxM; $i++ ) echo "<td>&nbsp; &nbsp; <b>/$$i</b></td>"; echo "</tr><tbody>/n"; for( $i=0; $i<$a_ntests; $i++ ){ echo ''<tr><td>&nbsp;<input name="test[]" value="'', htmlentities($a_test[$i], ENT_QUOTES,"UTF-8"),''" /></td>''; foreach ($res[$i] as $v) { echo ''<td>&nbsp; &nbsp; '',htmlentities($v, ENT_QUOTES,"UTF-8"),''&nbsp; &nbsp; </td>'';} echo "</tr>/n"; } ?> </table></form></body></html>


Prueba de reescritura .htaccess en línea

Encontré this ayuda de Google GoBlog para RegEx, me ahorró mucho tiempo al tener que cargar nuevos archivos .htaccess cada vez que hago una pequeña modificación.

desde el sitio:

probador htaccess

Para probar sus reglas de reescritura de htaccess, simplemente complete la url a la que está aplicando las reglas, coloque el contenido de su htaccess en el área de entrada más grande y presione el botón "Comprobar ahora".


Establece variables de entorno y usa encabezados para recibirlas:

Puede crear nuevas variables de entorno con líneas RewriteRule, como lo menciona OP:

RewriteRule ^(.*) - [E=TEST0:%{DOCUMENT_ROOT}/blog/html_cache/$1.html]

Pero si no puede hacer que funcione un script del lado del servidor, ¿cómo puede leer esta variable de entorno? Una solución es establecer un encabezado:

Header set TEST_FOOBAR "%{REDIRECT_TEST0}e"

El valor acepta especificadores de formato , incluido el especificador %{NAME}e para las variables de entorno (no olvide la minúscula e). A veces, tendrá que agregar el prefijo REDIRECT_ , pero no he averiguado cuándo se agrega el prefijo y cuándo no.


(Similar a la idea de Doin) Para mostrar lo que se está comparando, utilizo este código

$keys = array_keys($_GET); foreach($keys as $i=>$key){ echo "$i => $key <br>"; }

Guárdelo en r.php en la raíz del servidor y luego haga algunas pruebas en .htaccess
Por ejemplo, quiero hacer coincidir las direcciones URL que no comienzan con un prefijo de idioma

RewriteRule ^(?!(en|de)/)(.*)$ /r.php?$1&$2 [L] #$1&$2&... RewriteRule ^(.*)$ /r.php?nomatch [L] #report nomatch and exit


Algunos errores que observé pasan al escribir .htaccess

El uso de ^(.*)$ Repetidamente en varias reglas, el uso de ^(.*)$ Hace que otras reglas sean impotentes en la mayoría de los casos, ya que coincide con toda la URL en un solo golpe.

Entonces, si estamos usando la regla para este url sapmle/url , también consumirá este url sapmle/url/string .

[L] bandera [L] debe usarse para asegurar que nuestra regla haya terminado de procesarse.

Debe saber sobre:

Diferencia en% n y $ n

%n coincide durante la parte %{RewriteCond} y $n coincide con la parte %{RewriteRule} .

Trabajo de RewriteBase

La directiva RewriteBase especifica el prefijo de URL que se usará para las directivas RewriteRule por directorio (htaccess) que sustituyen una ruta relativa.

Esta directiva es necesaria cuando utiliza una ruta relativa en una sustitución en el contexto de directorio (htaccess) a menos que se cumpla alguna de las siguientes condiciones:

La solicitud original, y la sustitución, están debajo de DocumentRoot (en lugar de ser accesibles por otros medios, como Alias). La ruta del sistema de archivos al directorio que contiene la RewriteRule, con el sufijo de la sustitución relativa, también es válida como una ruta URL en el servidor (esto es raro). En el servidor HTTP Apache 2.4.16 y posterior, esta directiva se puede omitir cuando la solicitud se asigna a través de Alias ​​o mod_userdir.


Aquí hay algunos consejos adicionales sobre reglas de prueba que pueden facilitar la depuración para los usuarios en alojamiento compartido

1. Utilice un agente de usuario falso

Al probar una nueva regla, agregue una condición para ejecutarla solo con un agente de usuario fake que utilizará para sus solicitudes. De esta manera no afectará a nadie más en su sitio.

p.ej

#protect with a fake user agent RewriteCond %{HTTP_USER_AGENT} ^my-fake-user-agent$ #Here is the actual rule I am testing RewriteCond %{HTTP_HOST} !^www/.domain/.com$ [NC] RewriteRule ^ http://www.domain.com%{REQUEST_URI} [L,R=302]

Si está utilizando Firefox, puede usar el Conmutador de agente de usuario para crear la cadena y la prueba del agente de usuario falso.

2. No use 301 hasta que haya terminado la prueba

He visto tantas publicaciones donde las personas aún están probando sus reglas y están usando 301''s. No lo hagas

Si no está utilizando la sugerencia 1 en su sitio, no solo usted, sino todos los que visiten su sitio en ese momento se verán afectados por el 301.

Recuerde que son permanentes y que su navegador almacena en caché de manera agresiva. Use un 302 en su lugar hasta que esté seguro, luego cámbielo a un 301.

3. Recuerde que los 301 se almacenan en caché agresivamente en su navegador

Si su regla no funciona y le parece correcta, y no estaba utilizando las sugerencias 1 y 2, vuelva a realizar la prueba después de borrar la memoria caché de su navegador o durante la navegación privada.

4. Usa una herramienta de captura de HTTP

Use una herramienta de captura HTTP como Fiddler para ver el tráfico HTTP real entre su navegador y el servidor.

Mientras que otros podrían decir que su site does not look right , en su lugar podría ver e informar que all of the images, css and js are returning 404 errors , lo que reduce rápidamente el problema.

Mientras que otros informarán que started at URL A and ended at URL C , podrá ver que comenzaron en la URL A, were 302 redirected to URL B and 301 redirected to URL C Incluso si la URL C era el objetivo final, sabrá que esto es malo para SEO y debe ser corregido.

Podrá ver los encabezados de caché que se configuraron en el lado del servidor, reproducir las solicitudes, modificar los encabezados de las solicitudes para probar ...


Con respecto a 4., aún debe asegurarse de que su "talón de script ficticio" sea realmente la URL de destino después de que haya terminado la reescritura, ¡o no verá nada!

Un truco similar / relacionado (vea esta pregunta ) es insertar una regla temporal como:

RewriteRule (.*) /show.php?url=$1 [END]

Donde show.php es un script muy simple que solo muestra sus parámetros $_GET (también puede mostrar variables de entorno, si lo desea).

Esto detendrá la reescritura en el punto en que lo inserte en el conjunto de reglas, más bien como un punto de interrupción en un depurador.

Si está utilizando Apache <2.3.9, deberá usar [L] lugar de [END] , y luego deberá agregar:

RewriteRule ^show.php$ - [L]

En la parte superior de su conjunto de reglas, si la URL /show.php se está reescribiendo.


Dejaré esto aquí, tal vez con detalles obvios, pero me golpeé la cabeza durante horas: tenga cuidado al usar %{REQUEST_URI} porque lo que @Krist van Besien dice en su respuesta es totalmente correcto, pero no para la cadena REQUEST_URI , porque fuera de este TestString comienza con un / . Así que ten cuidado:

RewriteCond %{REQUEST_URI} ^/assets/$ ^ | check this pesky fella right here if missing


Encontré esta pregunta al intentar depurar mis problemas de mod_rewrite, y definitivamente tiene algunos consejos útiles. Pero al final, lo más importante es asegurarse de que la sintaxis de expresiones regulares sea correcta. Debido a problemas con mi propia sintaxis de RE, la instalación del script regexpCheck.php no era una opción viable.

Pero como Apache usa expresiones regulares compatibles con Perl (PCRE), cualquier herramienta que ayude a escribir PCRE debería ayudar. He usado la herramienta RegexPlanet con Java y Javascript RE en el pasado, y me alegró descubrir que también soportan Perl.

Simplemente escriba su expresión regular y una o más URL de ejemplo, y le dirá si las expresiones regulares coinciden (un "1" en la columna "~ =") y, si corresponde, cualquier grupo coincidente (los números en la "división" La columna corresponderá a los números que Apache espera (por ejemplo, $ 1, $ 2, etc.) para cada URL. Afirman que el soporte de PCRE está "en beta", pero era justo lo que necesitaba para resolver mis problemas de sintaxis.

http://www.regexplanet.com/advanced/perl/index.html

Simplemente habría agregado un comentario a una respuesta existente, pero mi reputación aún no está en ese nivel. Espero que esto ayude a alguien.


Si está creando redirecciones, pruebe con curl para evitar problemas de almacenamiento en caché del navegador. Utilice -I para obtener los encabezados http solamente. Usa -L para seguir todas las redirecciones.


Si planea escribir más de una línea de reglas en .htacesss,
ni siquiera pienses en probar uno de esos métodos de corrección para depurarlo.

He perdido días en establecer múltiples reglas sin comentarios de los REGISTROS, solo para finalmente renunciar a una.
Conseguí Apache en mi PC, copié todo el sitio a HDD y ordené que todo el conjunto de reglas se resolviera usando registros muy rápido.
Luego revisé mis viejas reglas que funcionaban, vi que realmente no están haciendo lo que se deseaba. Una bomba de tiempo para una dirección un poco diferente.

Hay tantas caídas en boxes en las reglas de reescritura, no es una lógica directa.
Puede poner a Apache en funcionamiento en diez minutos, tiene 10 MB, buena licencia, * listo para NIX / WIN / MAC, incluso sin instalación.
Además, verifique las líneas de encabezado de su servidor y obtenga la misma versión de Apache del archivo si es antiguo. Mi OP todavía está en 2.0, muchas cosas no son compatibles.


Una de un par de horas que desperdicié:

Si ha aplicado todos estos consejos y solo se están cometiendo 500 errores porque no tiene acceso al registro de errores del servidor, tal vez el problema no esté en el archivo .htaccess sino en los archivos a los que se redirige.

Después de haber solucionado mi problema con .htaccess, pasé dos horas más tratando de arreglarlo un poco más, a pesar de que simplemente me había olvidado de algunos permisos.


Asegúrese de usar el signo de porcentaje delante de las variables, no el signo de dólar.

Es %{HTTP_HOST} , no ${HTTP_HOST} . No habrá nada en el error_log, no habrá errores internos del servidor, su expresión regular sigue siendo correcta, la regla simplemente no coincidirá. Esto es realmente horrible si trabajas mucho con las plantillas de django / genshi y tienes ${} para la sustitución de variables en la memoria muscular.


No olvide que en los archivos .htaccess es una URL relativa que coincide.

En un archivo .htaccess, la siguiente RewriteRule nunca coincidirá:

RewriteRule ^/(.*) /something/$s