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

240

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

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

  • Поймите, что движок 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 directory)
    while rewrite occurred
    

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

  • Убедитесь, что синтаксис каждого Regexp правильный, путем тестирования против набора тестовых шаблонов, чтобы убедиться, что это допустимый синтаксис, и делает то, что вы намереваетесь с полным спектром тестов URIs. Подробнее см. ниже.

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

  • Используйте заглушку script для вывода переменных сервера и среды. (См. Листинг 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 _ * перечисляют предыдущий проход. Etc..

  • Убедитесь, что вы не укусили ваш кеш-кеширование неверных 301 переадресаций. См. Ниже ниже. Я благодарю Ulrich Palha за это.

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

Больше комментариев или предложений?

Листинг 1 - phpinfo

<?php phpinfo(INFO_ENVIRONMENT|INFO_VARIABLES);
  • 10
    Это хорошо ... Возможно, вам следует перенести их из вопроса в ответ.
  • 0
    @ w00t, я отключил проверку регулярных выражений в соответствии с вашим предложением, потому что я хочу отослать его по ссылке в других ответах.
Показать ещё 3 комментария
Теги:
.htaccess
mod-rewrite

14 ответов

122

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

1. Использовать агент Fake-user

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

e.g

#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, вы можете использовать User 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 и нуждается в исправлении.

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


  • 9
    Ульрих, большое спасибо за этот вклад. Вы подобрали некоторые аспекты, которые я не думал включать в свой список. Что касается проблемы с отладкой 301, я использую Chrome в «Приватном просмотре» (AKA «Porn-mode»), поскольку при закрытии окна эта информация о состоянии выводится. Я надеюсь, что вы не возражаете, чтобы я не «принял» это как важный момент, но ни один лучший ответ. Еще раз спасибо. :)
  • 1
    Чтобы прояснить это (у вас есть это в вашем коде, но вы его не заметили), но чтобы убедиться, что вы используете перенаправление 302, а не 301, вам нужно [L,R=302]
Показать ещё 3 комментария
55

Online.htaccess переписать тестирование

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

с сайта:

htaccess tester

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

  • 4
    Спасибо за указатель на этот инструмент, который я нашел самый прямой способ отладить мою проблему.
  • 0
    Если у вас есть доступ ssh к вашему веб-пространству, другой вариант - изменить .htaccess напрямую через редактор на сервере.
Показать ещё 2 комментария
11

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

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

RewriteRule ^/(.*)     /something/$s
  • 4
    Да, строка, переданная в правило перезаписи, является относительной и поэтому разбивается на любые ведущие / , но это сопоставление не происходит для строк соответствия, собранных в командах Rewrite Cond .
7

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

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

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

Листинг 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>
  • 0
    Краткое примечание: import_request_variables устарела в PHP 5.3 и удалена в 5.4. extract($_GET) сочетании с extract($_POST) может выполнять одну и ту же функцию, но для всех переменных потребуется префикс, удаленный из их имени. Источник: php.net/manual/en/function.import-request-variables.php
  • 0
    @ Уотчер, спасибо. Год назад я обновил свою локальную версию до версии 5.4, но забыл изменить эту публикацию. Сейчас сделано.
Показать ещё 3 комментария
6

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

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

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

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

Header set TEST_FOOBAR "%{REDIRECT_TEST0}e"

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

5

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

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

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

  • 0
    Я использую веб-сервис хостинга с общим доступом для своего личного сайта, но я настроил тестовую виртуальную машину, которая примерно отражает ее с точки зрения конфигурации PHP / Apache, домашнего каталога и т. Д. Однако, поскольку эта виртуальная машина находится под моим admin Я могу включить переписывание журнала, чтобы диагностировать любые сложные проблемы .htaccess .
4

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

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

  • 0
    Да, переменные $ substitution относятся к последнему шаблону RewriteRule, а % относятся к последнему шаблону RewriteCond и специальным предложениям, таким как% {env: XXX}
3

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

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

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

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

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

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

RewriteRule ^show.php$ - [L]

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

3

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

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

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

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

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

  • 0
    хороший инструмент, но ужасная форма ... посмотрите эти классные инструменты: regex101.com или refiddle.com или regexr.com
2

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

  • 0
    curl -IvL ... чертовски хороший подход.
1

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

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

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


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


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

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

%n сопоставляется во время %{RewriteCond} и $n соответствует совпадению %{RewriteRule}.

Работа RewriteBase

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

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

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

0

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

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

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

  • 0
    Папо, я запустил выделенные серверы, VPS-хосты, размещенные у провайдера, и частные виртуальные машины в своей структуре разработки, но я все еще использую сервис общего хостинга для моих публичных доменов и электронной почты, просто потому что это более удобно и рентабельно использовать полностью управляемый сервис для них. Это руководство действительно предназначено для пользователей общих служб. Настроить частную виртуальную машину для полного зеркалирования общего сервиса довольно сложно. Да, если вы можете использовать тестовую ВМ, это помогает, но я все еще время от времени использую эти «хитрости» в моей общей службе.
  • 0
    Я бы согласился с этим, если бы ваш A был подставлен как альтернативное предложение для отладки правил mod_rewrite , но открытие "даже не думайте об этом" - просто плохой совет для основных пользователей общих служб, которые пытаются понять, почему их файлы htaccess не работают так, как им кажется.
Показать ещё 4 комментария
0

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

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

(Подобно идее 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
  • 1
    просто использование заглушки phpinfo (), как я упоминал в пункте 4 на моем O / P, делает в основном то же самое. Ищите QUERY_STRING

Ещё вопросы

Сообщество Overcoder
Наверх
Меню