apache rewriterule - Suggerimenti per il debug delle regole di riscrittura.htaccess




header external (13)

Molti poster hanno problemi nel debug delle loro istruzioni RewriteRule e RewriteCond all'interno dei loro file .htaccess . La maggior parte di questi utilizza un servizio di hosting condiviso e pertanto non ha accesso alla configurazione del root server. Non possono evitare di usare i file .htaccess per riscrivere e non possono abilitare un RewriteLogLevel "come suggeriscono molti rispondenti.Inoltre ci sono molti errori e i vincoli specifici di .htaccess non sono coperti bene.Impostazione di un test locale Lo stack della LAMP implica troppo di un curva di apprendimento per la maggior parte.

Quindi la mia Q qui è come raccomanderemmo di eseguire il debug delle loro regole da soli . Fornisco alcuni suggerimenti di seguito. Altri suggerimenti sarebbero apprezzati.

  1. Comprendere che il motore mod_rewrite passa attraverso i file .htaccess . Il motore esegue questo ciclo:

    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
    

    Quindi le tue regole verranno eseguite ripetutamente e se cambi il percorso URI allora potrebbe finire per eseguire altri file .htaccess se esistono. Assicurati quindi di terminare questo ciclo, se necessario aggiungendo RewriteCond aggiuntivo per interrompere l' RewriteCond delle regole. Elimina anche qualsiasi livello inferiore .htaccess riscrivi i set di regole a meno che non intenda esplicitamente utilizzare set di regole multilivello.

  2. Assicurati che la sintassi di ogni Regexp sia corretta testando un insieme di pattern di test per assicurarti che sia una sintassi valida e fai ciò che intendi con una gamma completa di URI di test. Vedi la risposta sotto per maggiori dettagli.

  3. Costruisci le tue regole in modo incrementale in una directory di test. Puoi utilizzare "esegui il file .htaccess più profondo sulla funzione del percorso" per impostare una directory di test separata (albero) ed eseguire il debug di set di regole senza rovinare le regole principali e interrompere il funzionamento del tuo sito. Devi aggiungerli uno alla volta perché questo è l'unico modo per localizzare i fallimenti alle singole regole.

  4. Utilizzare uno stub di script fittizio per scaricare le variabili del server e dell'ambiente . (Vedi Listato 2 ) Se la tua app usa, ad esempio, blog/index.php , puoi copiarlo in test/blog/index.php e usarlo per testare le regole del tuo blog nella sottodirectory di test . È anche possibile utilizzare le variabili di ambiente per assicurarsi che il motore di riscrittura interpreti correttamente le stringhe di sostituzione, ad es

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

    e cerca queste variabili REDIRECT_ * nel dump di phpinfo. A proposito, ho usato questo e ho scoperto sul mio sito che dovevo usare %{ENV:DOCUMENT_ROOT_REAL} . Nel caso del ciclo di redirector REDIRECT_REDIRECT_ * le variabili elencano il passaggio precedente. Eccetera..

  5. Assicurati di non essere morso dal browser che memorizza nella cache i reindirizzamenti 301 errati . Vedi la risposta qui sotto . Grazie a Ulrich Palha per questo.

  6. Il motore di riscrittura sembra sensibile alle regole in cascata all'interno di un contesto .htaccess , (è dove un RewriteRule traduce in una sostituzione e questo cade però con ulteriori regole), come ho trovato bug con sotto-richieste interne (1) , e l'elaborazione PATH_INFO non corretta che spesso può essere impedito dall'uso dei flag [NS], [L] e [PT].

Altri commenti o suggerimenti?

Listato 1 - phpinfo

<?php phpinfo(INFO_ENVIRONMENT|INFO_VARIABLES);

Answers

Non dimenticare che nei file .htaccess è un URL relativo che è abbinato.

In un file .htaccess, la seguente RewriteRule non corrisponderà mai:

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

Ho trovato questa domanda durante il tentativo di eseguire il debug dei miei problemi mod_rewrite, e ha sicuramente qualche consiglio utile. Ma alla fine la cosa più importante è assicurarsi di avere la sintassi della regex corretta. A causa di problemi con la mia sintassi RE, l'installazione dello script regexpCheck.php non era un'opzione valida.

Ma poiché Apache utilizza le espressioni regolari compatibili con Perl (PCRE), qualsiasi strumento che aiuti a scrivere i PCRE dovrebbe aiutare. Ho usato lo strumento di RegexPlanet con Java e Javascript RE in passato, ed ero felice di scoprire che supporta anche Perl.

Basta digitare la tua espressione regolare e uno o più URL di esempio, e ti dirà se la regex corrisponde (un "1" nella colonna "~ =") e se applicabile, qualsiasi gruppo corrispondente (i numeri nella "divisione") la colonna corrisponderà ai numeri che Apache si aspetta, ad es. $ 1, $ 2 ecc.) per ogni URL. Sostengono che il supporto PCRE è "in beta", ma era proprio quello di cui avevo bisogno per risolvere i miei problemi di sintassi.

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

