Mod rewrite что это

Обновлено: 17.05.2024

Этичный хакинг и тестирование на проникновение, информационная безопасность

Как работает RewriteRule

RewriteRule просто преобразовывает строку в соответствии с регулярными выражениями, и все. RewriteRule работает со строкой, а не со ссылкой или путем до файла.

Как мы выяснили выше, на вход RewriteRule попадает путь от .htaccess до запрошенного файла. Удобнее всего теперь абстрагироваться от путей и ссылок и рассматривать то, с чем работает RewriteRule, как обычную строку. Эта строка передается от RewriteRule к RewriteRule, видоизменяясь, если какое-то из RewriteRule сработало.

  1. Взяли строку.
  2. Сравнили с регулярным выражением в первом аргументе.
  3. Если есть совпадение — заменили всю строку на значение второго аргумента.
  4. Передали строку следующему RewriteRule.

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

Здесь нужно сделать замечание: хоть RewriteRule и работает с чистой строкой, она все-таки ориентирована на работу со ссылками. Поэтому она будет по-особому реагировать на строки, начинающиеся на «https://» или аналоги (запомнит, что мы хотели сделать внешний редирект) и на символ "?" (посчитает следующие символы аргументами, которые нужно будет подставить к запросу). Однако сейчас нас это не интересует — важно понять, что в RewriteRule нет никакой магии — она просто берет строку и изменяет ее так, как вы ей сказали. Внешние редиректы и аргументы мы рассмотрим позже в статье, там тоже есть, о чем поговорить.

После того как все преобразования произведены и выполнено последнее RewriteRule, вступает в силу RewriteBase.

Разница в работе mod_rewrite в контексте .htaccess и в контексте VirtualHost

В контексте <VirtualHost> mod_rewrite работает с точностью до наоборот.
  • В <VirtualHost> в RewriteRule попадает весь путь запроса, начиная от первого слеша, заканчивая началом параметров GET: «http://example.com/some/news/category/post.html?comments_page=3» -> "/news/category/post.html". Эта строка всегда начинается со /.
  • Второй аргумент RewriteRule также необходимо начинать со /, иначе будет «Bad Request».
  • RewriteBase не имеет смысла.
  • Проход правил происходит только один раз. Флаг [L] действительно заканчивает обработку всех правил, описанных в <VirtualHost>, без каких-либо последующих итераций.

Как работает mod_rewrite. Указание параметров запроса и флаг [QSA]

Изменение параметров запроса в RewriteRule не изменяет строку, с которой работает следующий RewriteRule. Однако при изменении параметров изменяется переменная %, с которой может работать RewriteCond.

Используемая терминология: «параметры» — параметры запроса, «аргументы» — аргументы RewriteRule.

С помощью RewriteRule можно изменять не только путь до файла, который будет обрабатываться, но и параметры запроса GET, которые будут ему передаваться. Это часто используется для передачи обработки ЧПУ в общий скрипт-обработчик, например:

  1. RewriteRule заменяет строку, с которой оно работает, на часть второго аргумента до вопросительного знака. Обратите внимание, что новые параметры запроса не попадают в строку, с которой будут работать последующие правила RewriteRule.
  2. Часть второго аргумента после вопросительного знака попадает в переменную %. Если был указан флаг [QSA], параметры запроса будут добавлены в начало %. Если флаг указан не был, % полностью заменится параметрами запроса из RewriteRule.

Скорее всего, правило выше работает неправильно, так как теряется аргумент page. Исправим это:

Мы добавили только флаг [QSA], и правило стало работать корректно.

Важно понимать, что изменение параметров запроса изменяет % , который может использоваться в дальнейшем в RewriteCond. Это нужно учитывать при составлении последующих правил, проверяющих аргументы.

— Конечно, изменяется, ведь запрос уходит на повторную обработку Apache'м!

Нет, % изменяется сразу же. Доказательство приводить не буду — про параметры и так уже написано больше, чем интересно читать :)

Что же делать, чтобы проверить в RewriteCond именно те параметры запроса, которые передал пользователь, а не модифицированные RewriteRule'ами? Смотрите советы в конце статьи.

Оглавление. Полное руководство по mod_rewrite

8. Директива RewriteOptions, технические подробности, когда НЕ использовать mod_rewrite

Какая часть запроса проверяется на совпадение с Шаблоном?

В контексте VirtualHost Шаблон первоначально проверяется на соответствие с частью URL после имени хоста (hostname) и номера порта и до строки запроса (т.е. к примеру "/app1/index.html"). Это (%-кодированный) URL-путь.

В контексте директорий (Directory и .htaccess), Шаблон проверяется на совпадение только с частью пути, к примеру, запрос "/app1/index.html" может привести к сравнению по "app1/index.html" или "index.html" в зависимости от того, где определено RewriteRule.

Путь до директории, где определено правило, отбрасывается из анализируемого запроса (вплоть до и включая конечный слэш). В конечном счёте, правилу для сравнения передаётся строка «ниже» папки, где определено правилов.

Если вам нужно искать совпадения в имени хоста, порту или строке запроса после ? (вопросительного знака), используйте RewriteCond (эта директива будет рассмотрена в четвёртой части данного руководства) с переменными % , % или % соответственно.

Этичный хакинг и тестирование на проникновение, информационная безопасность

mod_rewrite — просто о сложном

Hello world

Простейший пример. Допустим, Вы захотели, чтобы никто не знал, что Ваш сайт написан на PHP и решили замаскировать расширения файлов. Можно, конечно, внести соответствующую директиву в конфигурацию Apache и тогда все файлы с расширением ".msl" («My Super Language») будут обрабатываться интерпретатором PHP. Но можно поступить проще:
создаем в корне нашего сайта файл .htaccess со следующим содержимым
RewriteEngine On
RewriteBase /
RewriteRule ^(.*)\.msl$ $1.php [QSA,L]

