it-swarm.com.ru

Советы по отладке .htaccess переписать правила

Многие авторы имеют проблемы с отладкой своих операторов RewriteRule и RewriteCond в своих .htaccess файлах. Большинство из них используют службу общего хостинга и поэтому не имеют доступа к конфигурации корневого сервера. Они не могут избежать использования файлов .htaccess для перезаписи и не могут включить RewriteLogLevel ", как предлагают многие респонденты. Также есть много .htaccess-специфичных ловушек и ограничений, которые не очень хорошо освещены. локальный тестовый стек LAMP включает в себя слишком много кривой обучения для большинства.

Поэтому мой вопрос здесь заключается в том, как бы мы порекомендовали им отладить свои правила самих себя. Я приведу несколько предложений ниже. Другие предложения будут оценены.

  1. Поймите, что механизм mod_rewrite циклически просматривает файлы .htaccess. Двигатель запускает этот цикл:

    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
    

    Таким образом, ваши правила будут выполняться неоднократно, и если вы измените путь URI, он может в конечном итоге выполнить другие .htaccessфайлы, если они существуют. Поэтому убедитесь, что вы прерываете этот цикл, если необходимо, добавив дополнительное RewriteCond, чтобы остановить запуск правил. Также удалите все более низкие уровни .htaccess переписать наборы правил, если явно не намерены использовать многоуровневые наборы правил.

  2. Убедитесь, что синтаксис каждого регулярного выражения правильный , проверив набор тестовых шаблонов, чтобы убедиться, что это правильный синтаксис и выполняет то, что вы намерены с полный спектр тестовых URI. Смотрите ответ ниже для более подробной информации.

  3. Построить свои правила постепенно в тестовом каталоге. Вы можете использовать "выполнить самый глубокий файл .htaccess в пути", чтобы настроить отдельный тестируйте каталог (дерево) и отлаживайте здесь наборы правил, не нарушая ваших основных правил и не останавливая работу вашего сайта. Вы должны добавлять их по одному, потому что это единственный способ локализовать сбои в отдельных правилах.

  4. Используйте фиктивную заглушку скрипта для вывода переменных сервера и окружения . (См. Листинг 2 ) Если ваше приложение использует, скажем, blog/index.php, вы можете скопировать его в test/blog/index.php и использовать его для проверки правил блога в test подкаталог. Вы также можете использовать переменные окружения, чтобы убедиться, что механизм перезаписи правильно интерпретирует строки подстановки, например,.

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

    и найдите эти REDIRECT _ * переменные в дампе phpinfo. Кстати, я использовал это и обнаружил на своем сайте, что я должен был использовать вместо этого %{ENV:DOCUMENT_ROOT_REAL}. В случае зацикливания перенаправителя переменные REDIRECT_REDIRECT _ * перечисляют предыдущий проход. Так далее..

  5. Убедитесь, что ваш браузер не укушен неправильным кэшированием 301 перенаправлений . Смотрите ответ ниже . Моя благодарность Ульрих Палха за это.

  6. Механизм перезаписи кажется чувствительным к каскадным правилам в контексте .htaccess (то есть, когда RewriteRule приводит к подстановке, а это относится к дальнейшим правилам), поскольку я обнаружил ошибки с внутренними подзапросами (1) = и некорректная обработка PATH_INFO , которую часто можно предотвратить с помощью флагов [NS], [L] и [PT].

Есть еще комментарии или предложения?

Листинг 1 - phpinfo

<?php phpinfo(INFO_ENVIRONMENT|INFO_VARIABLES);
260
TerryE

Вот несколько дополнительных советов по правилам тестирования, которые могут упростить отладку для пользователей на виртуальном хостинге.

1. Используйте фальшивый пользовательский агент

При тестировании нового правила добавьте условие, чтобы выполнить его только с пользовательским агентом fake, который вы будете использовать для своих запросов. Таким образом, это не повлияет ни на кого на вашем сайте.

например

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

Если вы используете Firefox, вы можете использовать ser Agent Switcher , чтобы создать поддельную строку агента пользователя и проверить ее.

2. Не используйте 301, пока не закончите тестирование

Я видел очень много постов, где люди все еще проверяют свои правила и используют 301. DO NOT .

Если вы не используете предложение 1 на своем сайте, 301 повлияет не только на вас, но и на любого посетителя вашего сайта.

Помните, что они являются постоянными и агрессивно кешируются вашим браузером. Вместо этого используйте 302, пока не будете уверены, затем измените его на 301.

3. Помните, что 301 агрессивно кэшируются в вашем браузере

Если ваше правило не работает и выглядит правильно для вас, а вы не использовали предложения 1 и 2, то проведите повторную проверку после очистки кэша браузера или в режиме приватного просмотра.

