Лучший хостинг
Акции
RICHHost Акция действует с 5 марта 2023 по 20 марта 2023
HostiMan Акция действует с 16 декабря 2022 по 8 января 2023
RICHHost Акция действует с 3 декабря 2022 по 15 декабря 2022
FineRDP Акция действует с 22 ноября 2022 по 31 декабря 2022
NetRay Акция действует с 1 октября 2022 по 31 декабря 2023
Все акции...

Что такое mod_rewrite

Данная статья была написана с целью дать читателю понимание базовых принципов и основ работы модуля mod_rewrite в файле .htaccess. Здесь не будет конкретных примеров как сделать то или иное действие, это будет рассматриваться в отдельных статьях. Статья разбита на логические разделы, которые в некоторых случаях дополняют друг друга. Поэтому при прочтении статьи, может сложиться чувство недосказанности впечатление неполного изложения, но все необходимые для понимая данные описаны в этой или других статьях, на которые естественно есть ссылки.
Что такое mod_rewrite
Принцип работы модуля mod_rewrite
RewriteCond
RewriteRule
Обратные связи RewriteCond и RewriteRule
Переменные сервера

Что такое mod_rewrite

mod_rewrite — это модуль веб сервера Apache, использующийся для преобразования URL адресов. Под преобразованием следует понимать фактически любые действия с URL. Это очень мощное и в то же время гибкое средство, имеющее очень широкие возможности. Модуль позволяет производить практически любые типы преобразований. С помощью mod_rewrite можно настраивать редиректы, изменять URL адреса, блокировать доступ и т.д. Он поддерживает неограниченное количество правил преобразования, регулярные выражения, обратные связи с группированными частями шаблона, разные источники информации для преобразований (переменные сервера, HTTP заголовки, время и т.д.). За счет такого набора возможностей, достигается высокая функциональность и гибкость. По умолчанию этот модуль выключен, для того что бы его включить, в .htaccess необходимо добавить следующие директивы:

RewriteEngine On
RewriteBase /

RewriteEngine On — директива включает модуль.
RewriteBase — указывает путь от корня сайта до файла .htaccess. Если .htaccess лежит в корне, то указывать этот параметр нужно как в примере, если во внутреннем каталоге, то указываем путь к этому каталогу, например /images.

Принцип работы модуля mod_rewrite

Работа модуля основана на наборе правил и условий, согласно которым производится преобразование. При получении запроса, Apache передает в mod_rewrite путь к файлу начиная от того места, где находится файл .htaccess, остальная часть пути обрезается. Если поступил запрос http://some-url.com/cat/cat2/file.html, а .htaccess лежит в корне, то в mod_rewrite попадет cat/cat2/file.html (без слеша в начале). Если .htaccess лежите в директории /cat, то в mod_rewrite попадет cat2/file.html. Далее mod_rewrite анализирует правила в .htaccess и действует согласно этих правил. Стоит знать, что mod_rewrite работает не со ссылками и не с URL адресами, а с обычными строками. То есть адрес, который нужно преобразовать, передается mod_rewrite как обычная строка, и эту строку можно преобразовать как угодно. Для построения правил используются две директивы, RewriteCond и RewriteRule (более детально эти директивы описаны ниже).​
RewriteCond — в этой директиве определяются условия, при которых сработает правило преобразования RewriteRule. Если условие в RewriteCond выполнено, выполняем правило в RewriteRule. Таких условий перед правилом RewriteRule может быть неограниченное количество. RewriteCond не является обязательной директивой для создания правила преобразования и может отсутствовать.
RewriteRule — здесь уже указывается само правило для преобразования, которое для конкретного преобразования должно быть единственным.
Пример, как это выглядит в .htaccess:

RewriteCond %{REQUEST_URI} !.(ico|css|js|txt)$ [NC]
RewriteCond %{REQUEST_FILENAME} !^/admin
RewriteRule ^(.*)$ /index.php [L]

Несмотря на то, что директива RewriteCond стоит выше, чем правило RewriteRule, mod_rewrite сначала проверяет строку на соответствие с шаблоном в RewriteRule, и если строка совпадает с шаблоном, он смотрит на указанные выше условия в RewriteCond. Если условия тоже совпадают, происходит преобразование согласно правилу RewriteRule. Рассмотрим подробней синтаксис и предназначение директив RewriteCond и RewriteRule.