Первая директива включает механизм mod_rewrite в текущей папке и во всех ее подпапках. Вторая указывает модулю mod_rewrite, что текущая папка в файловой системе соответствует корню сайта. Третья — непосредственно правило преобразования URL.

Прочесть его можно так:
Если сразу после начала строки ("^") идет произвольное количество любых символов ( "(.*)" ), причем мы хотим запомнить, что именно это за символы, окружая их скобками, затем идет точка ("\.") (экранируем точку, потому что одиночная точка — это просто любой символ), затем символы «msl» и на этом строка заканчивается ("$"), то заменим исходный URL на следующий: возьмем первую запомненную подстроку в скобках из правила, прибавим к ней ".php", добавим все дополнительные параметры адреса, которые могли быть "[QSA]" и на этом закончим, не будем применять дальнейшие преобразования, если они есть "[L]"

Все, теперь Вы можете смело менять все ссылки, заканчивающиеся на ".php" на ".msl" и писать в своем блоге, что изобрели новый скриптовый язык. Apache, встретив ссылку на «index.msl» с помощью mod_rewrite на лету преобразует ее в «index.php» и вызовет нужный скрипт.

А что еще умеет mod_rewrite?

О, этот модуль умеет многое. Лично я жду, когда же кто-нибудь достаточно продвинутый в магии и PCRE напишет «Морской бой» на mod_rewrite.

Но пока этого не случилось, покажу еще несколько вариантов использования этого замечательного модуля.

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

Первичная фильтрация данных

Предположим, что адреса пользовательских блогов будут иметь вид "/blogs/ABC/", а скрипт, который будет показывать ленту записей определенного блога, будет называться «viewblog.php».
Несложное правило mod_rewirte позволит нам отсеять некорректные имена блогов, которые могут использовать злоумышленники:
RewriteRule blogs/([a-z0-9_-]+)([\/])$ viewblog.php?blogname=$1 [L]
RewriteRule viewblog.php - [F]

В квадратных скобках, в соответствии с синтаксисом PCRE, мы задаем класс символов, включая в него цифры, буквы латинского алфавита, минус и знак подчеркивания. Все адреса, в которых будут какие-то другие символы, не пройдут проверку этим правилом и приведут к ошибке 404. Флаг [L] необходим, чтобы движок mod_rewrite, успешно сделав преобразование, не пошел далее, на второе правило. Этот флаг аналогичен оператору break внутри цикла.

Второе правило не задает напрямую преобразование адреса (символ "-"), а запрещает прямой доступ к скрипту viewblog.php (флаг "[F]"), тем самым закрывая злодеям возможность передать в параметрах что-то вредоносное.

Кстати:
Хорошим тоном будет начинать Ваши правила со строчки
RewriteRule .htaccess - [F]
Это запретит доступ к файлу .htaccess в случае дурно настроенного хостинга.

Использование для кэширования в ФС

И тут mod_rewrite может придти на помощь, если по каким-то причинам Вы не хотите переходить на свой сервер.

Во-первых, модифицируйте свой скрипт viewblog.php таким образом, чтобы при обращении к нему он не только выдавал сформированную страницу в браузер, но и записывал ее в файловую систему по адресу /blogs/ABC.html

Проще всего это сделать, использовав функции управления буферизацией. Предположим, что исходный код скрипта viewblog.php выглядит у Вас примерно так:
<?php
$blogname = $_GET['blogname'];
if ( !Blogs::exists($blogname) )
die("No blog!");

Применим буферизацию вывода и запишем вывод в файл.
<?php
$blogname = $_GET['blogname'];
if ( !Blogs::exists($blogname) )
die("No blog!");

ob_start();
Blogs::display($blogname);
$content = ob_get_contents();
ob_end_flush();

$f = fopen(_YOUR_SITE_ROOT . "/blogs/" . $blogname . ".html", "w");
fwrite($f, $content);
fclose($f);
?>

Теперь остается только немного модифицировать Ваши правила в .htaccess, чтобы получить полноценную систему кэширования контента:

RewriteRule blogs\/([a-z0-9_-]+)([\/])$ blogs\/$1\.html

RewriteCond % blogs\/([a-z0-9_-]+)\.html$
RewriteCond % !-s
RewriteRule (.*) viewblog.php?blogname=%1

В первой строке мы преобразуем URL вида blogs/ABC/ в blogs/ABC.html, таким образом перенаправляя Apache на сгенерированный нами файл кэша страницы.
Следующие три строки представляют собой одно большое правило. Если идет запрос на blogs/ABC.html и при этом в файловой системе нет такого файла — запрос перенаправляется на скрипт viewblog.php

Таким образом нам остается только предусмотреть систему своевременной очистки кэша и задача решена.

Другие применения

Лично я использую модуль mod_rewrite аналогично последнему примеру для генерации и хранения в ФС превью изображений.

Очень легко с помощью mod_rewrite делается отображение поддоменов на папки, например forum.localhost.localdomain физически будет находиться в localhost.localdomain/forum, что часто бывает проще для разработчика приложения.

Незаменим mod_rewrite для ограничения скачивания файлов на файловом хостинге или в магазине цифровых товаров (придется задействовать механизм символических ссылок) или для запрета хотлинкинга (через проверку реферера).

А вообще — это Вуду :)
Чертовски интересное Вуду, позволяющее каждый день открывать новые стороны и применения.

Для чего нужен mod_rewrite / Что умеет mod_rewrite

Слово «rewrite» в названии модуля буквально означает «перезапись». Эта «перезапись» относится к URL (адресу сайта, страницы, файла). Перезапись (преобразование) происходит между тем, что введено в строке браузера пользователя (фактически, отправлено на веб-сервер) и тем, что веб-сервер получит на самом деле.

