Содержание:
- Немного теории
- Что такое mod_rewrite
- Как работает модуль
- Правило преобразования URL RewriteRule
- Директива RewriteCond
- Примеры
- Битрикс
В сегодняшней статье рассмотрим работу модуля mod_rewrite сервера Apache, и как с помощью правил RewriteRule и RewriteCond работать с URL. Поговорим про описание и логику работы правила RewriteRule, а так же синтаксис некоторых директив модуля mod_rewrite.
Немного теории
Веб-сайты работают благодаря серверам — компьютерам с установленным программным обеспечением, отвечающим за передачу информации от физических хранилищ до браузера пользователя.
Apache — это программное кроссплатформенное обеспечение, основное назначение которого HTTP-сервер.
HTTP сервер или веб-сервер — это программа, которая понимает, что нужно клиенту и выдает ему ответы в виде HTML страниц, на которых может содержаться различная информация: изображения, тексты, скрипты, файлы, медиаданные (видео и аудио) и многое другое.
Apache является самым популярным ПО для веб-серверов в мире, благодаря простоте, гибкости в настройке, надежности, производительности и модульности.
.htaccess — конфигурационный файл Apache, в котором директивами (командами), задаются параметры для работы сервера: разрешение или запрет доступа к директориям, переназначение типов файлов, оптимизация скорости загрузки (можно задать кэш для файлов). Файл .htaccess располагается в корневой директории сервера и распространяется на весь сервер, кроме директорий, где находится другой файл.
Чтобы сервер мог работать с директивами, активируйте модуль mod_rewrite в конфигурационном файле (*.conf). Настройка этого модуля, происходит в файле .htaccess. Как это сделать будет описано ниже.
Команда подключения модулей (LoadModule) прописывается в конфигурационном файле Apache. В зависимости от системы может располагаться:
- Linux, CentOS, Fedora (Redhat-системы) — /etc/httpd/conf/httpd.conf;
- Apache 2.2 — /etc/apache2/apache2.conf;
- Gentoo, Apache 2.0 — /etc/apache2/httpd.conf.
Включить и отключить модуль Apache можно с помощью следующих команд:
a2enmod
a2dismod
Например, подключение модуля rewrite_module происходит с помощью консольной команды:
sudo a2enmod rewrite - включить модуль
sudo systemctl restart apache2 - перезагрузить Apache что бы применилась активация
Если используется Apache в Windows, то для включения mod_rewrite в файле httpd.conf (C:\Server\bin\Apache24\conf\httpd.conf) найдите и раскомментируйте строку:
LoadModule rewrite_module modules/mod_rewrite.so
Для этого уберите перед строкой знак “#”.
Также используйте знак решетки если не работает что-то из директив. Поставьте ее перед строкой с кодом. Это позволит закомментировать не нужный Вам текст программа при чтении пропустит данную строку.
Что такое mod_rewrite
Это модуль сервера Apache (программа, работающая на стороне сервера), выполняющий действия с URL, такие как: создание редиректов, ЧПУ, ограничения доступа к директориям на веб-сайте. Главная задача — преобразования URL-ов.
Например, рассмотрим перенаправление всех страниц домена oldsite.com на соответствующие страницы newsite.com.
RewriteCond %{HTTP_HOST} ^oldsite\.com
RewriteRule ^(.*)$ http: //newsite .com/$1 [R=301,L]
Как работает модуль
В своей работе mod_rewrite использует регулярные выражения. В них используются специальные символы (метасимволы) и обычные символы (литералы). Основными метасимволами являются: [ ] \ / ^ $ . | ? * + ( ) { }, где наиболее часто используемые спецсимволы:
^ — начало строки;
$ — конец строки;
. — любой символ;
* — любое количество любых символов;
? — один определенный символ;
[0-9] — последовательность символов, например, от 0 до 9;
| — символ «или», выбирается или одна группа, или другая;
() — используется для выбора групп символов.
Порядок обработки правил (команд) прописывается в .htaccess, и составляются примерно в таком порядке:
<IfModule mod_rewrite.c> (проверяем что модуль включен)
RewriteEngine on (один раз сверху)
RewriteCond %{что сравнивать} с чем сравнивать [флаги]
RewriteRule исходный url целевой url [флаги]
</IfModule>
Если указано условие RewriteEngine off, то блок IfModule с кодом - будет проигнорирован и не выполнится.
Где:
- RewriteEngine включает или отключает преобразование http-ссылок;
- RewriteCond - условие, которое должно быть соблюдено перед выполнением правила, условий может быть несколько;
- RewriteRule - собственно само правило, которое выполняется при соблюдении условия.
Порядок размещения правил в .htaccess важен, потому что механизм преобразований обрабатывает их в специальном порядке. Условия (RewriteCond) всегда должны быть перед правилами (RewriteRule)!
Правило преобразования URL RewriteRule
Синтаксис директивы RewriteRule:
RewriteRule Шаблон Подстановка [Флаги]
Например:
RewriteRule ^(.*)$ index.php?/$1 [L,QSA]
Где:
- RewriteRule это директива;
- Шаблон — это символы ^(.*)$. Регулярное выражение применяемое к текущему URL. Читается так. Искать в строке URL от начала строки(^) до конца( $) любой символ (знак .) в количестве от нуля до бесконечности (знак *).
Например:
^stena - Любые строки, начинающиеся со слова stena. Строка, начинающаяся со слова dom-stena не удовлетворит критерию;
stena$ - Любые строки, заканчивающиеся набором символов stena. Строка, заканчивающаяся на stena-dom под выбор не попадёт;
[0-9]{1,6}$ - Выбрать все строки, оканчивающиеся от 1 до 6 цифрами из диапазона от 0 до 9.
В регулярных выражениях есть скобки(). Поэтому часть URL соответствующая условию в скобках добавляется в переменную подстановки $1, которая используется в Подстановке или в Сравниваемая Строка (это в директиве RewriteCond, о ней ниже); - Подстановка — index.php?/$1. Правило преобразования URL. Запись означает, что строка нового, измененного URL должна быть составлена из двух частей, где первая часть строки постоянное значение index.php?/, а вторая часть — значение из переменной подстановки $1. В $1 храниться та часть URL которая соответствовала части регулярного выражения в скобках из параметра Шаблон. Мы получаем преобразованный URL вида index.php?/URL по которому обратились;
- [L,QSA] – флаги. Правило означающее, что необходимо остановить процесс преобразования на этом месте и не применять больше никаких следующих правил преобразований для URL. Дополняют преобразование URL Третий аргумент директивы RewriteRule.
Рассмотрим флаги RewriteRule подробнее:
- [NC]. Делает шаблон нечувствительным к регистру, когда он применяется к текущему URL;
- [QSA]. Добавляет строку запроса из исходного URL к строке запроса, созданной правилами перезаписи;
- [L]. Останавливает процесс преобразования на этом месте и не применяет больше никаких правил преобразований;
- [N]. Перезапускает процесс преобразований (начав с первого правила). В этом случае URL снова сопоставляется неким условиям, но не оригинальный URL, а URL вышедший из последнего правила преобразования;
- [F]. Веб-сервер возвращает браузеру ошибку с кодом 403;
- [R]. Редирект с кодом ответа браузеру 302 (временно перемещен);
- [R=code]. Редирект с кодом ответа браузеру code;
- [B] (escape backreferences) - заставляет экранировать (кодировать) спец-символы, например взять правило "RewriteRule ^search/(.*)$ /search.php?term=$1" в котором есть строка поиска, которая может содержать к примеру 'x & y/z' и в результате будет возвращена строка 'search.php?term=x & y/z', что неявляется допустимым УРЛ и будет преобразовано браузером в "search.php?term=x%20&y%2Fz=". С флагом [B] строка будет преобразована в "/search.php?term=x%20%26%20y%2Fz". Для работы этого примера понадобится установить AllowEncodedSlashes в On ибо httpd по-умолчанию не позволяет кодировать слэши в УРЛ;
- [C] chain - объединить несколько правил в цепочку. Если первое правило цепочки не удовлетворяет условиям, тогда вся цепочка будет проигнорирована;
- [CO] cookie - устанавливает cookie в формате [CO=NAME:VALUE:DOMAIN:lifetime:path:secure:httponly], параметры для secure и httponly устанавливаются как true|false;
- [DPI] discardpathinfo - отбрасывает PATH_INFO в преобразованной ссылке, полезно использовать в случаях, когда PATH_INFO уже был добавлен в предыдущем преобразовании;
- [E] env - установить переменную [E=VAR:VAL] или удалить её [E=!VAR];
- [F] forbidden - возвращает ошибку 403;
- [G] gone - возвращает ошибку 410;
- [H] handler - принудительно устанавливает обработчик для определённых типов файлов, например правило "RewriteRule !\. - [H=application/x-httpd-php]" заставит пропустить через PHP все файлы без расширения;
- [L] last - указывает, что правило является последним и процесс дальнейшего преобразования прекращается;
- [N] next - начинает процесс преобразования с первого по порядку правила, используйте этот флаг с осторожностью ибо он может привести к замкнутому циклу (т.н. петля);
- [NC] nocase - отключает проверку регистра символов;
- [NE] noescape - mod_rewrite обычно применяет правила экранирования URI к результату преобразования. Спецсимволы (такие как '%', '$', ';', и так далее) будут экранированы их шестнадцатеричными (hexcode) подстановками ('%25', '%24', и '%3B', соответственно). Этот флаг запрещает делать это;
- [NS] nosubreq - игнорировать подзапросы, выполнять правило только для настоящих/прямых запросов;
- [P] proxy - Apache выполняет подзапрос к указанной странице с использованием программного модуля mod_proxy, при этом клиент об этом подзапросе ничего не узнает. Произойдет ошибка если модуль mod_proxy не подключен;
- [PT] passthrough - остановить преобразование и передать полученную новую ссылку дальше;
- [QSA] qsappend - добавляет исходные параметры запроса (query string) к замене. Если в подстановку не включаются новые параметры запроса, то исходные параметры запроса будут добавлены автоматически. Если же новые параметры включаются в подстановку, то исходные параметры запроса будут утеряны если не указать флаг QSA;
- [R] redirect - возвращает браузеру команду на перенаправление (по-умолчанию код 302 - MOVED TEMPORARY), код редиректа можно указать самостоятельно, например R=301 (код 301 - MOVED PERMANENTLY), но в границах 300-399, в противном случае правило не будет обработано;
- [S] skip - пропускает следующее правило, если данное правило сработало. Можно указать количество правил, например: S=2;
- [T] type - принудительно устанавливает MIME-тип целевого файла. К примеру, "RewriteRule \.pl$ - [T=text/plain]", это правило отобразит Perl скрипты в текстовом формате, а значит код скрипта будет выдан в браузер.
rewriterule примеры
Создание понятных для человека URL
ЧПУ — расшифровывается как Человекопонятный URL. Это ссылки которые визуально имеют упрощенную структуру. Ее проще запомнить.
Например, Ссылки вида http://site.com/?page=contacts нужно привести к http://site.com/contacts/.
Все в файле .htaccess пропишите:
RewriteRule ^contacts/?$ ?page=contacts [L,QSA]
RewriteRule ^news/?$ ?page=news [L,QSA]
RewriteRule ^news/([^/]+)/?$ ?page=news&slug=$1 [L,QSA]
Преобразования происходит благодаря флагу QSA (query string append), прописанному в квадратных скобках после каждого правила. Если строка запроса удовлетворяет правилу, она является эквивалентом указанного адреса, и выдает тот же самый контент.
Например, RewriteRule ^news/?$ ?page=news [L,QSA] и обратиться к сайту по адресу /news/, то:
- Строка запроса /news/ совпадет с указанным в правиле, значит это правило сработает;
- Флаг L (last) указывает, что после этого правила другие применяться не будут;
- Флаг QSA указывает на подстановку строки запроса и ее НЕ ЧПУ аналог;
- Строка запроса /news/ аналогична НЕ ЧПУ адресу ?page=news;
- По запросу /news/ выводится контент точно такой же, как и если набрать ?page=news.
Директива RewriteCond
Синтаксис директивы RewriteCond:
RewriteCond СравниваемаяСтрока Условие [Флаги]
Где:
- СравниваемаяСтрока — строка, которая проверяется на соответствие выражению, прописанному в параметре Условие;
- Условие — это логическое выражение, по которому проверяется параметр СравниваемаяСтрока. Часто в нем применяют регулярные выражения;
- [Флаги]. Задают дополнительные опции, например, можно установить логику объединения правил RewriteCond через логическое И [AND] (по умолчанию) или через логическое ИЛИ [OR]. Или, будет ли сравнение в условии RewriteCond выполнятся с учетом регистра или без учета регистра.
Пример директив RewriteCond, объединенных через логическое И [AND] (по умолчанию):
# одна точка входа, все запросы (кроме файлов и директорий) на /index.php
RewriteCond $1 !=favicon.ico
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php
СравниваемаяСтрока:
- может, содержать часть или весь URL.
- содержит часть URL можно при помощи переменных подстановки ($1, $2, $3), которые были созданы в соответствующем RewriteRule.
- содержит различные переменные из окружения сервера Apache: %{REQUEST_URI}, %{HTTP_HOST}, %{QUERY_STRING}.
Условие может содержать специальные символы:
- -d — проверка, что директория существует;
- -f — проверка, что файл существует.
Дополнительно, перед условием, допускается использование логических символов:
- !Условие — инвертирование значения, т.е. сравниваемая строка должна не соответствовать шаблону условия;
- =Условие — Условие считается простой строкой и лексически сравнивается с СравниваемаяСтрока. Истинно, если эти две строки полностью одинаковы (символ в символ). Если Условие имеет вид "" — это сравнивает СравниваемаяСтрока с пустой строкой.
Некоторые флаги RewriteCond:
- [NC] (от No Case). Регистр не имеет значения, как в СравниваемаяСтрока так и в Условие. Этот флаг эффективен только для сравнений между СравниваемаяСтрока и Условие, он не работает при проверках в файловой системе.
- [OR]. Логическое ИЛИ. Используется, когда перед директивой RewriteRule находится несколько директив RewriteCond и правило в RewriteRule должно быть выполнено при совпадении любого RewriteCond;
- [AND]. Логическое И. Используется, когда перед директивой RewriteRule находится несколько директив RewriteCond и правило в RewriteRule должно быть выполнено при совпадении всех RewriteCond. Этот флаг используется по умолчанию, так что его можно опускать.
Пример 1. Правила с набором условий:
RewriteCond $1 !^(index\.php|images|robots\.txt|public) [NC]
RewriteCond %{REQUEST_URI} !\.(css|js|jpg|gif|png)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L,QSA]
Блок директив содержит правило преобразования url и дополнительные условия. Смысл блока в следующем. Для любого url запустить правило перезаписи url. Проверить что url:
- Не начинается как index.php или images или robots.txt или public – т.е. не начинается на открытые нами к прямому обращению файлы и каталоги.
- Не заканчивается на .css или .js или. Не является файлом к которым мы позволяем обращаться напрямую;
- Не является реальным файлом на диске и директорией.
Если условия выполняются собрать новую строку url из двух строк. Где первая строка «index.php?/» вторая — первоначальный url.
Флаг L – закончить на этом правиле все преобразования. Флаг QSA — добавить значение из $1 к результирующей строке URL, а не заменить ее.
Разберем первое дополнительное условие из примера:
RewriteCond $1 !^(index\.php|images|robots\.txt|public) [NC]
Где:
- В параметре СравниваемаяСтрока прописывается выражение $1 – это переменная подстановки, в которой находится значение из круглых скобок, взятых из параметра Шаблон директивы RewriteRule. В параметре Шаблон содержится: ^(.*)$. Это означает, что в параметр СравниваемаяСтрока подставиться весь URL;
- Параметр Условие содержит оператор инверсии (!)условия и регулярное выражение, возвращающее результат применения его к параметру СравниваемаяСтрока. В данном случае параметр Условие звучит как: не начинается с символов: index.php или images или robots.txt или public;
- Флаг [NC]. Сравнивает регистр. Это дополнительное условие понимаем как: если без учета регистра URL не начинается с символов index.php, images, robots.txt, public то условие истинно.
Примеры
Если изначально в индекс поисковой системы попала версия «с www», в файл .htaccess добавляется редирект на «без www»:
RewriteCond %{HTTP_HOST} ^www.name\.site$ [NC]
RewriteRule ^(.*)$ http://name.site/$1 [R=301,L]
Если произошла обратная ситуация и необходима переадресация с без «www» на «www», то в файл прописывается:
RewriteCond %{HTTP_HOST} ^v name\.site$ [NC]
RewriteRule ^(.*)$ http://www.name.site/$1 [R=301,L]
В случае перехода на защищенный протокол https для всего сайта, необходимо настроить перенаправление с http на https, для этого в файл .htaccess добавьте:
RewriteCond %{SERVER_PORT} !^443$
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
Если данная конструкция не сработает, попробуйте другой вариант:
RewriteCond %{HTTPS} =on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [QSA,L]
Если циклическое перенаправление на страницах осталось, попробуйте такой вариант:
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Если редирект не работает и в этом случае, попробуйте такой вариант:
RewriteEngine On
RewriteCond %{SERVER_PORT} !^443$
RewriteCond %{REQUEST_URI} =/page.php
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R,L]
Редирект на .html
Пример, редирект с c site.ru/blog на site.ru/blog.html.
RewriteCond %{REQUEST_URI} (.*/[^/.]+)($|\?)
RewriteRule .* %1.html [R=301,L]
RewriteRule ^(.*)/$ /$1.html [R=301,L]
Редирект на страницу без слеша в конце адреса
Пример, редирект с c site.ru/blog/ на site.ru/blog.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [R=301,L]
Редирект на страницу со слешем в конце адреса
RewriteCond %{REQUEST_URI} (.*/[^/.]+)($|\?)
RewriteRule .* %1/ [R=301,L]
Редирект на страницу без index.php в адресе
RewriteRule ^index.php/(.*)$ http://mysite.ru/$1 [R=permanent,L]
Редирект на страницу без index.php в конце адреса
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.php\ HTTP/
RewriteRule ^index\.php$ http://site.ru/ [R=301,L]
Битрикс
Для перенаправления на новую страницу достаточно отредактировать файл .htaccess, внеся в него такой редирект:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.sng-it.ru$ [NC]
RewriteRule ^(.*)$ http://sng-it.ru/$1 [R=301,L]
Простой редирект
RewriteRule ^news/happy.* /news.html [R=301,L]
Для простого редиректа условия задавать не обязательно, только правило.
Реврайт без редиректа
RewriteRule ^news/happy.* /news.html [L]
Иногда требуется, чтобы был редирект без смены адреса, т.е. реврайт без редиректа. Для этого просто не указываем флаг редирект (R), и получаем желаемый результат, теперь по адресу news/happy получим news.html, а в адресной строке останется news/happy
Редирект на мобильную версию веб-сайта
Допустим, что мобильная версия расположена поддомене m.site.ru. Переход будет происходить с главной страницы основного домена.
RewriteCond %{HTTP_USER_AGENT}
(?i:midp|samsung|nokia|j2me|avant|docomo| novarra|palmos|palmsource| opwv|chtml|pda|mmp|blackberry|mib|symbian| wireless|nokia|hand|mobi|phone|cdm|upb|audio| SIE|SEC|samsung|HTC|mot-|mitsu|sagem|sony| alcatel|lg|eric|vx|NEC|philips|mmm|xx| panasonic|sharp|wap|sch|rover|pocket| benq|java|pt|pg|vox|amoi|bird| compal|kg|voda|sany|kdd|dbt| sendo|sgh|gradi|jb|dddi|moto| iphone|android) [NC]
RewriteCond %{HTTP_HOST} site.ru
RewriteRule ^$ http://m.site.com/ [R=302,L]
Рассмотрим подробнее код:
- Первая строка. Проверка USER_AGENT. Определяем что он относится к мобильной версии;
- Второй строкой проверяем что мы находимся на нужном домене;
- Третьей строкой, мы проверяем, что находимся на главной страницы и перенаправляем на поддомен.