Модуль mod_rewrite сервера Apache

17.08.2018

Теги: .htaccessApacheRegExpSEOURLWeb-разработкаЧПУШаблон

Модуль mod_rewrite веб сервера Apache используется для преобразования URL адресов. С его помощью можно настраивать редиректы, изменять URL адреса, блокировать доступ и т.д. По умолчанию этот модуль выключен, для того что бы его включить, в .htaccess необходимо добавить следующие директивы:

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

Если .htaccess лежит в корне, то директиву RewriteBase можно опустить.

Работа модуля основана на наборе правил и условий, согласно которым производится преобразование. При получении запроса, Apache передает в mod_rewrite путь к файлу начиная от того места, где находится файл .htaccess, остальная часть пути обрезается. Если поступил запрос

http://server.com/some/path/file.html

а .htaccess лежит в корне, то в mod_rewrite попадет some/path/file.html (без слеша в начале). Если .htaccess лежит в директории /some/, то в mod_rewrite попадет path/file.html.

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

  • Директива RewriteCond — здесь определяются условия, при которых сработает правило преобразования RewriteRule. Если условие в RewriteCond выполнено, выполняется правило в RewriteRule. Таких условий перед правилом RewriteRule может быть неограниченное количество. RewriteCond не является обязательной директивой для создания правила преобразования и может отсутствовать.
  • Директива RewriteRule — здесь уже указывается само правило для преобразования, которое для конкретного преобразования должно быть единственным.

Директива RewriteRule

Синтаксис директивы RewriteRule:

RewriteRule Шаблон Подстановка [Флаги]
  • Шаблон — условие, выполнение которого запускает исполнение правила;
  • Подстановка — правило изменения (преобразования) URL;
  • [Флаги] — дополняют преобразование URL.

Примеры:

# Преобразуем URL www.server.com/articles/123/ в
# URL www.server.com/index.php?show=article&id=123
RewriteRule ^articles/(\d+)/$ index.php?show=article&id=$1 [L]
# Запрет посещений веб-сайта для робота поисковой системы
# Google (при вызове возвращает ошибку 403 Forbidden)
RewriteCond %{USER_AGENT} Googlebot
RewriteRule .* - [F]

Дефис вместо Подстановка означает, что преобразование URL не требуется.

# Исправление ошибки при наборе адреса веб-страницы пользователем
RewriteRule ^(.*)\.htm$ $1.html [R=301]

Некоторые флаги RewriteRule:

  • [NC] — Это делает Шаблон нечуствительным к регистру, когда Шаблон применяется к текущему URL.
  • [QSA] — Добавить строку запроса из исходного URL к строке запроса, созданной правилами перезаписи.
  • [L] — Остановить процесс преобразования на этом месте и не применять больше никаких правил преобразований.
  • [N] — Перезапустить процесс преобразований (начав с первого правила). В этом случае URL снова сопоставляется неким условиям, но не оригинальный URL, а URL вышедший из последнего правила преобразования.
  • [F] — Сервер возвращает браузеру ошибку с кодом 403.
  • [R] — Редирект с кодом ответа браузеру 302 (временно перемещен).
  • [R=code] — Редирект с кодом ответа браузеру code.

Флаг QSA (Query String Append)

Строкой запроса является часть запрашиваемого адреса, которая следует после символа знак вопроса. К примеру, в запросе

/some/path/index.php?param=value

строкой запроса является выделенная красным часть.

Когда заменяющий URI (полученный после применения правил перезаписи) содержит строку запроса, поведение по умолчанию RewriteRule — отбросить исходную строку запроса и заменить её сгенерированной новой. Использование флага [QSA] приводит к объединению строк запроса.

# Преобразуем URL www.server.com/articles/123/ в
# URL www.server.com/index.php?show=article&id=123
RewriteRule ^articles/(\d+)/$ /index.php?show=article&id=$1 [QSA,L]

С флагом [QSA], запрос

/articles/123/?param=value

будет преобразован в

/index.php?show=article&id=123&param=value

Без флага [QSA], этот же самый запрос будет преобразован в

/index.php?show=article&id=123

То есть, существующая строка запроса будет отброшена.

Директива 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

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

СравниваемаяСтрока может, к примеру, содержать часть или весь 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. Этот флаг используется по умолчанию, так что его можно опускать.

Регулярные выражения

Текст

  • . — Любой одиночный символ
  • [chars] — Класс символов: один из символов
  • [^chars] — Класс символов: ни один из символов
  • (text1|text2) — Альтернатива: text1 или text2

Кванторы

  • ? — 0 или 1 из предшествующего текста
  • * — 0 или больше из предшествующего текста
  • + — 1 или больше из предшествующего текста

Группировка

  • (text) — Группировка текста (для установки границ альтернативы или для создания переменных $1, $2, $3 или %1, %2, %3)

