СтатьиПреобразование ссылок с помощью Apache
Допустим, у вас есть работающий веб-сайт, состоящий из большого количества статических html-страниц. Все идет хорошо, но вдруг в какой-то момент вы решаете усовершенствовать работу веб-сайта и добавляете динамические скрипты: в результате страничка новостей теперь доступна по ссылке одобные изменения требуют замены соответствующих ссылок на всех страницах вашего веб-сайта, которые ссылаются на новости и регионы, но это еще цветочки. Основная проблема заключается в том, что на эти страницы могут ссылаться другие веб-сайты, о существовании которых вы даже не подозреваете. Да и посетители вашего веб-сайта могли создать соответствующие закладки в своих браузерах, и поэтому они будут неприятно удивлены, когда вместо странички новостей получат ошибку "404: страница не найдена".
Анализ проблемы наводит на мысль о том, как хорошо было бы иметь возможность обращаться к одним и тем же страницам по различным HTTP-ссылкам, причем для страниц с похожими ссылками было бы очень удобно описать одно общее для них правило вместо того, чтобы для каждой страницы выписывать все возможные варианты ведущих на нее HTTP-ссылок. Если ваш веб-сайт работает под управлением весьма популярного в настоящее время веб-сервера Apache (скорее всего, это именно так), то в вашем распоряжении есть мощнейшее средство преобразования ссылок, которое реализуется специальным программным модулем
Для перестраховки можно уточнить у службы технической поддержки вашего хостера, включен ли модуль
Прежде чем углубиться в описание возможностей модуля # Включение преобразования ссылок RewriteEngine on # Новостная страница RewriteRule ^news.html$ /cgi-bin/news.cgi # Страницы с описаниями регионов RewriteRule ^regions/([0-9]+)\.html$ /cgi-bin/regions.pl?region=$1&mode=brief
Директива
Правила преобразования ссылок наследуются чуть сложнее. Чаще всего преобразование по умолчанию отключено в основном конфигурационном файле веб-сервера. Допустим, что вы записали в
А теперь перейдем непосредственно к описанию правил. Преобразования описываются при помощи директивы RewriteRule "исходный путь" "замена" "флаги"
Исходный путь — это часть исходной ссылки, от которой отрезаны имя сервера, путь до текущего каталога и параметры запроса. Допустим, что ваш веб-сайт
Замена — это то, на что будет заменена исходная ссылка в случае "срабатывания" правила. Замена может быть относительной (если она не начинается с символа Флаги — это дополнительные опции для данного правила, которые перечисляются в квадратных скобках через запятую.
Примеры (во всех случаях показано содержимое файла # Пример 1. Каталоги проектов project1 и project2 веб-сайта www.site.com ранее содержали статические html-страницы, теперь же эти страницы расположены на двух отдельных веб-сайтах project1.ru и project2.ru (в той же иерархии) # Первый способ требует наличия модуля mod_proxy и создает дополнительную нагрузку на веб-сервер, но зато посетитель веб-сайта не знает, откуда в действительности выбираются веб-страницы # Символы / даются с вопросительными знаками, чтобы правильно обработать ссылки вида http://www.site.com/project1 и http://www.site.com/project1/ RewriteRule ^project1/?(.*) http://project1.ru/$1 [P] RewriteRule ^project2/?(.*) http://project2.ru/$1 [P] # Второй способ возвращает внешние редиректы, так что посетитель увидит в адресной строке своего браузера, что страницы реально расположены на других веб-сайтах RewriteRule ^project1/?(.*) http://project1.ru/$1 [R] RewriteRule ^project2/?(.*) http://project2.ru/$1 [R] # Допустим, что в редиректах мы желаем передать в запросе какие-нибудь дополнительные параметры. Применение флага QSA позволит нам сохранить параметры оригинального запроса, так что ссылка http://site.com/project1/news.pl?mode=daily будет преобразована в http://project1.ru/news.pl?came_from=site.comamode=daily RewriteRule ^project1/?(.*) http://project1.ru/$1?came_from=site.com [R,QSA] RewriteRule ^project2/?(.*) http://project2.ru/$1?came_from=site.com [R,QSA] # Пример 2. Электронная книга отдается динамическим скриптом в то время как нам желательно иметь "красивую" иерархию вида "http://lib.ru/book1/chapter3.html". Кстати, расширение .html помогает нам скрывать динамическую природу нашего веб-сайта RewriteRule ^([a-z0-9]+)/([a-z0-9]+)\.html$ /cgi-bin/view_chapter.cgi?book=$1&chapter=$2 [NC] # Пример 3. Нам желательно скрыть от пользователя используемую на веб-сайте технологию, для чего мы не будем пользоваться расширениями в наших http-ссылках. Без флага L данное правило зациклится RewriteRule (.+) $1.html [L] # В то же время посетитель может ввести ссылку с расширением по одному ему понятным причинам. Правильно обработать такую ситуацию поможет следующее правило: RewriteRule ^([^.]+) $1.html [L] # Пример 4. На веб-сайте есть статические ссылки с расширением .html и динамические ссылки с расширением .pl. Допустим, что динамические ссылки остались прежними, а статические должны обрабатываться cgi-скриптом # Первый вариант предельно прост: RewriteRule (.+)\.html$ /cgi-bin/new_script.cgi?page=$1 [L] # Второй вариант более общий. Например, если нам нужно преобразовать массу различных ссылок кроме одной-двух, можно воспользоваться специальной "заменой без изменения" (обозначается символом -): RewriteRule \.pl$ - [L] RewriteRule (.*) /cgi-bin/new_script.cgi?page=$1 [L] # Пример 5. Есть один особый случай, когда делается внешний редирект на относительную ссылку. Допустим, мы находимся в каталоге /home/site.com/www/test веб-сайта site.com. Каталог доступен по ссылке http://site.com/test/. Нам нужен внешний редирект с файлов *.html на *.shtml. Приводимые директивы записываются в файл /home/site.com/www/test/.htaccess # Решение тривиально, если использовать абсолютную замену, но в этом случае нам приходится жестко прописывать название каталога, что не совсем хорошо: RewriteRule (.+)\.html /test/$1.shtml [R] # Если написать замену как относительную ссылку (см. ниже), то результат будет не таким, каким мы его ожидаем увидеть (это обусловлено особенностями преобразования ссылок на уровне каталогов): например, ссылка http://site.com/test/aaa.html будет преобразована в http://site.com/home/site.com/www/test/aaa.shtml RewriteRule (.+)\.html $1.shtml [R] # По полученной ссылке видно, что там подставлен полный реальный путь к нужному файлу. Решить проблему можно при помощи директивы RewriteBase, параметром которой является префикс для всех относительных замен, находящихся в данном файле .htaccess RewriteBase /test # Пример 6. Задание переменных окружения применяется очень редко, но тем не менее приведем два примера, не нуждающихся в пояснении # Сохраняет в окружении расширение исходного файла RewriteRule ^([^.]+)\.([a-z]+)$ /cgi-bin/new_script.cgi?page=$1 [L,E=EXT:$2] # Сохраняет в окружении содержимое http-заголовка X-Forwarded-For RewriteRule \.(cgi|pl)$ - [L,E=%{HTTP:X-Forwarded-For}]
Несмотря на такое изобилие, преобразование ссылок не ограничивается только директивой # Если подряд записаны несколько директив RewriteCond, то следующая за ними директива RewriteRule проверяется только в том случае, когда "сработали" все директивы RewriteCond: RewriteCond условие1 RewriteCond условие2 RewriteRule преобразование1 RewriteRule преобразование2 # Следует обратить внимание, что в приведенном выше примере вторая директива RewriteRule проверяется в любом случае, так как все директивы RewriteCond относятся только к первой директиве RewriteRule. Если же вы желаете, чтобы условия относились к обеим директивам RewriteRule, то вам придется повторить их еще раз: RewriteCond условие1 RewriteCond условие2 RewriteRule преобразование1 RewriteCond условие1 RewriteCond условие2 RewriteRule преобразование2 # Применение флага OR позволяет объединять условия не по И (как это делается по умолчанию), а по ИЛИ. В следующем примере директива RewriteRule проверяется, если выполняется любое из двух предшествующих условий: RewriteCond условие1 [OR] RewriteCond условие2 RewriteRule преобразование Синтаксис директивы RewriteCond выглядит следующим образом: RewriteCond "проверяемое выражение" "условие" "флаги"
Проверяемое выражение — это строка, которая может состоять из обычных символов, макросов и переменных. Макросы
Переменные записываются в виде
Условие — это обычное регулярное выражение. Кроме регулярных выражений существует еще несколько видов условий (условию может предшествовать символ
Флагов может быть всего два: И, наконец, примеры применения: # Пример 1. Жесткий запрет посещений нашего веб-сайта для робота поисковой системы Google RewriteCond %{USER_AGENT} Googlebot RewriteRule .* - [F] # Другой вариант возвращает вместо ошибки 403 (FORBIDDEN) ошибку 404 (NOT_FOUND) RewriteCond %{USER_AGENT} Googlebot RewriteRule .* - [R=404] # Пример 2. Есть два каталога /home/site/storage1 и /home/site/storage2, в которых нужно искать запрашиваемые файлы RewriteCond /home/site/storage1/%{REQUEST_FILENAME} -f RewriteRule (.+) /home/site/storage1/$1 [L] RewriteCond /home/site/storage2/%{REQUEST_FILENAME} -f RewriteRule (.+) /home/site/storage2/$1 [L] # Пример 3. Если ссылка не найдена на нашем веб-сайте, отправить посетителя на www.site.ru RewriteCond %{REQUEST_URI} !-U RewriteRule (.*) http://www.site.ru/$1 [R] # Пример 4. Закрыть доступ к веб-сайту в рабочее время RewriteCond %{TIME_HOUR}%{TIME_MIN} >1000 RewriteCond %{TIME_HOUR}%{TIME_MIN} <1900 RewriteRule .* - [F] # Пример 5. Есть скрипт, раз в сутки производящий оптимизацию базы данных. Если посетитель зайдет в этот момент на веб-сайт, то получит ошибку - вместо этого необходимо показать ему страницу с сообщением о том, что через пару минут все придет в норму. Оптимизирующий скрипт на время своей работы создает файл /home/site/optimizer.pid RewriteCond /home/site/optimizer.pid -f RewriteRule .* /optimization_message.html # Пример 6. Посетители веб-сайта авторизуются при помощи стандартной авторизации (AuthType BasicAuth). Необходимо по ссылке /home/* показывать содержимое их домашних каталогов RewriteCond %{REMOTE_USER} !="" RewriteCond /home/(%{REMOTE_USER}) -d RewriteRule (.*) /home/%1/$1
И в заключение вкратце упомянем еще о двух директивах преобразования ссылок, которые не входят в модуль # Обе директивы при "срабатывании" возвращают редиректы. В качестве замены всегда должна использоваться абсолютная ссылка # Обычный безусловный редирект: Redirect /news http://www.site.com/cgi-bin/news.cgi # Редирект с подстановкой: RedirectMatch (.*\.gif)$ http://www.site.com/alt/path/to/gif/files$1
Возможно, на первый взгляд преобразование http-ссылок с помощью модуля |
||