Наглядным примером применения mod_rewrite являются ЧПУ (аббр. от «человекопонятный URL») - URL-путь, состоящий из понятных слов, вместо идентификаторов, и отражающий файловую структуру сайта. Например, вместо /c14/3/97/ или /index.php?cat=10&subcat=2&id=41 будет /product/phone/Samsung/.

Человекопонятные пути улучшают удобство использования, Кроме того, позволяют по названию ссылки заранее предполагать содержимое страницы по ней, и представлять структуру сайта.

Слеши (/) на веб-сервере разделяют вложенные подпапки. Но в случае с ЧПУ если в адресе страницы встречается строка /product/phone/Samsung/, то это не означает, что на веб-сайте действительно имеется папка product, в которой подпапка phone и в которой подпапка Samsung. Благодаря mod_rewrite строка вида /product/phone/Samsung/ перезаписывается в строку вида index.php?category=product&type=phone&brand=Samsung. Таким образом, пользователь набирает в веб-браузере, либо переходит по ссылке с удобным для его восприятия адресом, а веб-сервер получает данные в понятном для обработки виде, когда каждой переменной присваивается соответствующее значение и эти переменные передаются в скрипт веб-сервера для обработки, либо отображения информации.

Это очень популярное, но не единственное применение mod_rewrite. Этот модуль умеет делать перезапись на основе разных данных: к примеру, на основе типа браузера. Это позволяет показывать разные страницы в зависимости от типа браузера, IP адреса, языка пользователя, установленных кукиз и т.д.

mod_rewrite умеет делать редирект (перенаправление) на другой адрес. В результате, если ваш сайт переехал на другой домен или поменялась структура сайта, вы можете настроить автоматическую переадресацию со старых адресов страниц на новые.

mod_rewrite умеет запрещать доступ к определённым ресурсам, как по определённому условию, так и безусловно. Т.е. вы можете настроить контроль доступа, закрыв определённые страницы для всех пользователей, либо на основе их стран, языка, веб-браузера и т.д.

На самом деле – это не всё, что умеет mod_rewrite! И даже в этом мануале вы встретитесь с дополнительными примерами применения mod_rewrite.

Прежде чем мы перейдём к теории и практики использования mod_rewrite, нужно включить модуль mod_rewrite для веб-сервера, либо убедиться, что mod_rewrite уже включен. Если вы используетесь shared (совместным) хостингом, то у большинства хостеров этот модуль включен по умолчанию. Ниже показано, как включить этот модуль на своём собственном локальном (домашнем) сервере, либо веб-сервере на VPS.

Логика работы mod_rewrite

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

Это так, но это не всё. Если указано несколько правил RewriteRule и, допустим, в запросе найдено совпадение с первым правилом и исходная строка запроса изменена в соответствии с этим правилом. Второму правилу передаётся не исходная строка запроса, а новая строка, получившаяся в результате обработки всеми предыдущими правилами. И также происходит ниже по цепочке.

Проверку по всем правилам можно назвать проходом (раундом, циклом). Если в данном раунде случилось хотя бы одно совпадение (сработало правило), то после завершения прохода начинается ещё один круг проверки по этим же самым правилам! Это неочевидно и мало где об этом говориться – поэтому обратите на это особое внимание. Т.е. на новый раунд передаётся уже изменённая строка запроса и именно она проходит оценку по всем правилам. И вновь: если сработало хотя бы одно правило, идёт заход на новый круг и т.д.

Это является поведением по умолчанию для mod_rewrite. Это поведение можно изменить несколькими флагами, о которых будет рассказано далее.

RewriteCond и производительность

Сначала проверяется совпадение запроса с RewriteRule, а уже потом — дополнительные условия RewriteCond.

Пару слов стоит сказать о том, в каком порядке mod_rewrite выполняет директивы. Так как в .htaccess сначала идут RewriteCond, а потом RewriteRule, кажется, что mod_rewrite сначала проверяет все условия, а потом приступает к выполнению RewriteRule.

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

Так что если у вас в RewriteRule регулярное выражение на две страницы и вы, задумавшись о производительности, решили ограничить выполнение этого правила дополнительными RewriteCond, знайте — ничего не получится. В этом случае лучше использовать флаги RewriteRule [C] или [S], чтобы пропустить более сложное правило, если более простые проверки не сработали.

Включение mod_rewrite

mod_rewrite – это опциональный (необязательный) модуль веб-сервера Apache, который по умолчанию отключён. Поэтому работу с mod_rewrite нужно начать с его включения в веб-сервере.

Поскольку для большинства ситуаций удобнее использовать именно .htaccess, то для работы mod_rewrite нам нужно:

  • включить непосредственно сам mod_rewrite
  • включить поддержку файлов .htaccess

Если вы используете Debian, Ubuntu, Linux Mint, Kali Linux то mod_rewrite можно включить следующей командой:

В Debian, Ubuntu, Linux Mint, Kali Linux эта группа строк выглядит так:

В этой группе строк замените


В Windows она может выглядеть так:

В этой группе строк замените


Чтобы любые изменения, сделанные в конфигурационном файле Apache, вступили в силу, нужно перезапустить сервер.

Если вы решили для использования mod_rewrite вносить изменения в конфигурационный файл Apache, то не забывайте каждый раз после изменения правил перезапускать веб-сервер, чтобы эти изменения вступили в силу.

Также должна быть включена опция Options FollowSymLinks (по умолчанию она включена). Если FollowSymLinks отключено, то невозможно использовать движок перезаписи. Это ограничение продиктовано причинами безопасности.

С чем работает RewriteRule

Первому RewriteRule передается путь от того места, где находится .htaccess, до запрошенного файла. Эта строка никогда не начинается со "/". Последующим RewriteRule передается результат предыдущих преобразований.