RewriteCond

Как уже писалось выше, в этой директиве указываются условия, при которых правило в директиве RewriteRule будет выполнено. Эта директива выглядит так:

RewriteCond [строка_для_сравнения] [условие] [флаг]
RewriteCond %{REQUEST_URI} !.(ico|css|js|txt)$ [NC]

В этом примере правило условие будет выполнено, если запрос пользователя не содержит расширение ​ico,css,js или txt.
Строка для сравнения — кроме обычного текста может содержать регулярное выражение, обратные RewriteCond и RewriteRule связи и переменные сервера. На практике здесь используются переменные сервера и иногда регулярные выражения.
Условие — собственно это то, с чем сравнивается строка для сравнения. Может содержать текст, регулярные выражения и специальные символы:

  • "-d" — проверяет правильность пути (его существование) и является ли этот путь, путем к каталогу.
  • "-f" — проверяет правильность пути (его существование) и является ли этот путь, путем к обычному файлу.
  • "-s" — то ж, что и -f, но дополнительно проверяет, что размер файла больше 0 (ноля).
  • "-l" — проверяет правильность пути (его существование) и является ли этот путь символической ссылкой.
  • "-F" — проверяет через внутренний подзапрос, является ли сравниваемая строка реально существующим файлом, при этом используются все существующие списки контроля доступа сервера. Это негативно сказывается на производительности, стоит использовать осторожно.
  • "-U" — проверяет через внутренний подзапрос, является ли сравниваемая строка реально URL адресом, при этом используются все существующие списки контроля доступа сервера. Это негативно сказывается на производительности, стоит использовать осторожно.
Дополнительно, перед условием, допускается использование логических символов:
  • "!" — инвертирование значения, указывает на то, что сравниваемая строка должна не соответствовать шаблону условия.
  • "<" — лексически меньше. Например символ "a" лексически меньше символа "b", "a" < "b".
  • ">" — лексически больше.
  • "=" — равенство, используется по умолчанию.

Флаг — необязательный параметр, в котором указываются дополнительные опции (через запятую, если их несколько). Указывается в конце правила в квадратных скобках [].

  • [NC] — регистронезависимый, то есть регистр (A-Z или a-z) в строке для сравнения или в условии не имеет значения.
  • [OR] — логическое ИЛИ. Используется, когда перед директивой RewriteRule находится несколько директив RewriteCond и правило в RewriteRule должно быть выполнено при совпадении одного из RewriteCond.​ Если флаг OR не указан, RewriteRule сработает только при соответствии всех директив RewriteCond.

RewriteRule

​В RewriteRule указывается правило для преобразования, то, как мы хотим изменить URL. По факту эта директива также содержит условие, при совпадении которого, будет произведено преобразование. Это шаблон, с которым сверяется полученная mod_rewrite строка. Стоит отметить, что если ничего подставлять не нужно, а такие случаи иногда происходят, в новом значении необходимо указать прочерк "-". Схематически правило RewriteRule выглядит следующим образом:

RewriteRule [шаблон] [новое_значение] [флаг]
RewriteRule ^(.*)$ /index.php [L]

