Советы по отладке .htaccess переписать правила
У многих плакатов есть проблемы с отладкой своих команд 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);
Ответы
Ответ 1
Вот несколько дополнительных советов по правилам тестирования, которые могут облегчить отладку для пользователей на общедоступном хостинге
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 и нуждается в исправлении.
Вы сможете увидеть заголовки кешей, которые были установлены на стороне сервера, повторить запросы, изменить заголовки запросов для проверки....
Ответ 2
Online.htaccess переписать тестирование
Я нашел this Googling для справки RegEx, это избавило меня от необходимости загружать новые файлы .htaccess
каждый раз, когда я делаю небольшую модификацию.
с сайта:
htaccess tester
Чтобы проверить правила перезаписи htaccess, просто заполните URL-адрес, к которому вы применяете правила, поместите содержимое своего htaccess в большую область ввода и нажмите кнопку "Проверить сейчас".
Ответ 3
Не забывайте, что в файлах .htaccess это сопоставимый URL-адрес.
В файле .htaccess следующий RewriteRule никогда не будет соответствовать:
RewriteRule ^/(.*) /something/$s
Ответ 4
Убедитесь, что синтаксис каждого 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> </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"> 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> </p>
<table><thead><tr><td><b>Test Vector</b></td><td> <b>Result</b></td>
<?php
for ( $i=0; $i<$maxM; $i++ ) echo "<td> <b>\$$i</b></td>";
echo "</tr><tbody>\n";
for( $i=0; $i<$a_ntests; $i++ ){
echo '<tr><td> <input name="test[]" value="',
htmlentities($a_test[$i], ENT_QUOTES,"UTF-8"),'" /></td>';
foreach ($res[$i] as $v) { echo '<td> ',htmlentities($v, ENT_QUOTES,"UTF-8"),' </td>';}
echo "</tr>\n";
}
?> </table></form></body></html>
Ответ 5
Один из двух часов, которые я потратил впустую:
Если вы применили все эти советы и только 500 ошибок, потому что у вас нет доступа к журналу ошибок сервера, возможно, проблема не в .htaccess, а в файлах, к которым она перенаправляется.
После того, как я исправил мою проблему .htaccess, я потратил еще два часа, пытаясь исправить это, хотя я просто забыл о некоторых разрешениях.
Ответ 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_
, но я не работал, когда добавляется префикс, а когда нет.
Ответ 7
Убедитесь, что вы используете знак процента перед переменными, а не знак доллара.
Это %{HTTP_HOST}
, не ${HTTP_HOST}
. В error_log ничего не будет, не будет внутренних ошибок сервера, ваше регулярное выражение все равно будет правильным, правило просто не будет соответствовать. Это действительно ужасно, если вы много работаете с шаблонами django/genshi и ${}
для замены переменных в мышечной памяти.
Ответ 8
Если вы создаете перенаправления, проверьте curl, чтобы избежать проблем с кешированием браузера.
Используйте -I для получения только заголовков HTTP.
Используйте -L для выполнения всех перенаправлений.
Ответ 9
Я нашел этот вопрос, пытаясь отладить мои проблемы с 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
Я бы просто добавил комментарий к существующему ответу, но моя репутация еще не на этом уровне. Надеюсь, это поможет кому-то.
Ответ 10
Что касается 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
сам переписывается.
Ответ 11
Некоторые ошибки, которые я наблюдал, случаются при написании .htaccess
Использование ^(.*)$
повторяется в нескольких правилах, использование ^(.*)$
приводит к тому, что другие правила становятся бессильны в большинстве случаев, потому что он соответствует всем URL-адресам с одним ударом.
Итак, если мы используем правило для этого url sapmle/url
, он также будет использовать этот url sapmle/url/string
.
[L]
флаг должен использоваться для обеспечения выполнения нашего правила обработки.
Должен знать о:
%n
сопоставляется во время %{RewriteCond}
и $n
соответствует совпадению %{RewriteRule}
.
Директива RewriteBase указывает префикс URL, который будет использоваться для per-directory (htaccess) Директивы RewriteRule, которые заменяют относительный путь.
Эта директива требуется, если вы используете относительный путь в замену в контексте per-directory (htaccess), если ни одна из выполняются следующие условия:
Исходный запрос и подстановка находятся под DocumentRoot (в отличие от других, таких как Alias). Путь файловой системы к каталогу, содержащему RewriteRule, суффикс относительной подстановки также действителен как путь URL-адреса на сервер (это редко). В Apache HTTP Server 2.4.16 и более поздних версиях, эта директива может быть опущена, когда запрос отображается через псевдоним или mod_userdir.
Ответ 12
Если вы планируете написать более чем одну строку правил в .htacesss,
даже не думайте о том, чтобы попытаться отладить один из этих методов исправления.
Я потратил впустую дни, устанавливая многократные правила, без обратной связи от ЛОГОВ, только чтобы наконец сдаться.
Я установил Apache на свой ПК, скопировал весь сайт на его жесткий диск и очень быстро разобрал весь набор правил, используя логи.
Затем я пересмотрел свои старые правила, которые работали. Я видел, что они действительно не делали то, что хотели. Часовая бомба, учитывая немного другой адрес.
В правилах переписывания так много ошибок, что это не совсем логичная вещь.
Вы можете запустить и запустить Apache за десять минут, он 10 МБ, хорошая лицензия, * NIX/WIN/MAC готов, даже без установки.
Также проверьте строки заголовка вашего сервера и получите ту же версию Apache из их архива, если она старая. Мой ОП все еще на 2.0; многие вещи не поддерживаются.
Ответ 13
(Подобно идее 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
Ответ 14
Я оставлю это здесь, может быть, явную деталь, но часами стучал головой:
будьте осторожны, используя %{REQUEST_URI}
, потому что @Krist van Besien говорит, что в его ответе абсолютно правильно, , но не для строки REQUEST_URI, потому что out этого TestString начинается с /
. Поэтому будьте осторожны:
RewriteCond %{REQUEST_URI} ^/assets/$
^
| check this pesky fella right here if missing