Чтобы досконально понять, как работает RewriteRule, необходимо сначала определить, с чем он работает. Рассмотрим, как Apache получает строку, которая изначально передается на обработку RewriteRule в .htaccess.

Когда только начинаешь работать с mod_rewrite, логично предполагаешь, что он работает со ссылками. Однако в случае с использованием mod_rewrite в .htaccess это не так. На самом деле в RewriteRule передается не ссылка, а путь до запрошенного файла.

Из-за внутренней архитектуры Apache в тот момент, когда в действие вступает .htaccess, mod_rewrite может оперировать только с путем до файла, который должен быть обработан. Это связано с тем, что до передачи в mod_rewrite запрос уже могли изменить другие модули (например, mod_alias), и итоговый путь до файла на сайте уже может не совпадать с исходной ссылкой. Если бы mod_rewrite работал с исходной ссылкой, он бы нарушал действие модулей, которые изменили запрос до него.

Поэтому в mod_rewrite передается абсолютный путь до файла, который должен быть обработан. Также mod_rewrite знает путь до .htaccess, в котором размещены правила RewriteRule. Чтобы сделать из пути до файла что-то похожее на ссылку, с которой планирует работать разработчик сайта, mod_rewrite отрезает от абсолютного пути часть до файла .htaccess.

как работает RewriteRule

Путь до .htaccess отрезается вместе со слешем. Из этого есть следствие: строка, которая изначально передается на обработку RewriteRule никогда не начинается со "/".

Важно запомнить, что не делает RewriteRule. Она не обрабатывает имя сайта, аргументы, которые переданы в скрипт, да и ссылку обрабатывает не всю, если .htaccess размещен не в корне сайта. Всем этим занимается RewriteCond, которого кратко коснемся чуть позже. Итак:

В начале использования mod_rewrite я рекомендую работать с ним только в .htaccess в корне сайта. Это несколько упростит контроль за его работой.

С чем работает RewriteRule, мы разобрались. Теперь посмотрим, как он работает.

5 последних уроков рубрики "Для сайта"

Эффекты блочного раскрытия

Сегодня мы хотели бы поделиться несколькими идеями касающегося эффекта блочного раскрытия, которую вы можете использовать для своих проектов.

15 полезных .htaccess сниппета для сайта на WordPress

Если вы хотите существенно повысить уровень безопасности вашего сайта на WordPress, то вам не избежать конфигурации файла .htaccess. Это позволит не только уберечься от целого ряда хакерских атак, но и организовать перенаправления, а также решить задачи связанные с кэшем.

20 бесплатных тем для WordPress в стиле Material Design

Material Design — это набирающий обороты тренд от Google. В данной подборке собраны бесплатные темы для WordPress, выполненные в этом популярном стиле.

20 сайтов с креативным MouseOver эффектом

Эффекты на то и существуют чтобы впечатлять наших посетителей. В этой подборке собрано несколько десятков ресурсов, чьи создатели очень постарались впечатлить своих посетителей.

45+ бесплатных материалов для веб дизайнеров за август 2016

Под конец месяца предлагаем ознакомиться с набором бесплатных материалов для веб дизайнеров за прошедший месяц.

Как на самом деле работает mod_rewrite. Пособие для продолжающих

image


Эта статья выросла из идеи продвинутого обучения наших сотрудников технической поддержки работе с mod_rewrite. Практика показала, что после изучения имеющихся в большом количестве учебников на русском языке саппортам хорошо дается решение шаблонных задач, но вот самостоятельное составление правил происходит методом проб и большого количества ошибок. Проблема заключается в том, что для хорошего понимания работы mod_rewrite требуется изучение оригинальной англоязычной документации, после чего — либо дополнительные разъяснения, либо часы экспериментов с RewriteLog.

В статье изложен механизм работы mod_rewrite. Понимание принципов его работы позволяет четко осознавать действие каждой директивы и ясно представлять себе, что происходит в тот или иной момент внутри mod_rewrite при обработке директив.

Я предполагаю, что читатель уже знаком с тем, что такое mod_rewrite, и не буду описывать его основы, которые легко найти в интернете. Также нужно отметить, что в статье освещается работа mod_rewrite при использовании его директив в файле .htaccess. Отличия при работе в контексте <VirtualHost> изложены в конце статьи.

Итак, вы изучили mod_rewrite, составили несколько RewriteRule и успели столкнуться с бесконечными перенаправлениями, со случаем, когда правило почему-то не ловит ваш запрос, а также с непредсказуемой работой группы правил, когда последующее правило неожиданно изменяет запрос, кропотливо подготовленный правилами предыдущими.

Почему так происходит?

Как работает mod_rewrite. Флаг [R]

Флаг [R] не останавливает обработку запроса, возвращая сразу внешний редирект. Вместо этого он запоминает необходимость внешнего редиректа, и обработка запроса продолжается следующими RewriteRule. Рекомендуется всегда использовать с флагом [L].

Флаг [R] сообщает Apache, что нужно выполнить не внутренний, а внешний редирект. Чем отличается внешний редирект от внутреннего? Внутренний редирект просто изменяет путь до файла, который будет отдан пользователю, при этом пользователь считает, что получает тот файл, который он изначально запросил. При внешнем же редиректе Apache вместо содержимого файла возвращает пользователю статус ответа 301 или 302 и сообщает ссылку, по которой браузер должен обратиться для получения файла.

Казалось бы, при обработке флага [R] Apache должен сразу прекратить обработку RewriteRule и вернуть пользователю внешний редирект. Однако давайте вспомним фантастический пример из раздела «Как работает RewriteRule». В нем мы сначала указали флаг [R], обозначив необходимость внешнего редиректа, после чего продолжили изменять ссылку следующими RewriteRule.

