Эта статья предназначена для тех, кто уже сталкивался или хотя бы слышал об использовании модуля mod_rewrite. При использовании файлов .htaccess, переадресация запросов является одним из самых часто используемых и непонятных новичку приемов. По крайней мере на форумах встречается много вопросов типа: «Как настроить редирект в htaccess». Я надеюсь, что подробное изложение основных принципов работы mod_rewrite поможет вам совершить меньше ошибок и действовать более осмысленно при настройке редиректов в htaccess. Для нетерпеливых отмечу, что в следующей статье будут собраны полезные практические примеры rewriterule.
Как не работает и как работает RewriteRule
Зачем мне это знать, спросите вы? Для того, чтобы сохранить часы своего времени, затраченные на настройку редиректов в .htaccess, достаточно уяснить несколько особеннойстей правил, которыми руководствуется mode_rewrite при разборе запросов. К ним можно придти, составляя правила методом проб и ошибок, или прочитав данную статью (что много быстрее). Не важно ведете вы сайт или seo блог, умение работать с mod_rewrite сэкономит вам массу сил и времени.
Итак, mod_rewrite позволяет обрабатывает входящие ссылки согласно, установленным нами правилам. Верно? Не совсем. Первое, что нужно запомнить — mode_rewrite работает с полным путем до файла. Связано это с тем, что до передачи запроса к данному модулю его уже могли изменить другие модули сервера Apache. В таком случае исходная ссылка не совпадает с запрашиваемым файлом уже на входе первого RewriteRule.
Теперь самое интересное. При обработке запрашиваемого адреса, перед применением правил, прописанных в .htaccess, mode_rewrite отбрезает от полного пути запроса часть, которая соответствует пути до данного файла .htaccess. В итоге на входе мы получаем строку похожую на относительный путь к файлу. Отсюда следует несколько немаловажных выводов о том, что RewriteRule не обрабатывает:
- имя сайта;
- аргументы запроса;
- всю ссылку, если .htaccess не находится в корне сайта
Отметим, что эти данные недоступны для RewriteRule, однако для их использования существует RewriteCond, о котором мы поговорим позже.
Важно, что путь до файла .htaccess с редиректами обрезается вместе со слешем, поэтому исходная строка никогда не начинается с /.
Для большей ясночти приведу несколько примеров RewriteRule. Предположим, что мы хотим перенаправить следующий запрос:
/lib/article/html-lesson-2
В таком случае, если .htaccess находится в папке lib, то RewriteRule будут работать со строкой «article/html-lesson-2» и ни одно из нижеприведенных правил не сработает.
RewriteRule ^/article/html-lesson-2$ /article/html-lesson-3
RewriteRule ^exp-seo.ru/(.*) http://www.example.com/$1
RewriteRule ^lib/article/html-lesson-2$ lib/article/html-lesson-3
Если причины не ясны подскажу: / в начале строки; имя сайта; lib обрезано от пути, т.к. .htaccess не в корне.
Итак мы уже выяснили, что при настройке .htaccess для переадресации мы используем RewriteRule, которое работает со строкой, содержащей относительный путь до файла. Далее эта строка проходит следующий путь:
- сравнивается с регулярным выражением в первом аргументе RewriteRule:
- если совпало, сравнивается с условиями в RewriteCond;
- если совпало, вся строка заменяется на второй аргумент RewriteRule;
- результат передается на обработку следующему правилу;
- после всех преобразований к результату дописывается RewriteBase
Стоп! о RewriteBase мы еще не говорили, а зря. Для полного понимания htaccess перенаправлений он необходим, приступим.
RewriteBase. Достроение ссылки после преобразований
Как мы уже узнали RewriteRule работает лишь с частью адреса. После всех преобразований необходимо преобразовать его к полному виду. Здесь кроется несколько особенностей.
В том случае, если после всех преобразований на выходе RewriteRule получится строка похожая на корректный внешний адрес, начинающийся с «http://» или указания другого протокола, mod_rewrite не использует RewriteBase, а сделает внешний редирект. Так же RewriteBase не используется, если на выходе получен абсолютный адрес (начинающийся со /). В остальных случаях RewriteBase дописывается в левой части результирующей строки.
# .htaccess находится в /lib/
# RewriteBase указан /lib/
RewriteBase /lib/
# Запрос /lib/article/html-lesson-2
# На вход попадает «article/html-lesson-2»
RewriteRule ^article/html-lesson-2$ article/html-lesson-3
# RewriteRule: «article/html-lesson-2» -> «article/html-lesson-3»
# RewriteBase: «article/html-lesson-3» -> «/lib/article/html-lesson-3»
# Запрос /lib/article/html-lesson-2
RewriteRule ^article/html-lesson-2$ /lib/article/html-lesson-3
# RewriteRule: «article/html-lesson-2» -> «/lib/article/html-lesson-3»
# RewriteBase не дописывается, так как строка нанчинается на ‘/’.
# Запрос /lib/article/html-lesson-2
# Используем 301 редирект
RewriteRule ^article/html-lesson-2$ article/html-lesson-3 [R=301]
# После RewriteRule: «article/html-lesson-2» -> «article/html-lesson-3»
# и mod_rewrite зафиксировал указание внешнего редиректа [R=301]
# Дописывается RewriteBase: «article/html-lesson-3» -> «/lib/article/html-lesson-3»
# mod_rewrite дописывает полную ссылку для редиректа:
# «/lib/article/html-lesson-3» -> /lib/article/html-lesson-3
# Если RewriteBase не указан в последнем примере получим
# /var/www/exp-seo.ru/lib/article/html-lesson-3
# Применился RewriteBase по умолчанию
Теперь можем продолжить рассмотрение последовательности обработки редиректа в htaccess до логического завершения.
- запрос преобразуется в абсолютный путь к файлу
- от пути отрезается путь до .htaccess с правилами перенаправления
- строка сравнивается с регулярным выражением в первом аргументе RewriteRule:
- если совпало, сравнивается с условиями в RewriteCond;
- если совпало, вся строка заменяется на второй аргумент RewriteRule;
- результат передается на обработку следующему правилу;
- после всех преобразований к результату дописывается RewriteBase
- если результат отличается от исходного запроса, то он проходит весь цикл повторно
Пока что на этом все, не ожидал что получится так много. Устал писать) Завтра продолжим. Нас еще ждут флаги, RewriteCond и практические примеры применения mod_rewrite. upd.
Отличный блог! Только картинки нужно выводить на главной, чтобы больше привлекало
Лично мне надоели однообразные изображения из фотостоков, которые заполонили seo блоги. Хотя иногда — да, возможно, стоит разбавлять текст картинками.
Использовал для своего сайта редиректы, дабы заставить поисковых ботов лазить по ключевым словам. Вообще хтаццес-редирект очень полезная вещь.
вот только сегодня наткнулся на этот блог, почему не раньше?? на той недели я с этим htaccess боролся несколько дней, все не мог правильно сделать — а тут все так понятно написано…
Подскажите, по возможности, а?
Из http://site.ru/product.php?id_product=103660 переходить
http://www.site.ru/catalog/410/ При заходе на страницу
http://site.ru/product.php?id_product=103660
RewriteCond %{QUERY_STRING} ^id_product=(103[0-9]{1,3})$
RewriteRule .? http://www.site.ru/catalog/410/ [R=301,L]
хотелось-бы попасть
http://site.ru/catalog/430/
НО вместо этого попадаю
http://site.ru/catalog/430/?id_product=103660
Как убрать эти вот «?id_product=103660» Маюсь второй день :(((
Рамиль, добавьте ? на конце правила, вот так:
RewriteRule .?http://www.site.ru/catalog/410/?%5BR=301,L%5D
Должно сработать, т.к. таким образом мы обнулим $QUERY_STRING
Спасибо за подсказку! Совсем не знал, что кванторы ?-*-+ можно использовать и в конце строки.
в данном случае ? не квантор, а просто задает пустой $QUERY_STRING, поскольку если мы добавляем вручную GET-параметры к запросу без указания флага [QSA], то они перезаписывают старое значение $QUERY_STRING, что вам и было нужно.