В прошлый раз мы рассмотрели полный цикл работы mode_rewrite, однако остались неосвещенными некоторые важные моменты. О них мы и поговорим
Mode_rewrite флаги
Как вам наверное известно, каждая директива RewriteRule может иметь на конце необязательный набор флагов, регулирующих ее действие и изменяющих действие редиректа в .htaccess. Мы рассмотрим самые интересные и важные флаги:
- [L] — остановка процесса преобразований.
- [R] — вызов редиректа.
- [QSA] — добавление (по умолчанию замена) строки запроса.
[L]:остановка обработки mode_rewrite
Как вы уже поняли, добавление флага [L] позволяет остановить процесс обработки запроса, т.е. все последующие правила не будут применены. Использование данного флага иногда очень удобно, но стоит помнить о двух возможных ошибках.
Флаг [L] прерывает только текущую итерацию обработки. В прошлый раз я рассказал, как работает mod_rewrite и показал, что запросы обрабатываются до тех пор, пока исходная строка не совпадет с результатом преобразований. Использование флага [L] не отменяет этого правила.
Следующая проблема является следствием предыдущей. В случае частого использования флага [L] может возникнуть трудно отлавливаемое зацикливание процесса обработки, вывызвающее внутреннюю ошибку сервера. Приведу пример:
RewriteBase /
RewriteRule ^test1.html$ test2.html [L]
RewriteRule ^test2.html$ test1.html [L]
Запрос любого из двух документов вызовет бесконечный цикл преобразований. В случае отсутствия флагов такого не произойдет, т.к. исходный и конечный запрос совпадают.
[R]:редирект в mode_rewrite
Данный флаг прямо указывает, что должен быть произведен внешний редирект. Это означает, что ответ сервера будет содержать код редиректа 301 или 302, а адрес в строке браузера изменится (в случае внутреннего редиректа пользователь не может узнать о нем).
Следует помнить, что apache не производит редирект сразу, встретив флаг [R], а лишь запоминает о необходимости выполнить внешний редирект. Как правило мы хотим противоположного поведения, поэтому практически всегда следует использовать связку двух флагов: [R=301,L] — сделать 301 редирект и прервать дальнейшие преобразования. Кроме того, как я уже писал в предыдущей части статьи, при указании полной внешней ссылки, редирект автоматически становится внешним.
[QSA]: изменение параметров запроса в mode_rewrite
Параметры запроса не входят в саму строку, с которой оперирует RewriteRule, однако если во второй половине директивы к строке добавляются параметры запроса — они передаются в переменную %{QUERY_STRING}, которую можно использовать в RewriteCond. Важно, что эта часть строки не попадает в основную, с которой будут работать следующие директивы. Флаг [QSA] регулирует порядок добавления новых параметров запроса в %{QUERY_STRING}. По умолчанию происходит перезапись параметров, при наличии флага [QSA], новые параметры добавляются в начало %{QUERY_STRING}. Важно, что %{QUERY_STRING} изменятся сразу же в данном правиле, поэтому в последующих правилах может возникнуть проблема при необходимости узнать исходные параметры запроса пользователя. Решение приведено в одном из практических примеров работы с mode_rewrite.
RewriteCond: условия для RewriteRule
После того как мы разобрались с особенностями отработки RewriteRule и основных флагов, осталось поговорить о RewriteCond, которые являются аналогом оператора if, только с длинным названием)).
В общем случае применение RewriteCond выглядит примерно так:
RewriteEngine on
RewriteCond условие1
RewriteCond условие2
RewriteRule правило 1
RewriteRule правило 2
В данном случае правило 1 будет применено, если выполняются условия 1 и 2, а правило 2 исполнится всегда, т.к. RewriteCond действует только на следующее непосредственно за ним RewriteRule. Для группировки RewriteCond можно использовать логический флаг [OR] (по умолчанию подразумевается AND).
Основные возможности RewriteCond заключаются в применении следующих «фишек»:
- $N (N — число от 1 до 9) — доступ к частям директивы RewriteRule;
- %N (N — число от 1 до 9) — доступ к частям директивы RewriteCond;
- %{NAME_OF_VARIABLE} — использование нижеприведенных переменных запроса
HTTP_USER_AGENT | Содержит информацию о типе и версии браузера и операционной системы посетителя. |
HTTP_REFERER | Приводится адрес страницы, с которой посетитель пришёл на данную страницу. |
HTTP_COOKIE | Список COOKIE, передаваемых браузером |
HTTP_FORWARDED | Страница непосредственно, с которой перешел пользователь |
HTTP_HOST | Адрес сервера |
HTTP_ACCEPT | Описываются предпочтения клиента относительно типа документа. |
REMOTE_ADDR | IP-адрес посетителя. |
REMOTE_HOST | адрес посетителя в нормальной форме |
REMOTE_IDENT | Имя удаленного пользователя. Имеет формат имя.хост |
REMOTE_USER | Тоже, что и REMOTE_IDENT, но содержит только имя. |
REQUEST_METHOD | Позволяет определить тип запроса (GET или POST). Должен обязательно анализироваться, т.к. определяет дальнейший способ обработки информации |
SCRIPT_FILENAME | Полный путь к веб-странице на сервере. |
PATH_INFO | Содержит в себе все, что передавалось в скрипт. |
QUERY_STRING | Содержит строчку, переданную в качестве запроса при вызове CGI скрипта. |
AUTH_TYPE | Используется для идентификации пользователя |
DOCUMENT_ROOT | Cодержит путь к корневой директории сервера. |
SERVER_ADMIN | Почтовый адрес владельца сервера, указанный при установке. |
SERVER_NAME | Адрес сервера |
SERVER_ADDR | IP-адрес вашего сайта. |
SERVER_PORT | Порт, на котором работает Apache. |
SERVER_PROTOCOL | Версия HTTP протокола. |
SERVER_SOFTWARE | Название сервера, например, Apache/1.3.2 (Unix) |
TIME_YEAR TIME_MON TIME_DAY TIME_HOUR TIME_MIN TIME_SEC TIME_WDAY TIME | Переменные предназначены для работы со временем в разных форматах. |
API_VERSION | Это версия API модуля Apache (внутренний интерфейс между сервером и модулем) в текущей сборке сервера, что определено в include/ap_mmn.h. |
THE_REQUEST | Полная строка HTTP запроса отправленная браузером серверу (т.е., «GET /index.html HTTP/1.1»). Она не включает какие-либо дополнительные заголовки отправляемые браузером. |
REQUEST_URI | Ресурс, запрошенный в строке HTTP запроса. |
REQUEST_FILENAME | Полный путь в файловой системе сервера к файлу или скрипту соответствующим этому запросу. |
IS_SUBREQ | Будет содержать текст «true» если запрос выполняется в текущий момент как подзапрос, «false» в другом случае. Подзапросы могут быть сгенерированы модулями которым нужно иметь дело с дополнительными файлами или URI для того чтобы выполнить собственные задачи. |
RewriteCond, как и RewriteRule использует Perl-совместимые регулярные выражения, однако с несколькими дополнениями:
- Префикс ‘!’ для указания несоответствия шаблону.
- ‘<Условие’ (лексически меньше)
- ‘>Условие’ (лексически больше)
- ‘=Условие’ (лексически равно)
- ‘-d’ (является ли каталогом)
- ‘-f’ (является ли обычным файлом)
- ‘-s’ (является ли обычным файлом с ненулевым размером)
- ‘-l’ (является ли символической ссылкой)
- ‘-F’ (проверка существования файла через подзапрос)
- ‘-U’ (проверка существования URL через подзапрос)
Интересным моментом является порядок проверки условий в mode_rewrite. Он поступает нетривиально и сначала проверяет условие в RewriteRule и если оно выполняется проверяет соответствующие RewriteCond. Поэтому использование RewriteCond для увеличения производительности не имеет смысла.
Я снова устал писать, однако на этом ВСЕ. Осталось лишь привести много практических примеров работы с mod_rewrite, но это будет тема отдельного поста.
Как все понятно написано. А то в универе вообще непонятно рассказывают. Спасибо.
Да, действительно чётко написано. Я хоть лучше понял механизм работы флага [L], а то раньше иногда возникало зацикливание, потому что я считал его прерыванием цикла, а он прерывает лишь итерацию. И т.к. не было такого понятного мануала, то просто подгонял под рабочий вариант
Здравствуйте уважаемый Дмитрий. Скажите пожалуста, можно ли с Вашим блогом обменяться постовыми. Мой блог в имени. Обмен постовыми почта моя mozdok939@yandex.ru За ранее Вам благодарен!!!