Именно так и работает Apache при указании внешнего редиректа. Он просто «помечает» себе, что после выполнения всех правил необходимо вернуть статус 302 (по умолчанию), но при этом продолжает выполнение всех RewriteRule дальше по списку. Мы можем и дальше изменять запрос как нам нужно, единственное, что не получится — сделать редирект обратно внутренним.

Тем не менее, вряд ли вы хотите после отдачи внешнего редиректа каким-либо образом изменять его. Поэтому рекомендуется при употреблении флага [R] указывать его совместно с [L]:

  • Если внешний редирект ведет на тот же сайт, лучше использовать флаг [R] без указания полной ссылки (иными словами, использовать относительный внешний редирект). Это сделает правило независимым от имени сайта.
  • Если же внешний редирект ведет на другой сайт, иначе, как указав полную внешнюю ссылку, это сделать не получится.

Для чего нужен RewriteBase

Если получившийся после преобразований запрос является относительным и отличается от исходного, RewriteBase добавит себя к нему слева. Нужно обязательно указывать RewriteBase в .htaccess. Его значение — путь от корня сайта до .htaccess.
RewriteBase выполняется только после всех RewriteRule, а не между ними.

Мы уже говорили выше о том, что в mod_rewrite, работающий в .htaccess, попадает абсолютный путь до запрошенного файла. Чтобы передать его в RewriteRule, mod_rewrite отрезает путь до .htaccess. Потом правила RewriteRule одно за одним последовательно изменяют запрос. И вот после того, как запрос изменен, Apache должен восстановить абсолютный путь до файла, который он должен в итоге обработать. RewriteBase фактически является хаком, который помогает восстановить исходный путь до файла.

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

  1. RewriteBase должен совпадать с путем от корня сайта до .htaccess.
  2. Начинать перенаправления со "/" нужно только тогда, когда необходимо указать абсолютный путь от корня сайта до файла.

как работает RewriteBase

Итак, запрос прошел через все RewriteRule, после чего к нему, в случае необходимости, добавился RewriteBase. Должен ли теперь Apache отдать файл, на который показывает результирующий путь? Нет. Теперь получившийся запрос будет обрабатываться еще раз.

Директива RewriteBase

Мы уже выяснили, что на совпадение проверяется только часть запроса – начиная от текущий папки и далее вложенные подпапки. Если Подстановкой, получившейся в результате перезаписи, является относительный путь, то чтобы найти этот ресурс, к полученному значению добавляется путь до текущей папки. Это является поведением по умолчанию, а директива RewriteBase позволяет изменить это поведение.

Директива RewriteBase определяет URL префикс, используемый для постановки перед относительным путём.

Обычно, эта директива не требуется. Но она нужна когда:

Советы и решения

Здесь собраны советы, которые можно было бы привести по ходу статьи, но которые были исключены из основного текста для краткости изложения материала.

Составление регулярных выражений


Старайтесь составлять регулярные выражения так, чтобы они наиболее узко определяли именно те запросы, которые вы хотите модифицировать — чтобы правила RewriteRule случайно не сработали для другого запроса. Например:

Впрочем, о регулярных выражениях на одном известном сайте есть целый раздел.

Изменение внешних редиректов

Несмотря на то, что mod_rewrite позволяет изменять с помощью RewriteRule даже внешние редиректы, вплоть до протокола, я крайне не рекомендую делать это. В статье пример с изменением внешних редиректов используется только чтобы отвязаться от таких понятий как «ссылки» и «файлы» и более явно показать, что RewriteRule работает с простой строкой.

Не думаю, что разработчики mod_rewrite предполагали, что кто-то будет так делать, поэтому возможны всякие артефакты. Не делайте так, пожалуйста.

Как остановить бесконечный цикл

Иногда логика перенаправлений на сайте такова, что без специальных действий mod_rewrite воспринимает их как бесконечный цикл перенаправлений. Возьмем следующий пример.

На сайте была страница /info.html. Специалист по SEO решил, что поисковые системы будут лучше индексировать эту страницу, если она будет называться /information.html и попросил сделать внешний редирект с info.html на information.html. Однако разработчик сайта по каким-то своим соображениям не может просто переименовать info.html в information.html и сделать редирект — ему нужно, чтобы данные обязательно отдавались непосредственно из файла info.html. Он пишет следующее правило:

… и сталкивается с бесконечным циклом. Каждый запрос /information.html получает внешний редирект снова на /information.html.

Решить эту проблему можно как минимум двумя способами. На Хабре был уже описан один из них — нужно установить переменную окружения и на основании ее значения прекращать перенаправления. Код будет выглядеть следующим образом:

RewriteRule ^info.html$ information.html [R,L]
RewriteRule ^information.html$ info.html [E=FINISH:1]

Обратите внимание, что к имени переменной mod_rewrite добавляет 'REDIRECT_'.

Второй способ — проверить в THE_REQUEST, что именно было запрошено пользователем:

RewriteRule ^information.html$ info.html

Анализ исходного запроса пользователя — борьба с раскрытием ссылок Apache


При обработке запроса Apache раскрывает закодированные (URL-encoded) символы из первоначального запроса. В некоторых случаях это может быть нежелательно — разработчик хочет проверять именно первоначальный, немодифицированный запрос пользователя. Сделать это можно, проверяя в RewriteCond переменную %:

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

Директивы RewriteEngine и RewriteRule

Модуль mod_rewrite использует несколько директив, и в этом руководстве мы рассмотрим их все. Но в каждом примере мы неизменно будем использовать две главные директивы, это RewriteEngine и RewriteRule. Первая директива, в виде

просто включает использование mod_rewrite в файле .htaccess.

Значение директивы можно установить на off:

В этом случае правила, которые следуют после отключения RewriteEngine off, не будут задействованы. Отключение RewriteEngine можно использовать вместо удаления или комментирования строк с правилами RewriteRule.