Шаблон — то, с чем будет сравниваться исходная строка. Исходная строка необязательно является той, которую запросил пользователь. Она могла быть ранее изменена другими правилами RewriteRule. Может содержать обычный текст, регулярные выражение и обратные RewriteCond и RewriteRule связи. Исходная строка, это путь от файла .htaccess до файла, доменного имени там нет.
Новое значение — это значение, на которое будет изменена исходная строка после преобразования. Может содержать обычный текст, регулярные выражение, обратные RewriteCond и RewriteRule связи и переменные сервера.
Флаг — ​необязательный параметр, в котором указываются дополнительные опции, (через запятую, если их несколько). Указывается в конце правила в квадратных скобках [].

  • [R=code] — редирект. code — это код ответа браузеру, по умолчанию используется 302 (временно перемещен), поэтому для постоянного редиректа используйте код 301.
  • [F] — запрет доступа к URL, Forbidden. Сервер возвращает браузеру ошибку с кодом 403.
  • [G] — возвращает ошибку 410, URL не существует.
  • [P] — Apache выполняет подзапрос к указанному адресу с использование другого модуля Apache mod_proxy.
  • [L] — последнее правило. Говорит о том, что на этом месте следует остановить преобразование URL.
  • [N] — процесс преобразований будет запущен опять, начиная с самого первого правила. Будет использована уже модифицированная ранее строка.
  • [C] — связь со следующим правилом, создается цепочка правил. Если правило не соответствует, все последующие правила в цепочке пропускаются.
  • [NS] — срабатывают правила только для запросов, подзапросы игнорируются.
  • [T] — принудительно указать MIME-тип файла.
  • [NC] — не учитывать регистр символов.
  • [QSA] — дополнять строку запроса, а не заменять ее. Флаг стоит использовать при работе с GET параметрами в переменной %{QUERY_STRING}, что бы их не терять. Если это флаг не указан, данные в %{QUERY_STRING} будут полностью заменены параметрами из RewriteRule. Если флаг указан, новые параметры будут добавлены в начало %{QUERY_STRING}.
  • [NE] — запрещает преобразование специальных символов в их hex эквиваленты.
  • [PT] — останавливает преобразование и передает строку дальше для обработки другими директивами (Alias, ScriptAlias, Redirect и т.д.).
  • [S] — пропустить следующее правило. Есть возможность указать несколько правил в формате S=N, где N это количество правил.
  • [E=VAR:VAL] — установить переменную окружения, где VAR это имя переменной, а VAL ее значение.Значение может быть обратной RewriteCond и RewriteRule связью или текстом.
  • [CO=NAME:VAL:domain:lifetime:path:secure:httponly] — установить cookie в браузер. NAME — имя куки, VAL — значение, domain — имя домена, lifetime — время жизни (опционально), path — путь, для которого эта кука валидна, по умолчанию равна "/", secure — если установлено 1 или true, куки будут действительны только при https (безопасном) соединении, httponly — если установлено 1 или true, куки будут доступны для JavaScript.

Обратные связи RewriteCond и RewriteRule

Обратные связи, это возможность использования группы символов (заключенные в скобки "()") для их последующей подстановки. Например в скобках можно указать определенное регулярное выражение и таким образом охватить большое количество адресов.
$N — позволяет использовать группу символов из шаблона директивы RewriteRule.
%N — позволяет использовать группу символов из шаблона директивы RewriteCond.
Вместо символ "N" в обоих случаях используется число от 1 до 9.
На практике это выглядит следующим образом. Рассмотрим простой пример.
Есть адрес с определенной вложенность, http://some-url.com/cat1/cat2/cat3/cat4/page.html. Есть желание сделать страницу http://some-url.com/cat1/cat2/cat3/cat4/page.html доступной по адресу http://some-url.com/page.html, но кроме page.html, там есть куча других файлов с расширением html, которые также должны быть доступны по новому адресу. Это решается очень просто:

RewriteRule ^cat1/cat2/cat3/cat4/(.*).html$ $1.html

Теперь, при обращении к по адресу http://some-url.com/page.html, будет отображаться информация с адреса http://some-url.com/cat1/cat2/cat3/cat4/page.html и так со всеми адресами вида http://some-url.com/*.html. Точно также, с использованием "%N", можно подставлять группы символов из шаблона для RewriteCond. В данном примере, вместо $1 подставляется группа символов в скобках из шаблона.

Переменные сервера