4. Используйте инструмент HTTP Capture

Используйте инструмент захвата HTTP, например Fiddler , чтобы увидеть фактический трафик HTTP между вашим браузером и сервером.

В то время как другие могут сказать, что ваш site does not look right, вы можете вместо этого увидеть и сообщить, что all of the images, css and js are returning 404 errors, быстро сузив проблему.

В то время как другие сообщат, что вы started at URL A and ended at URL C, вы сможете увидеть, что они начали с URL A, were 302 redirected to URL B and 301 redirected to URL C. Даже если URL C был конечной целью, вы будете знать, что это плохо для SEO и должно быть исправлено.

Вы сможете увидеть заголовки кэша, которые были установлены на стороне сервера, воспроизвести запросы, изменить заголовки запросов для проверки ....


126
Ulrich Palha

Онлайн тестирование перезаписи .htaccess

Я нашел this Поиск в Google для справки RegEx, он избавил меня от необходимости загружать новые .htaccess файлы каждый раз, когда я вносил небольшие изменения.

с сайта:

тестер htaccess

Чтобы проверить свои правила перезаписи htaccess, просто введите URL-адрес, к которому вы применяете правила, поместите содержимое вашего htaccess в большую область ввода и нажмите кнопку "Проверить сейчас".

73
JCastell

Не забывайте, что в файлах .htaccess это относительный URL-адрес, который соответствует.

В файле .htaccess следующий RewriteRule никогда не будет совпадать:

RewriteRule ^/(.*)     /something/$s
12
Krist van Besien

Убедитесь, что синтаксис каждого регулярного выражения правильный

проверяя набор тестовых шаблонов, чтобы убедиться, что это правильный синтаксис и что вы собираетесь с полным диапазоном тестовых URI.

См. regexpCheck.php ниже для простого сценария, который вы можете добавить в личный каталог/test на вашем сайте, чтобы помочь вам сделать это. Я сохранил это краткое, а не красивое. Просто вставьте это в файл regexpCheck.php в тестовом каталоге, чтобы использовать его на своем веб-сайте. Это поможет вам создать любое регулярное выражение и сравнить его со списком тестовых случаев. Я использую движок PHP PCRE здесь, но, посмотрев на исходник Apache, он в основном идентичен тому, который используется в Apache. Существует множество практических руководств и учебных пособий, которые предоставляют шаблоны и могут помочь вам развить навыки регулярного выражения.

Листинг 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>
8
TerryE

Один из пары часов, которые я потратил впустую:

Если вы применили все эти советы и допустили только 500 ошибок, потому что у вас нет доступа к журналу ошибок сервера, возможно, проблема не в .htaccess, а в файлах, на которые он перенаправляет.

После того, как я исправил свою проблему .htaccess, я потратил еще два часа, пытаясь ее исправить, хотя я просто забыл о некоторых разрешениях.

6
Ruben

Установите переменные окружения и используйте заголовки для их получения:

Вы можете создавать новые переменные окружения с помощью строк RewriteRule, как указано в OP:

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

Но если вы не можете заставить работать серверный скрипт, как вы можете тогда прочитать эту переменную среды? Одним из решений является установка заголовка:

Header set TEST_FOOBAR "%{REDIRECT_TEST0}e"

Значение принимает спецификаторы формата , включая спецификатор %{NAME}e для переменных среды (не забывайте строчную букву e). Иногда вам нужно добавить префикс REDIRECT_, но я не определился, когда префикс будет добавлен, а когда - нет.

6
Flimm

Убедитесь, что вы используете знак процента перед переменными, а не знак доллара.

Это %{HTTP_Host}, не${HTTP_Host}. В error_log ничего не будет, не будет внутренних серверных ошибок, ваше регулярное выражение все еще верно, правило просто не будет соответствовать. Это действительно отвратительно, если вы много работаете с шаблонами Django/genshi и имеете ${} для замены переменных в мышечной памяти.

5
Simon

Если вы создаете перенаправления, проверьте с помощью curl , чтобы избежать проблем с кэшированием в браузере. Используйте -I для получения только заголовков http. Используйте -L, чтобы следовать всем перенаправлениям.

4
flm

Что касается 4., вам все равно нужно убедиться, что ваша "заглушка сценария" на самом деле является целевым URL-адресом после того, как все переписывание выполнено, иначе вы ничего не увидите!

Подобный/связанный трюк (см. этот вопрос ) заключается во вставке временного правила, такого как:

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

Где show.php - это очень простой скрипт, который просто отображает свои параметры $_GET (вы также можете отображать переменные окружения, если хотите).