Конфигурации перезаписи не наследуются виртуальными хостами. Это означает, что нужно иметь директиву RewriteEngine on для каждого виртуального хоста, на которым вы хотите использовать правила перезаписи.

А вторая директива RewriteRule является главной рабочей лошадкой этого модуля. Именно с её помощью мы будем устанавливать правила перезаписи.

Она используется следующим образом:

Шаблон – это то, что мы ищем в передаваемом URL.

Подстановка – это новая строка, которая передаётся веб-серверу в том случае, если в исходных данных найдено совпадение с Шаблоном.

[флаги] – это условные обозначения, задающие дополнительные действия или поведение при перезаписи. Они являются необязательными. Мы также рассмотрим флаги в этой инструкции.

Подстановка RewriteRule

Подстановка правила перезаписи – это строка, которая заменяет оригинальный URL-путь, который совпал с Шаблоном. В качестве подстановки может быть:

Указывает местоположение в файловой системе ресурса, который будет доставлен клиенту. Подстановки обрабатываются как путь к файловой системе, когда правило настроено в контексте сервера (virtualhost), и первый компонент пути в подстановке существует в файловой системе.

Относительный DocumentRoot путь к ресурсу, который будет обслуживаться. Обратите внимание, что mod_rewrite пытается угадать, указали ли вы путь файловой системы или URL-путь, проверяя, существует ли первый сегмент пути в корне файловой системы. Например, если вы укажете строку Подстановки /www/file.html, это будет рассматриваться как путь URL-адреса, если директория с именем www не существует в корне вашей файловой системы (или в случае использования перезаписи в файле .htaccess относительно вашего корня документов), в последних случаях это будет рассматриваться как путь в файловой системе. Если вы хотите, чтобы другие директивы сопоставления URL (такие как Alias) применялись к результирующему URL-адресу, используйте флаг [PT], как описано в третьей части данного руководства.

Если указан абсолютный URL, mod_rewrite проверяет, совпадает ли имя хоста с текущим хостом. Если да, то схема и имя хоста отбрасываются и результирующий путь трактуется как URL-путь. В противном случае, выполняется внешний редирект (перенаправление) для заданного URL. Для принудительного внешнего редиректа на текущий хост (чтобы запрашиваемая страница поменяла адрес на другую страницу этого же хоста), смотрите флаг [R], описанный далее.

Чёрточка говорит о том, что не должна выполняться какая-либо подстановка (существующий путь должен быть пропущен нетронутым). Это используется когда нужно применить флаг (смотрите далее) без изменения пути.

В дополнении к простому тексту, строка Подстановки может включать:

  1. обратную ссылку ($N) на шаблон RewriteRule
  2. обратную ссылку (%N) на последний совпавший шаблон RewriteCond
  3. серверные переменные как в тестовых строках условия правила (%)
  4. вызов функции сопоставления (mapping) ($)

Журнал (логи) преобразований mod_rewrite

Когда вы написали и тщательно проверили правила для mod_rewrite, журнал преобразований можно включить или отключить на своё усмотрение. Но на время обучения либо тестирования новых правил, рекомендуется, конечно, включить ведение журнала и в случае возникновения проблем изучать логи mod_rewrite.

Тема логов Apache сама по себе довольно объёмная, не будем на ней заострять внимание. Но необходимо упомянуть, что если вы работали с предыдущими версиями mod_rewrite и использовали директивы RewriteLog и RewriteLogLevel, то теперь их функциональность полностью заменена директивой LogLevel, которая настраивать логи всего веб-сервера и всех модулей.

По умолчанию LogLevel установлено показывать предупреждение, в конфигурационном файле Apache это строка:

Можно заменить эту строку на:

Что такое mod_rewrite

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

mod_rewrite предоставляет возможность динамически изменять входящие URL-запросы, основываясь на правилах, использующих регулярные выражения. Это позволяет вам сопоставлять произвольные URL-адреса к вашей внутренней структуре URL любым способом. По умолчанию mod_rewrite сопоставляет URL-адрес пути к файловой системе. Однако он также может использоваться для перенаправления одного URL-адреса на другой URL-адрес или для вызова внутренней прокси передачи.

Правила перезаписи могут оперировать полными URL, включая path-info (информацию о пути) и строку запроса; отдельные правила можно настроить для использоваться в контексте всего сервера, отдельного для каждого виртуального хоста или для каждой директории (папки). Правила перезаписи могут вести к последующим правилам, внутренним подпроцессам, внешним перенаправлениям запросов или проксированию, в зависимости от флагов, которые вы добавили к правилам.

Поскольку mod_rewrite такой мощный, его изучение требует времени. Функциональность mod_rewrite пересекается с некоторыми другими модулями Apache и решение, что именно использовать, за вами. В этой инструкции дан подробный разбор всех возможностей mod_rewrite и показано много примеров, как использовать этот модуль, а когда лучше использовать другие альтернативы.

Переменные и флаги RewriteCond, остальные флаги RewriteRule и прочее

Мы познакомились с принципами работы RewriteRule, RewriteBase, флагов [L], [R] и [QSA], а также разобрали механизм обработки запросов внутри mod_rewrite. Из незатронутого остались: другие флаги RewriteRule, директивы RewriteCond и RewriteMap.

К счастью, эти директивы и флаги не таят в себе каких-либо загадок и работают именно так, как описано в большинстве учебников. Для их понимания достаточно почитать официальную документацию. В первую очередь рекомендую изучить список переменных, которые можно проверять в RewriteCond — %, %, %, %, % и т. д.)

Введение в использование mod_rewrite

В данном уроке объясняется, что такое mod_rewrite и как его использовать. Описываются три практичных примера: перенаправление 301, создание дружественных URL и блокирование использования ссылок на изображения.