Avrei semplicemente aggiunto un commento a una risposta esistente ma la mia reputazione non è ancora a quel livello. Spero che questo aiuti qualcuno.


(Simile all'idea di Doin) Per mostrare ciò che viene abbinato, io uso questo codice

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

Salvalo in r.php sulla root del server e poi esegui alcuni test in .htaccess
Ad esempio, voglio associare URL che non iniziano con un prefisso di lingua

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

Ecco alcuni suggerimenti aggiuntivi sulle regole di test che possono facilitare il debug degli utenti su hosting condiviso

1. Utilizzare un agente utente falso

Quando si verifica una nuova regola, aggiungere una condizione per eseguirla solo con un fake user-agent che verrà utilizzato per le richieste. In questo modo non influenzerà nessun altro sul tuo sito.

per esempio

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

Se si utilizza Firefox, è possibile utilizzare lo User Agent Switcher per creare la stringa e il test dell'agente utente falso.

2. Non usare 301 fino a quando non si è fatto il test

Ho visto così tanti post in cui le persone stanno ancora testando le loro regole e usano 301. NON .

Se non stai utilizzando il suggerimento 1 sul tuo sito, non solo tu, ma chiunque visiti il ​​tuo sito al momento sarà interessato dal 301.

Ricorda che sono permanenti e in modo aggressivo nella cache del tuo browser. Usa invece un 302 fino a quando non sei sicuro, quindi cambialo in 301.

3. Ricorda che i 301 sono aggressivamente memorizzati nella cache del tuo browser

Se la tua regola non funziona e sembra giusta per te, e non stavi usando i suggerimenti 1 e 2, esegui nuovamente il test dopo aver svuotato la cache del browser o durante la navigazione privata.

4. Utilizzare uno strumento Capture HTTP

Utilizza uno strumento di acquisizione HTTP come Fiddler per vedere il traffico HTTP effettivo tra il tuo browser e il server.

Mentre altri potrebbero dire che il tuo site does not look right , puoi invece vedere e segnalare che all of the images, css and js are returning 404 errors , restringendo rapidamente il problema.

Mentre altri segnaleranno che hai started at URL A and ended at URL C , sarai in grado di vedere che hanno iniziato URL A, were 302 redirected to URL B and 301 redirected to URL C Anche se l'URL C era l'obiettivo finale, saprai che questo è negativo per il SEO e deve essere risolto.

Sarete in grado di vedere le intestazioni della cache impostate sul lato server, riprodurre le richieste, modificare le intestazioni delle richieste per testare ....


Assicurati che la sintassi di ogni Regexp sia corretta

testando una serie di modelli di test per assicurarsi che sia una sintassi valida e fa ciò che si intende con una gamma completa di URI di test.

Vedi regexpCheck.php sotto per un semplice script che puoi aggiungere a una directory privata / di test nel tuo sito per aiutarti a farlo. Ho mantenuto questo breve piuttosto che carino. Appena passato questo in un file regexpCheck.php in una directory di test per usarlo sul tuo sito web. Questo ti aiuterà a costruire qualsiasi regexp e testarlo contro un elenco di casi di test mentre lo fai. Sto usando il motore PHP PCRE qui, ma avendo dato un'occhiata al sorgente Apache, questo è sostanzialmente identico a quello usato in Apache. Ci sono molti HowTo e tutorial che forniscono modelli e possono aiutarti a sviluppare le tue abilità regexp.

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

Assicurati di utilizzare il segno di percentuale davanti alle variabili, non il simbolo del dollaro.

È %{HTTP_HOST} , non ${HTTP_HOST} . Non ci sarà nulla nel file error_log, non ci saranno errori interni del server, il tuo regexp è ancora corretto, la regola non corrisponderà. Questo è davvero orribile se si lavora molto con i modelli django / genshi e si ha ${} per la sostituzione variabile nella memoria muscolare.


Imposta le variabili d'ambiente e usa le intestazioni per riceverle:

È possibile creare nuove variabili di ambiente con le linee RewriteRule, come indicato da OP:

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

Ma se non riesci a far funzionare uno script sul lato server, come puoi leggere questa variabile d'ambiente? Una soluzione è impostare un'intestazione:

Header set TEST_FOOBAR "%{REDIRECT_TEST0}e"

Il valore accetta gli specificatori di formato , incluso lo specificatore %{NAME}e per le variabili di ambiente (non dimenticare la e minuscola). A volte, devi aggiungere il prefisso REDIRECT_ , ma non ho funzionato quando il prefisso viene aggiunto e quando non lo è.


Se hai intenzione di scrivere più di una sola riga di regole in .htacesss,
non pensare nemmeno a provare uno di quei metodi di correzione rapida per eseguire il debug.

Ho sprecato giorni a impostare regole multiple senza feedback dai LOG, solo per rinunciare finalmente a una.
Ho ottenuto Apache sul mio PC, ho copiato l'intero sito su HDD e ho regolato l'intero set di regole usando i log in modo molto veloce.
Poi ho rivisto le mie vecchie regole che funzionavano, ho visto che in realtà non stavano facendo ciò che si desiderava. Una bomba ad orologeria per un indirizzo poco diverso.

Ci sono così tante cadute nelle regole di riscrittura, non è affatto una logica logica.
È possibile ottenere Apache attivo e funzionante in dieci minuti, è 10MB, buona licenza, * NIX / WIN / MAC pronto, anche senza installazione.
Inoltre, controlla le linee di intestazione del tuo server e ottieni la stessa versione di Apache dall'archivio se è vecchia. Il mio OP è ancora su 2.0, molte cose non sono supportate.


Riguardo a 4., devi comunque assicurarti che il tuo "fittizio script stub" sia in realtà l'URL di destinazione dopo che tutta la riscrittura è stata eseguita, o non vedrai nulla!

Un trucco simile / correlato (vedi questa domanda ) è inserire una regola temporanea come:

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

Dove show.php è uno script molto semplice che mostra solo i suoi parametri $_GET (puoi anche visualizzare le variabili di ambiente, se vuoi).

Questo fermerà la riscrittura nel momento in cui la inserirai nel set di regole, piuttosto come un punto di interruzione in un debugger.

Se utilizzi Apache <2.3.9, dovrai utilizzare [L] anziché [END] e potresti quindi dover aggiungere:

RewriteRule ^show.php$ - [L]

Nella parte superiore del tuo /show.php di regole, se l'URL /show.php viene riscritto.


Test di riscrittura online .htaccess

Ho trovato this Googling per l'aiuto RegEx, mi ha risparmiato un sacco di tempo dal dover caricare nuovi file .htaccess ogni volta che eseguo una piccola modifica.

dal sito:

tester htaccess

Per testare le tue regole di riscrittura htaccess, inserisci semplicemente l'url a cui stai applicando le regole, posiziona il contenuto del tuo htaccess nell'area di input più grande e premi il pulsante "Check Now".


Uno da un paio d'ore che ho sprecato:

Se hai applicato tutti questi suggerimenti e stai solo verificando 500 errori perché non hai accesso al log degli errori del server, il problema potrebbe non essere nel file .htaccess ma nei file a cui viene reindirizzato.

Dopo aver risolto il problema .htaccess, ho passato altre due ore a cercare di sistemarlo ancora, anche se mi ero semplicemente dimenticato di alcune autorizzazioni.


Alcuni errori osservati si verificano durante la scrittura di .htaccess

Usando ^(.*)$ Ripetutamente in più regole, usando ^(.*)$ altre regole diventano impotenti nella maggior parte dei casi, perché corrisponde a tutto l'url in un singolo colpo.

Quindi, se usiamo la regola per questo url sapmle/url , si consumerà anche questo url sapmle/url/string .

[L] flag [L] deve essere utilizzato per garantire che la nostra regola abbia eseguito l'elaborazione.

Dovrebbe sapere di:

Differenza in% n e $ n

%n è abbinato durante la parte %{RewriteCond} e $n corrisponde sulla parte %{RewriteRule} .

Funzionamento di RewriteBase

La direttiva RewriteBase specifica il prefisso URL da utilizzare per le direttive RewriteRule per directory (htaccess) che sostituiscono un percorso relativo.

Questa direttiva è necessaria quando si utilizza un percorso relativo in una sostituzione in contesto per directory (htaccess) a meno che non si verifichi una delle seguenti condizioni:

La richiesta originale e la sostituzione sono sotto DocumentRoot (diversamente da essere raggiungibile con altri mezzi, come Alias). Il percorso del file system nella directory contenente RewriteRule, suffisso dalla relativa sostituzione, è valido anche come percorso URL sul server (questo è raro). In Apache HTTP Server 2.4.16 e versioni successive, questa direttiva può essere omessa quando la richiesta viene mappata tramite Alias ​​o mod_userdir.


Il mio caso su Apache 2.4 il problema è stato risolto aggiungendo sotto impostazione alla configurazione dell'host virtuale:

Listen 80

in modo che le impostazioni siano qualcosa come:

Listen 80
<VirtualHost *:80>
    ServerAdmin [email protected]
    ServerName testsite.com
    ServerAlias www.testsite.com
    DocumentRoot /var/www/testsite
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>






apache .htaccess mod-rewrite