Это остановит переписывание в том месте, где вы вставляете его в набор правил, как точка останова в отладчике.

Если вы используете Apache <2.3.9, вам нужно использовать [L], а не [END], и вам может затем добавить:

RewriteRule ^show.php$ - [L]

В самом верху вашего набора правил , если , URL /show.php сам переписывается.

3
Doin

Я нашел этот вопрос, пытаясь отладить проблемы с mod_rewrite, и у него определенно есть несколько полезных советов. Но в конце самое главное, чтобы убедиться, что ваш синтаксис регулярных выражений правильный. Из-за проблем с моим собственным синтаксисом RE установка сценария regexpCheck.php не была приемлемой опцией.

Но поскольку Apache использует Perl-совместимые регулярные выражения (PCRE), любой инструмент, который помогает в написании PCRE, должен помочь. В прошлом я использовал инструмент RegexPlanet с Java и ​​Javascript RE, и был счастлив обнаружить, что они также поддерживают Perl.

Просто введите свое регулярное выражение и один или несколько примеров URL-адресов, и он скажет вам, соответствует ли регулярное выражение ("1" в столбце "~ =") и, если применимо, любые соответствующие группы (числа в "split") столбец будет соответствовать числам, ожидаемым Apache, например, $ 1, $ 2 и т. д.) для каждого URL. Они утверждают, что поддержка PCRE находится "в бета-версии", но это было как раз то, что мне было нужно для решения моих проблем с синтаксисом.

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

Я бы просто добавил комментарий к существующему ответу, но моя репутация еще не достигла такого уровня. Надеюсь, это кому-нибудь поможет.

3
Lambart

Некоторые ошибки, которые я наблюдал, случаются при написании .htaccess

Повторное использование ^(.*)$ в нескольких правилах, использование ^(.*)$ в большинстве случаев приводит к тому, что другие правила оказываются бессильными, поскольку они соответствуют всем URL-адресам в одном обращении.

Таким образом, если мы используем правило для этого URL sapmle/url, оно также будет использовать этот URL sapmle/url/string.


[L] флаг должен использоваться, чтобы убедиться, что наше правило завершило обработку.


Должен знать о:

Разница в% n и $ n

%n сопоставляется в части %{RewriteCond}, а $n совпадает в части %{RewriteRule}.

Работа RewriteBase

Директива RewriteBase указывает префикс URL, который будет использоваться для директив RewriteRule для каждого каталога (htaccess), которые заменяют относительный путь.

Эта директива требуется, когда вы используете относительный путь в подстановке в контексте для каждого каталога (htaccess), если не выполняется одно из следующих условий:

Первоначальный запрос и подстановка находятся под DocumentRoot (в отличие от достижимого другими средствами, такими как Alias). Путь файловой системы к каталогу, содержащему RewriteRule, с суффиксом относительной подстановки, также допустим в качестве URL-пути на сервере (это редко). В Apache HTTP Server 2.4.16 и более поздних версиях эта директива может быть опущена, когда запрос отображается через Alias ​​или mod_userdir.

2
Abhishek Gurjar

Если вы планируете написать более чем одну строку правил в .htacesss,
даже не думайте о том, чтобы попытаться отладить один из этих методов исправления.

Я потратил несколько дней на настройку нескольких правил без обратной связи с журналами, только чтобы окончательно отказаться от одного.
Я установил Apache на свой компьютер, скопировал весь сайт на жесткий диск, и весь набор правил был отсортирован по журналам очень быстро.
Затем я пересмотрел свои старые правила, которые работали, и увидел, что они на самом деле не делают то, что хотели. Бомба замедленного действия для немного другого адреса.

В правилах переписывания столько ошибок, что это не совсем логичная вещь.
Apache можно запустить и запустить за десять минут, он 10 МБ, хорошая лицензия, * NIX/WIN/MAC готов, даже без установки.
Кроме того, проверьте строки заголовка вашего сервера и получите ту же версию Apache из архива, если она старая. Мой OP по-прежнему на 2.0, многие вещи не поддерживаются.

1
papo

(Похоже на идею Doin) Чтобы показать, что сопоставляется, я использую этот код

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

Сохраните его в r.php в корневом каталоге сервера, а затем выполните несколько тестов в .htaccess.
Например, я хочу сопоставить URL, которые не начинаются с префикса языка

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

Я оставлю это здесь, возможно, очевидную деталь, но заставил меня несколько часов биться головой: будьте осторожны, используя %{REQUEST_URI}, потому что то, что @ Krist van Besien сказать в своем ответе, совершенно верно, но не для строки REQUEST_URI , потому что выход этого TestString начинается с /. Так что будьте аккуратнее:

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