mod_rewrite - это замечательный модуль веб сервера Apache. Он очень гибкий и может выполнять много полезных функций.

Использование mod_rewrite может представлять определенные трудности для новичков по причине сложного синтаксиса и механизма обработки. Однако, стоит разобраться в нескольких базовых концепциях и можно будет эффективно использовать mod_rewrite для собственного сервера.

В данном уроке мы научимся создавать несколько базовых правил mod_rewrite на реальных примерах, которые можно будет использовать для собственного сайта. Рекомендуется тщательно изучить материал о регулярных выражениях, если вы еще не знаете что это такое.

Что такое mod_rewrite?

mod_rewrite - это модуль сервера Apache для манипуляции (изменения) URL. Часто это означает получение запроса URL от посетителя и посылка ему содержания с другого URL. Например, посетитель вводит следующий URL в адресной строке браузера:

Что можно делать с помощью mod_rewrite

Вот несколько обычных функций, которые выполняет mod_rewrite:

Как использовать mod_rewrite

Для использования mod_rewrite, нужно создать директивы Apache для указания модулю, что нужно делать. это простые конфигурационные установки. Часто директивы размещаются в файле .htaccess в корневой папке вашего веб сайта. Директивы применяются для всего сайта.

Две самых важных директивы mod_rewrite:

  • RewriteEngine : Включает/выключает механизм mod_rewrite для текущего запроса.
  • RewriteRule : Описывает правило изменения адреса URL.

Вот простой пример. Создайте файл .htaccess со следующим содержанием и разместите его на вашем сайте:

В данном файле задаются следующие установки:

RewriteEngine on - включаем механизм mod_rewrite

Если вы получаете ошибку 404, то вероятно на вашем хостинге не используется mod_rewrite. В данном случае надо обратиться к администратору хостинга.

Как работает RewriteRule

Вы можете использовать директиву RewriteRule для создания правил перенаправления. Обобщенный синтаксис директивы имеет вид:

  • Pattern - регулярное выражение шаблона. Если URL соответствует шаблону, то правило выполняется. Иначе правило пропускается.
  • Substitution - новый URL, который будет использоваться вместо соответствующего шаблону адреса.
  • [Optional Flags] - один или несколько флагов, которые определяют поведение правила.

Вы можете добавить в файл .htaccess столько правил RewriteRule , сколько нужно. Модуль mod_rewrite проходит все правила каждый раз при запросе, обрабатывая соответствующие адресу URL.

Если правило изменяет запрашиваемый URL на новый адрес, то новый URL используется дальше при проходе по файлу .htaccess , и может соответствовать другому правилу RewriteRule , размещающемуся далее в файле. (Если нужно изменить такое поведение, то надо использовать флаг L ("последнее правило").)

Несколько примеров использования mod_rewrite

Самый простой способ объяснить mod_rewrite - показать его использование при решении практических задач.

Пример 1: исключение ошибки 404

Иногда происходит изменение URL страницы на вашем сайте. Такое может произойти в момент реорганизации содержания. Если поисковый механизм или другие сайты ссылаются на старый адрес URL, то пользователь получит ошибку "404 Not Found", когда он попробует воспользоваться ссылкой.

Следующий файл .htaccess перенаправит запросы на новый адрес URL:

Правило RewriteRule работает так:

  • ^my-old-url\.html$ - регулярное выражение, которому соответствует адрес URL для изменения. Шаблон означает: "соответствует началу адреса URL ( ^ ), за которым следует текст 'my-old-url.html' , за которым следует символ окончания URL ( $ )." В регулярном выражении символ точки (.) означает соответствие любому символу, поэтому нужно использовать обратный слэш, чтобы указать, что нам нужна именно точка (\.).
  • /my-new-url.html - вторая часть правила RewriteRule , которая описывает на что нужно менять. В данном случае это просто /my-new-url.html.
  • [R=301,L] третья часть правила, которая содержит один или несколько флагов, помещенных в квадратные скобки. Флаги позволяют добавлять определенные опции или действия к правилу. В данном примере используется 2 флага: R=301 означает "использовать перенаправление 301 на новый адрес URL"; а L означает "последнее правило", или другими словами "остановить процесс обработки URL, если он соответствует правилу ".
Пример 2: создание дружественных адресов URL

Допустим, вы написали PHP скрипт display_article.php для вывода статей на вашем сайте. Вы можете ссылаться на статью с помощью следующего адреса URL:

Данный адрес выглядит уродливо и запрос внутри него ( ?articleId=my-article ) может смущать некоторые поисковые механизмы. Гораздо лучше использовать адрес URL такого вида:

Вы можете задействовать mod_rewrite для преобразования ссылок первого формата во второй, что даст возможность использовать дружественные ссылки на страницах сайта, а обращение будет выполняться к реальным адресам, не видимым никому. Для этого файл .htaccess , расположенный в корневой директории вашего сайта, должен содержать следующие строки:

Описание правила RewriteRule :

  • ^articles/([^/]+)/?$ - регулярное выражение, соответствующее любому URL в формате articles/(article ID)/ . Оно гласит:"соответствует началу URL ( ^ ) , за которым следует текст articles/ , за которым следует один или более символов, не являющиеся слэшем ([^/]+) , за которыми может следовать слэш (/?) , за которым следует символ окончания URL ($) ". Обратите внимание на круглые скобки вокруг части шаблона [^/]+ . Таким образом текст, соответствующей данной части, например, "my-article" , сохраняется для дальнейшего использования.
  • display_article.php?articleId=$1 - данная часть правила указывает серверу Apache использовать скрипт display_article.php , которому передается текст, соответствующий подшаблону [^/]+ из регулярного выражения первой части (например, "my-article" ), в качестве параметра articleId . $1 называется обратной связью и хранит текст соответствующий подшаблону. Если регулярное выражение содержит еще один подшаблон в круглых скобках, то соответствующий ему текст будет храниться в переменной $2, и так далее.
  • [L] - как и в предыдущем примере мы используем флаг для остановки дальнейшей обработки URL, чтобы не произошло изменение адреса другими правилами RewriteRule.