Маркеры

  • ^ — Маркер начала строки
  • $ — Маркер конца строки
  • Экранирование

    • \char — экранирование конкретного символа (к примеру, для указания символов .[]() и т.д.)

    Переменные окружения сервера

    Если запрашивается документ:

    http://www.host16.ru/some/path/index.php?param=value

    то переменные окружения сервера будут:

    Переменная Описание Значение
    DOCUMENT_ROOT Путь к корневой папке сайта. Зависит от операционной системы сервера и используемого программного обеспечения. D:/work/localhost16/www
    HTTP_ACCEPT Типы файлов, которые способен принять браузер. В качестве значения возвращается список поддерживаемых MIME-типов разделенных между собой запятой. text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, image/apng, */*;q=0.8
    HTTP_HOST Доменное имя сайта. Переменная вернёт тот адрес сайта, который указан в адресной строке браузера. www.host16.ru
    HTTP_REFERER Адрес страницы, с которой пользователь перешел на данный сайт, он еще называется реферер.
    HTTP_USER_AGENT Идентификатор используемого браузера и операционной системы. В качестве значения возвращается строка, содержащая ключевые слова. Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
    QUERY_STRING Запрос, который указан в адресной строке после вопросительного знака. param=value
    REMOTE_ADDR IP-адрес посетителя сайта 127.0.0.1
    REQUEST_FILENAME Полный путь в файловой системе сервера к файлу или скрипту. По факту содержит те же данные, что и SCRIPT_FILENAME. D:/work/localhost16/www/some/path/index.php
    REQUEST_METHOD Метод отправки данных на сервер, по умолчанию применяется метод GET. GET
    REQUEST_URI Адрес запрашиваемого документа, отсчёт ведётся от корня сайта. /some/path/index.php?param=value
    SERVER_PROTOCOL Протокол для получения и отправки данных. HTTP/1.1
    SCRIPT_NAME Путь к текущему исполняемому скрипту. /some/path/index.php
    SCRIPT_FILENAME Абсолютный путь к исполняемому скрипту. D:/work/localhost16/www/some/path/index.php
    SERVER_NAME Имя сервера. www.host16.ru
    THE_REQUEST Полная строка HTTP запроса, отправленная браузером серверу. Она не включает какие-либо дополнительные заголовки, отправляемые браузером. GET /some/path/index.php?param=value HTTP/1.1

    Переменные подстановки RewriteCond и RewriteRule

    Если в директивах RewriteCond и/или RewriteRule часть символов заключить в круглые скобки, то можно обращаться к содержимому в этих скобках через переменные $1, $2, $3 и/или %1, %2, %3:

    • $n — позволяет использовать группу символов из шаблона директивы RewriteRule;
    • %n — позволяет использовать группу символов из шаблона директивы RewriteCond.
    # Редирект с адреса с www на адрес без www
    RewriteCond %{HTTP_HOST} ^www\.server\.com$ [NC]
    RewriteRule ^(.*)$ http://server.com/$1 [R=301,L]
    # Редирект с адреса с www на адрес без www
    RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
    RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
    # Редирект с адреса без www на адрес с www
    RewriteCond %{HTTP_HOST} ^server\.com$ [NC]
    RewriteRule ^(.*)$ http://www.server.com/$1 [R=301,L]
    # Редирект с адреса без www на адрес с www
    RewriteCond %{HTTP_HOST} !^www\.(.*) [NC]
    RewriteRule ^(.*)$ http://www.%1/$1 [R=301,L]

    Примеры

    # запретить использование ссылок на изображения другими сайтами
    RewriteCond %{HTTP_REFERER} !^$
    RewriteCond %{HTTP_REFERER} !^http://(www\.)?server\.com/.*$ [NC]
    RewriteRule .+\.(gif|jpe?g|png)$ - [F]
    # перенаправление с HTTP на HTTPS
    RewriteCond %{HTTPS} =off
    RewriteRule (.*) https://%{SERVER_NAME}/$1 [R=301,L]
    # перенаправление с HTTP на HTTPS
    RewriteCond %{SERVER_PORT} !=443
    RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
    # запрет доступа к файлу .htaccess
    RewriteRule ^\.htaccess$ - [F]
    # запрет доступа к сайту поисковому роботу EmailSiphon
    RewriteCond %{HTTP_USER_AGENT} ^EmailSiphon
    RewriteRule .* - [F]
    # запрет доступа к сайту с ip-адреса 212.37.64.10
    RewriteCond %{REMOTE_ADDR} ^212.37.64.10$ 
    RewriteRule .* - [F]
    # редирект страниц со слэшем в конце на страницы без слэша,
    # чтобы исключить дублирвание; например /about/ => /about
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} ^(.+)/$
    RewriteRule ^(.+)/$ $1 [R=301,L]
    # редирект страниц без слэша в конце на страницы со слэшом,
    # чтобы исключить дублирвание; например /about => /about/
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_URI} !(.*)/$
    RewriteRule ^(.*[^/])$ $1/ [R=301,L]

    Поиск: .htaccess • Apache • RegExp • SEO • URL • Web-разработка • ЧПУ • Шаблон • mod_rewrite • RewriteEngine • RewriteBase • RewriteCond • RewriteRule

    Каталог оборудования
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    Производители
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    Функциональные группы
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.