​Переменные сервера могут содержать много полезной информации, которую можно и нужно использовать для построения правил. Ниже приведен список этих переменных:
HTTP_USER_AGENT — дает информацию о браузере и ОС пользователя. При посещении сайта пользователь, передается User Agent, по факту это обозначает ПО, с помощью которого производится доступ к сайту.
HTTP_REFERER — адрес страницы, с которой был осуществлен переход на сайт.
HTTP_COOKIE — список cookie, которые передает браузер.
HTTP_FORWARDED — адрес страницы, с который был переход. Большой разницы с HTTP_REFERER я не заметил.
HTTP_HOST — адрес сервера (сайта).
HTTP_ACCEPT — это пожелания клиента, по типу документа, который он хочет получить. На деле это выглядит так, браузер отправляет на сервер в http заголовке типы файлов, которые он хочет получить (обычно это относится к изображениям и другим медиа файлам), то есть сообщает, какой тип файла он может обработать.
REMOTE_ADDR — IP адрес посетителя.
REMOTE_HOST — адрес (хост) пользователя, который отдается командой "host" по IP адресу.
REMOTE_IDENT — имя пользователя в формате имя.хост.
REMOTE_USER — то же самое что и REMOTE_IDENT, но не содержит хост пользователя.
​REQUEST_METHOD — тип запроса к сайту (GET, POST, HEAD).
SCRIPT_FILENAME — полный путь к запрошенному файлу или адресу.
PATH_INFO — данные, которые передавались в скрипт.
QUERY_STRING — строка, переданная как запрос в CGI скрипт, GET параметры.
AUTH_TYPE — тип идентификации пользователя.
DOCUMENT_ROOT — путь к корневой директории сервера.
SERVER_ADMIN — email администратора сервера.
SERVER_NAME — адрес (имя) сервера, отдаваемый командой host.
SERVER_ADDR — IP вашего сайта.
SERVER_PORT — порт, га котором работает Apache.
SERVER_PROTOCOL — версия http протокола.
SERVER_SOFTWARE — используемая версия Apache.
TIME_YEAR, TIME_MON, TIME_DAY, TIME_HOUR, TIME_MIN, TIME_SEC, TIME_WDAY, TIME — время.
API_VERSION —версия API модуля Apache.
THE_REQUEST — строка содержит весь http запрос, отправленный браузером на сервер (GET /index.html HTTP/1.1). Здесь не включены дополнительные заголовки.
REQUEST_URI — адрес, запрошенный в http заголовке.
REQUEST_FILENAME — полный путь к запрошенному файлу, по факту содержит те же данные, что и SCRIPT_FILENAME.
IS_SUBREQ — проверка на подзапрос. Если да — ответ true, если нет — ответ false.
Список переменных вашего сервера, вы можете легко узнать поместив в корень сайта php файл с кодом:

phpinfo () ;
?>

Набрав адрес этого файла в браузере, внизу страницы вы получите информацию о переменных сервера.

Комментарии (7)
Darius # 20 ноября 2017 в 05:55 0
Otlichnaja statja. Bol'shoje sposibo!
Карен # 19 июня 2018 в 13:16 0
Наверно одна из немногочисленных статей о mod_rewrite в которой все толково объясняется. Спасибо за труд!
Администратор # 19 июня 2018 в 22:17 -1
Рад что вам понравилась статья.
Юрий # 11 сентября 2018 в 11:00 0
Здесь напутано:

RewriteRule ^cat1/cat2/cat3/cat4/(.*).html$ $1.html
Теперь, при обращении к по адресу http://some-url.com/page.html, будет отображаться информация с адреса http://some-url.com/cat1/cat2/cat3/cat4/page.html

Согласно правилу, наоборот, обращаясь по URL соот-его шаблону ^cat1/cat2/cat3/cat4/(.*).html$ идёт преобразование к адресу $1.html

+ на странице не работает Ответить в хроме
Олег # 5 декабря 2018 в 15:29 0
Спасибо, хорошая статья. После прочтения более-менее разобрался в работе mod_rewrite.
Эдуард # 13 февраля 2019 в 17:58 0
Огромное спасибо. Нашел то, что искал.
Владимир # 4 февраля 2020 в 11:06 0
Здравствуйте, Александр. (Если я правильна срисовал адрес почты из Инета)

Позвольте обратиться, - нужен совет по редиректам.
Хочу попробовать следующий вариант:

DirectoryIndex start.php
RewriteEngine on
RewriteRule ^ start.php

Эта штука работает. Я хочу получать на вход любой URI, и внутри программы разбираться, что отдать обратно: 404, 410, 301, 302 или 200.
Т.е., как я понимаю, технически это работает. А как насчёт практического использования? И как прореагируют роботы-индексировщики?
Добавить комментарий
© 2012-2023 Hostgid.net. Все права защищены.