Пример 3: предотвращаем использование ссылок на изображения на вашем сайте

Другой сайт может ссылаться на своих страницах прямо на вашу фотографию следующим образом:

Это означает, что чужой сайт не только "заимствует" ваше изображение, но использует часть трафика вашего сервера для отображения изображения на своих страницах. И если чужой сайт имеет большой поток посетителей, то такое положение станет проблемой!

Как только вы закончите выполнять все операции копирования любой браузер , запрашивающий изображения с вашего сайта использующий при запросе URL, начинающийся с имени домена, отличного от www.example.com или example.com , будет получать ошибку "403 Forbidden". что остановит использование ссылок на ваши изображения на других сайтах.

Вот как работает данный набор правил:

  • RewriteEngine on - включаем механизм mod_rewrite
  • RewriteCond % !^$ - RewriteCond является еще одной директивой mod_rewrite. Она позволяет устанавливать условие, которое должно выполняться для обработки URL следующим за ним правилом RewriteRule . В данном случае условием является наличие значения в переменной HTTP_REFERER .
  • RewriteCond % !^http://(www\.)?example\.com/.*$ [NC] - вторая директива RewriteCond требует, чтобы значение переменной HTTP_REFERER не начиналось с http://www.example.com/ или http://example.com/ . Флаг [NC] устанавливает чувствительность к регистру символов.
  • RewriteRule .+\.(gif|jpg|png)$ - [F] - если два выше предыдущих условия RewriteCond не выполняются, то правило пропускается. Само же правило возвращает ошибку "403 Forbidden" (используется флаг [F] ), если URL содержит имя файла изображения (строка заканчивается на .jpg , .jpg или .jpg ), Тире в параметре подстановки означает "не надо заменять URL другим адресом".

То есть весь набор правил в файле .htaccess гласит, если переменная HTTP_REFERER содержит значение, и оно не начинается на http://example.com/ или http://www.example.com/ , и запрашиваемый URL содержит имя файла изображения, то надо отказать запросу с ошибкой "403 Forbidden".

Заключение

В данном уроке мы провели введение в использование модуля сервера Apache mod_rewrite для манипулирования адресами URL. Рассмотренные три практических примера затрагивают лишь небольшую часть всех возможностей модуля. Более подробную информацию о mod-rewrite на русском языке можно найти здесь.

Тестирование правил mod_rewrite

Для тестов, на вашем веб-сервере в папке сайтов создайте новую папку mr, к примеру, на Windows это может быть каталог C:\Server\data\htdocs\mr\, а на Linux это /var/www/html/mr/

Шаблон RewriteRule

В качестве Шаблона используется регулярное выражение, которое представляет собой способ описать текст, который считается подходящим (совпадающим с шаблоном). Шаблоны можно выразить словами, например, «все слова, которые начинаются с буквы A» или «каждый десятизначный телефонный номер» или «каждое предложение с двумя запятыми и без заглавных букв Q».

Польза регулярных выражений в том, что они позволяют, не перечисляя все возможные варианты (которых может быть бесконечно много), установить правила для каждого из этого возможного варианта, если исходный запрос удовлетворяет определённым требованиям.

Они позволяют описывать различные условия очень гибким способом, например: все файлы .jpg и .jpg в любой директории "images" можно записать как "/images/.*(jpg|gif)$".

Более подробно регулярным выражениемя (шаблонам) посвящена вся вторая часть данного руководства.

Как работает mod_rewrite. Флаг [L]

mod_rewrite запускает обработку запроса снова и снова, до тех пор, пока он не перестанет меняться. И флаг [L] не может это остановить.

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

Apache поступает так, потому что в процессе изменения запроса он мог быть перенаправлен в другую директорию. В ней может быть собственный .htaccess, который не участвовал в предыдущей обработке запроса. В этом же новом .htaccess могут быть правила, которые влияют на обработку запроса — как правила mod_rewrite, так и правила других модулей. Чтобы корректно обработать эту ситуацию, Apache должен запустить весь цикл обработки заново.

— Постойте, но ведь есть флаг [L], который останавливает обработку запроса mod_rewrite'ом!

Не совсем так. Флаг [L] останавливает текущую итерацию обработки запроса. Однако если запрос был изменен теми RewriteRule, которые все-таки успели отработать, Apache запустит цикл обработки запроса заново с первого RewriteRule.

RewriteRule ^a.html$ b.html [L]
RewriteRule ^b.html$ a.html [L]

Пример выше приведет к бесконечному циклу перенаправлений и к «Internal Server Error» в итоге. В этом примере бесконечный цикл очевиден, однако в более сложных конфигурациях может потребоваться покопаться в правилах, чтобы определить, какие запросы зацикливаются между собой.

  1. Когда используется внешний редирект — [L,R=301] или [L,R=302]. В случае внешнего редиректа дальнейшая обработка запроса нежелательна (см. ниже про флаг [R]), и ее лучше остановить.
  2. Когда в .htaccess есть зацикливание, от которого не избавиться, и обработку запроса mod_rewrite'ом нужно принудительно прекратить. В этом случае используется специальная конструкция — см. в конце статьи советы на эту тему.

RewriteBase /
RewriteRule ^a.html$ b.html
RewriteRule ^b.html$ a.html

Отгадка: В результате выполнения всех RewriteRule запрос меняется таким образом, что конечный результат равен исходному . Apache видит это и не запускает повторную обработку запроса . Будет возвращен файл a.html .

Читайте также: