Примеры URL преобразований. Принудительное использование канонического имени с HTTPS и www. Как проверить, включён ли mod_rewrite

Возможности 10.05.2019
Возможности

Почему то на просторах рунета информация о локальной настройки веб-сервера Apache посредством конфигурационного файла .htaccess приводится как то не полно и однобоко. В основном приводятся примеры (часто не рабочие) или сухой перевод англоязычной документации.

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

Редиректы

Редиректы осуществляются с помощью модуля mod_rewrite . Задаются правила преобразований в виде следующей конструкции:

Options +FollowSymLinks RewriteEngine On [СЮДА ПИШЕМ ПРАВИЛА]

Правила преобразования записываются в таком виде:

RewriteCond [СТРОКА ДЛЯ СРАВНЕНИЯ] [УСЛОВИЕ] [ФЛАГИ] RewriteCond [СТРОКА ДЛЯ СРАВНЕНИЯ] [УСЛОВИЕ] [ФЛАГИ] RewriteRule [ШАБЛОН] [СТРОКА ПОДСТАНОВКИ] [ФЛАГИ]

Строки RewriteCond - задают условия для срабатывания следующего за ними правила RewriteRule . Условий может быть несколько, они накладываются по правилу AND . Но можно изменить правило на OR с помощью флага OR .

В качестве [СТРОКИ ДЛЯ СРАВНЕНИЯ] могут использоваться различные переменные. Ссылка на полный список Я приведу только те, которые нужны чаще всего:

Подвыражения в регулярных выражениях (заключенные в скобки), доступны для вставки в [СТРОКУ ПОДСТАНОВКИ] , обращаться к подвыражениям нужно так: %N - для подвыражений в условиях (RewriteCond ) и $N - для подвыражений в правилах (RewriteRule ), где N - порядковый номер подвыражения.

RewriteRule - правило подстановки. Если запрос подходит под вышестоящие проверки и [ШАБЛОН] , то применяется правило подстановки. Здесь регулировать поведение также можно с помощью флагов. Флаги есть разные, приведу наиболее часто используемые:

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

Внимание! Браузеры кешируют редиректы!!!

Причем обычные сочетания типа Ctrl+F5 или Ctrl+R не помагают. Я во время тестирования каждый раз открываю страницу в НОВОМ окне в режиме инкогнито. Причем старые страницы в режими инкогнито надо закрывать.

Примеры

Универсальный редирект с www на без www

Тут самое интересное, почему то везде приводятся примеры, жестко привязанные к домену сайта. Зачем?, если есть универсальное решение:

RewriteCond %{HTTP_HOST} ^www\.(.*) RewriteRule ^(.*)$ http://%1/$1

Проверяем доменное имя, если оно начинается с www, то сработает правило: "все, на http://%1/$1 ". Здесь %1 это наш домен без www (взят из условия), а $1 это адрес (взят из самого правила).

Универсальный редирект с без www на www

RewriteCond %{HTTP_HOST} ^(.*)$ RewriteCond %{HTTP_HOST} !^www\. RewriteRule ^(.*)$ http://www.%1/$1

Тут маленько сложнее. Первое условие нужно для того чтобы получить домен (%1 ), оно всегда истина. Второе условие проверяет, что домен начинается не с www. Ну и само правило, аналогичное предыдущему примеру

Простой редирект

RewriteRule ^news/happy.* /news.html

Для простого редиректа условия задавать не обязательно, только правило.

Реврайт без редиректа

RewriteRule ^news/happy.* /news.html [L]

Иногда требуется, чтобы был редирект без смены адреса, т.е. реврайт без редиректа. Для этого просто не указываем флаг редирект (R ), и получаем желаемый результат, теперь по адресу news/happy получим news.html , а в адресной строке останется news/happy

Редирект от GET параметров

Например, нужно что бы со страницы /?action=page&id=15 был редирект на /page/15/ :

RewriteCond %{QUERY_STRING} action=page RewriteCond %{QUERY_STRING} id=(\d+) RewriteRule .* /page/%1/?

Поясню, первым условиям проверяем что есть get параметр action=page , вторым условием проверяем что id равно числу. Эти условия нельзя объединять, т.к. параметры могут идти и наоборот, т.е. index.php?action=page&id=15 и index.php?id=15&action=page должны быть равноценны. Но и наконец правило, там все обычно, кроме знака вопрос (? ) на конце. Он нам нужен, чтобы отсечь исходные GET параметры, иначе получим /page/15/?action=page&id=15

Редирект на мобильную версию сайта

Допустим, что мобильная версия расположена на поддомене 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) RewriteCond %{HTTP_HOST} site.ru RewriteRule ^$ http://m.site.com/

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

Второй строкой проверяем что мы находимся на нужном домене (т.к. пример не универсальный)

Третьей строкой, мы проверяем, что находимся на главной страницы (без всяких параметров и прочего) и перенаправляем на поддомен.

Универсальная версия

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

RewriteCond %{HTTP_HOST} ^(.*)$ 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) RewriteRule ^$ http://m.%1

Редирект с главной страницы

Речь идет про запрос типа site.ru (без site.ru/index.php)

Здесь оказалось не все так очевидно, я столкнулся с необъяснимым поведением.

Рабочий вариант :

RewriteRule ^index.php$ /about/ [L]

Редирект. НЕ рабочий вариант :

RewriteRule ^index.php$ /about/

Реврайт без редиректа (урл не меняется). НЕ рабочий вариант :

RewriteRule ^$ /about/ [L]

Редирект. Рабочий вариант :

RewriteRule ^$ /about/

Если мне кто - нибудь расскажет почему эти примеры работают крест накрест, а обратно не работают - буду очень рад.

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

Самый главный файл .htaccess располагается в корне сайта:

Его действия распространяются на текущий каталог и на все вложенные каталоги. Т.е. у владельцев сайтов есть возможность воздействовать только на работу своего проекта, не мешая работе всего сервера. Если этот файл отсутствует, то его можно создать с помощью любого блокнота. Главное, чтобы название файла было ".htaccess" - без форматов.txt, .doc и т.д.

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

Чуть ниже мы рассмотрим все распространенные варианты редиректов через .htaccess , а для начала ознакомимся с опциями и правилами.

Чтобы иметь возможность работать с редиректами нужно включить модуль ReWriteEngine . Для этого необходимо прописать две строчки кода (желательно в самом верху файла .htaccess ):

Options +FollowSymLinks RewriteEngine On

Разместите эти строки в самом верху файла .htaccess , чтобы иметь возможность работать с директивами модуля mod_write.

Также на хостинге должны быть включены модули mod_alias (для поддержки Redirect, RedirectPermanent и RedirectMatch).

1. Правила Redirect, RewriteRule и RewriteCond

1.1. Директива Redirect

Синтаксис Redirect :

Redirect /откуда http://куда_полный_адрес

Redirect устанавливает прямой редирект с одной страницы на другую.

В status пишут код редиректа. Является необязательным параметром. Чаще всего пишут 301, что сигнализирует о постоянном смене адреса страницы.

Важно, чтобы страница "откуда" была прописана в формате без указания полного адреса сайта, но с указанием полного относительного адреса URL начиная со слэша "/" (т.е. с корня сайта). Страницу куда идет редирект нужно писать полностью, т.е. абсолютный адрес страницы URL (т.е. с названием домена и протокола http или https).

Например

Redirect 301 /oldpage.php http://site/newpage.php

Можно также писать по другому

RedirectPermanent 301 /oldpage.php http://site/newpage.php или Redirect permanent 301 /oldpage.php http://site/newpage.php

1.2. Директива RewriteRule

Директива RewriteRule устанавливает правила перехода. Синтаксис следующий:

RewriteRule Шаблон Подстановка [коды]
  • При внешнем редиректе меняется урл адреса в строке браузера - " "
  • При внутреннем - не меняет урл адреса в строке браузера - " " или "[L] "

1.3. Директива RewriteCond

Директива RewriteCond определяет условия при котором выполняется правила в RewriteRule.

RewriteCond Сравниваемая_Строка Условие

Например, этими условиями могут быть браузер пользователя, IP-адрес , заголовок и т.д.

1.4. Директива RedirectMatch

Директива RedirectMatch аналогична Redirect с той лишь разницей, что позволяет записывать регулярные выражения.

RedirectMatch Откуда Куда

2. Примеры 301 редиректов в.htaccess

Мы уже рассматривали множество примеров с редиректом по .htaccess в статьях:

  • Смена адреса сайта - редирект со старого домена на новый

Здесь мы дополним варианты редиректов, которых еще не было.

2.1. Редирект с одной страницы на другую

Редирект с site.ru/cat/oldpage на site.ru/newpage.html

RewriteRule ^cat/oldpage.* /newpage.html

Или второй вариант:

Redirect 301 /cat/oldpage http://www.site.com/newpage.php

2.2. Редирект со всех файлов.htm на.html

RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)\.htm$ $1.html

Или второй вариант:

RewriteRule ^(.*)\.htm$ $1.html

2.3. Редирект всего каталога на другую страницу

С любой страницы в каталоге и подкаталогах /old/ будет происходит редирект на /new.php

RewriteRule ^old(.*)$ /new.php

2.4. Удаление лишних слэшей в адресе URL

Например, страница /catalog///stranica.html доступна и открывается. Чтобы избежать такой ситуации и не плодить бесконечное число дублей следует записать следующий редирект

RewriteCond %{REQUEST_URI} ^(.*)//(.*)$ RewriteRule . %1/%2

2.5. Реврайт без редиректа

Можно загрузить другую страницу без смены адреса страницы URL. Например, загрузим страницу /news.html , а в адресной строке будет отображаться адрес /news/happy

RewriteRule ^news/happy.* /news.html [L]

2.6. Простановка замыкающего слеша в конце адреса главной страница

Например, многие сервера работают так, что последний слэш не пишется в URL. Например, http://site.ru . Ниже приведенный код решают это проблему: сайт будет открывать по http://site.ru/

RewriteCond %{REQUEST_URI} /+[^\.]+$ RewriteRule ^(.+[^/])$ %{REQUEST_URI}/

2.7. Удаляем директорию каталога из URL

Например для редиректа со страницы site.com/directoriya/stranica.html на site.com/stranica.html нужно прописать следующее:

RewriteRule ^directoriya/(.+)$ http://site.com/$1

Или второй вариант:

RewriteCond %{DOCUMENT_ROOT}/directoriya/$1 -f RewriteRule ^(.*)$ directoriya/$1

2.8. Редирект GET параметров

Например, сделать редирект со страницы /?act=page&id=2 на /page-2/

RewriteCond %{QUERY_STRING} act=page RewriteCond %{QUERY_STRING} id=(\d+) RewriteRule .* /page/%1/? ]

2.9. Редирект на мобильную версию сайта m.site.ru

В данном примере сначала проверяется факт того, что пользователь открыл сайт с мобильного устройства {HTTP_USER_AGENT} , далее происходит замена адреса сайта на m.URL

RewriteCond %{HTTP_HOST} ^(.*)$ 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) RewriteRule ^$ http://m.%1

2.10. Редирект с поддомена

Например, выполним редирект с любой страницы поддомена poddomen.site.ru на основной домен site.ru

RewriteCond %{HTTP_HOST} ^poddomen.site.ru$ RewriteRule ^(.*)$ http://site.ru%{REQUEST_URI}

3.Другие примеры с htaccess

3.1. Запретить IP-адрес и браузер

Запретим открывать сайт для пользователя с браузера IE с IP-адресом 172.111.222.55

RewriteCond %{HTTP_USER_AGENT} MSIE RewriteCond %{REMOTE_ADDR} ^172\.111\.222\.55$ RewriteRule ^.*$ - [F]

3.2. Запретить конкретный файл

Запретим для всех файл disable_file.html :

deny from all

3.3. Разрешить доступ с одного ip

Доступ будет разрешен только с одного ip-адреса 172.111.222.55

order deny,allow deny from all allow from 172.111.222.55

3.4. Запретить доступ с разных ip

Запретить доступ к сайту с нескольких ip-адреса 172.112.222.55, 172.113.222.55, 172.114.*.*

order deny,allow deny from all deny from 172.112.222.55 deny from 172.113.222.55 deny 172.114.*.*

3.5. Редирект в URL с больших символов на маленькие

Все большие буквы в адресе URL будут переведены на маленькие.

RewriteRule - RewriteRule ! - RewriteRule ^([^A]*)A(.*)$ $1a$2 RewriteRule ^([^B]*)B(.*)$ $1b$2 RewriteRule ^([^C]*)C(.*)$ $1c$2 RewriteRule ^([^D]*)D(.*)$ $1d$2 RewriteRule ^([^E]*)E(.*)$ $1e$2 RewriteRule ^([^F]*)F(.*)$ $1f$2 RewriteRule ^([^G]*)G(.*)$ $1g$2 RewriteRule ^([^H]*)H(.*)$ $1h$2 RewriteRule ^([^I]*)I(.*)$ $1i$2 RewriteRule ^([^J]*)J(.*)$ $1j$2 RewriteRule ^([^K]*)K(.*)$ $1k$2 RewriteRule ^([^L]*)L(.*)$ $1l$2 RewriteRule ^([^M]*)M(.*)$ $1m$2 RewriteRule ^([^N]*)N(.*)$ $1n$2 RewriteRule ^([^O]*)O(.*)$ $1o$2 RewriteRule ^([^P]*)P(.*)$ $1p$2 RewriteRule ^([^Q]*)Q(.*)$ $1q$2 RewriteRule ^([^R]*)R(.*)$ $1r$2 RewriteRule ^([^S]*)S(.*)$ $1s$2 RewriteRule ^([^T]*)T(.*)$ $1t$2 RewriteRule ^([^U]*)U(.*)$ $1u$2 RewriteRule ^([^V]*)V(.*)$ $1v$2 RewriteRule ^([^W]*)W(.*)$ $1w$2 RewriteRule ^([^X]*)X(.*)$ $1x$2 RewriteRule ^([^Y]*)Y(.*)$ $1y$2 RewriteRule ^([^Z]*)Z(.*)$ $1z$2 RewriteRule - [N] RewriteCond %{ENV:HASCAPS} TRUE RewriteRule ^/?(.*) /$1

RewriteRule определяет правила для механизма преобразований

Синтаксис: RewriteRule Шаблон Подстановка (пример, RewriteRule ^tags$ /tags.php [L] )

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

В качестве третьего аргумента директивы RewriteRule. Флаги — это разделённый запятыми, следующий список флагов:

  • "redirect|R [=code]" (вызывает редирект)

Префикс в Подстановке вида http://thishost[:thisport]/ (создающий новый URL из какого-либо URI) запускает внешний редирект (перенаправление). Если нет накакого кода в подстановке ответ будет с HTTP статусом 302 (ВРЕМЕННО ПЕРЕМЕЩЕН). Если вы хотите использовать дркгие коды ответов в диапазоне 300-400, просто напишите их в виде числа или используйте одно из следующих символических имён: temp (по-умолчанию), permanent, seeother. Используйте это в директивах, которые должны преобразовывать некие виртуальные URL в реальные и возвращать их клиенту, например, преобразовывать «/~» в «/u/» или всегда добавлять слэш к /u/user, и т.д.

Примечание: При использовании этого флага, убедитесь, что поле подстановки, это работающий URL! Если это не так, вы перенаправляете в никуда! И помните, что сам по себе этот флаг, только дополняет URL строкой http://thishost[:thisport]/, и процесс преобразования продолжается. Также, обычно вы хотите остановиться и сделать этот редирект немедленно. Для остановки процесса преобразования, вам также нужно написать флаг "L".

  • "forbidden|F" (делает URL запрещенным)

Это делает текущий URL запрещённым, например, клиенту немедленно отправляется ответ с HTTP статусом 403 (ЗАПРЕЩЕНО). Используйте этот флаг в сочетании с соответствующими RewriteConds для блокирования URL по некоторым критериям.

  • "gone|G" (делает URL «мёртвым»)

Этот флаг делает текущий URL «мертвым», т.е., немедленно отправляется HTTP ответ со статусом 410 (GONE). Используйте этот флаг для маркировки «мертвыми» не существующие более страницы.

  • "proxy|P" (вызвает прокси)

Этот флаг помечает подстановочную часть как внутренний запрос прокси и немедленно (т.е., процесс преобразования здесь останавливается) пропускает его через прокси модуль. Вы должны убедиться, что строка подстановки это реальный URI (например, типично начинающийся с http://hostname), который может быть обработан прокси модулем Apache. Если это не так, вы получите ошибку от прокси модуля. Используйте этот флаг для того, чтобы добиться более мощной реализации диркетивы ProxyPass, интегрирующей некоторое содержимое на удаленных серверах, в пространство имён локального сервера.

Примечание: Для того чтобы это использовать убедитесь что у вас есть работающий прокси модуль на вашем сервере Apache. Если вы не знаете этого проверьте есть ли в выводе «httpd -l» строчка mod_proxy.c. Если да, эти возможности доступны mod_rewrite. Если нет, то сначала вы должны пересобрать программу «httpd» с включенным прокси модулем.

  • "last|L" (последнее правило)

Остановить процесс преобразования на этом месте и не применять больше никаких правил преобразований. Это соответствует оператору last в Perl или оператору break в языке C. Используйте этот флаг для того, чтобы не преобразовывать текущий URL другими, следующими за этим, правилами преобразований. К примеру, используйте это для преобразования корневого URL из ("/") в реальный, например, "/e/www/".

  • "next|N" (следуюший раунд)

Перезапустить процесс преобразований (начав с первого правила). В этом случае URL снова сопоставляется неким условиям, но не оригинальный URL, а URL вышедший из последнего правила преобразования. Это соответствует оператору next в Perl или оператору continue из языка C. Используйте этот флаг для перезапуска процесса преобразований, т.е., безусловному переходу на начало цикла.

Однако будьте осторожны, для того чтобы не сделать бесконечный цикл!

  • "chain|C" (связь со следующим правилом)

Этот флаг связывает текущее правило со следующим (которое, в свою очередь, может быть связано со следующим за ним, и т.д.). Это имеет следующий эффект: если есть соответствие правилу, процесс продолжается как обычно, т.е., флаг не производит никакого эффекта. Если правило не соответствует условию, все следующие, связанные правила, пропускаются. Например, импользуйте это для удаления «.www» части в конфигурационном правиле контекста каталога работающего когда вы разрешаете внешний редирект (где не должно быть «.www»!).

  • "type|T=MIME-тип" (принудительно установить MIME тип)

Принудительно установить MIME-тип целевого файла в MIME-тип. К примеру, это можно использовать для имитации mod_alias директивы ScriptAlias которая принудительно устанавливает для всех файлов внутри отображаемого каталога MIME тип равный «application/x-httpd-cgi».

  • "nosubreq|NS" (используется только в случае невнутреннего подзапроса)

Этот флаг дает команду механизму преобразований пропустить директиву если текущий подзапрос является внутренним подзапросом. К примеру, внутренние подзапросы в Apache происходят тогда, когда mod_include пытается получить информацию о возможных файлах по-умолчанию для каталогов (index.xxx). При подзапросах это не всегда полезно и даже иногда вызывает проблему в работе всего набора директив преобразований. Используйте этот флаг для исключения некоторых правил.

Используйте следующее правило по своему усмотрению: всякий раз когда вы предваряете некоторые URL префиксом передавая их на обработку CGI-скрипту, — велик шанс что вы напоретесь на проблемы (или даже на ненужные издержки) в случае применения подзапросов. В этих случаях, используйте этот флаг.

  • "nocase|NC" (не учитывать регистр)

Это делает Шаблон нечуствительным к регистру, т.е., нет различий между "A-Z" и "a-z" когда Шаблон применяется к текущему URL.

  • "qsappend|QSA" (добавлять строку запроса) - Query String Append

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

Пример на learnsongs.ru:

RewriteRule ^tags/([-A-Za-z0-9_’]+)$ /tags.php?tag=$1

RewriteRule ^tags/([-A-Za-z0-9_’]+)?page=(+)$ /tags.php?tag=$1&page=$2

  • "noescape|NE" (не экранировать URI при выводе)

Этот флаг не даёт mod_rewrite применять обычные правила экранирования URI к результату преобразования. Обычно, специальные символы (такие как "%", "$", ";", и так далее) будут экранированы их шестнадцатиричными подстановками ("%25", "%24", и "%3B", соответственно); этот флаг не дает это делать. Это позволяет символам процента появлятся на выходе, как в

RewriteRule /foo/(.*) /bar?arg=P1\%3d$1

Для которого "/foo/zed" преобразовывалось бы в безопасный запрос "/bar?arg=P1=zed".

  • "passthrough|PT" (пропускать через следующий обработчик)

Этот флаг даёт команду механизму преобразований устанавливать поле uri внутренней структуры request_rec равным полю filename. Этот флаг, просто лишь хитрый трюк, для того чтобы иметь возможность обработки вывода директив RewriteRule, директивами Alias, ScriptAlias, Redirect, и т.д. из других трансляторов URI-имя файла. Тривиальный пример для показа этой семантики: если вы хотите преобразовать /abc в /def с использованием механизма преобразований mod_rewrite и затем /def в /ghi с использованием mod_alias:

RewriteRule ^/abc(.*) /def$1

Alias /def /ghi

Если вы опустите флаг PT, mod_rewrite прекрасно сделаетс свою работу, т.е., он преобразует uri=/abc/... в filename=/def/... как должен делать полностью API-совместимый транслятор URI-имя файла. Затем настаёт очередь mod_alias пытающегося сделать переход URI-имя файла который и не будет работать.

Примечание: Вы должны использовать этот флаг если вы хотите смешивать директивы разных модулей содержащих трансляторы URL-имя файла. Типичный пример это использование модулей mod_alias и mod_rewrite..

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

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

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

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

Что такое mod_rewrite?

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

Http://www.example.com/page.html

Обычно Apache отправляет обратно пользователю содержание файла page.html . Однако с помощью mod_rewrite можно отправить содержание с другого URL, например такого:

Http://www.example.com/another_page.html

Важно понимать, что изменение адреса происходит внутри сервера Apache. Адресная строка браузера по прежнему будет показывать http://www.example.com/page.html , но сервер Apache отправит содержание страницы http://www.example.com/another_page.html . В этом заключается отличие от перенаправления HTTP, которое указывает браузеру посетить другой URL.

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

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

Модуль mod_rewrite позволяет создавать правила манипулирования адресами URL. Например, вы можете вставить значение полученное из запрашиваемого URL в новый URL, организуя динамическое перенаправление URL. Или можно проверить переменные сервера, например, HTTP_USER_AGENT (тип браузера), и изменять URL только если используется браузер, например, Safari, запущенный на iPhone.

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

  • Создание "дружественных" адресов URL, которые маскируют "корявые" адреса URL. Например, вы можете маскировать с помощью отлично выглядящего адреса URL www.example.com/articles/my-article/ реальный адрес URL www.example.com/display_article.php?articleId=my-article . И каждый сможет использовать "дружественный" адрес URL вместо реального.
  • Блокировать использование ссылок на изображения на вашем сайте. Чтобы остановить использование другими ресурсами изображений, размещенных на вашем сайте, можно использовать mod_rewrite для отправки ошибки "Forbidden", если ссылающийся URL не принадлежит вашему сайту.
  • Перенаправление канонических адресов URL. Многие страницы доступны через несколько адресов URL — например, www.example.com/mypage.html и example.com/mypage.html . Вы можете использовать mod_rewrite постоянного перенаправления браузера на "правильный" URL, например www.example.com/mypage.html . Помимо прочего такое использование mod_rewrite гарантирует отображение правильного URL в результатат поиска.
  • Исключение ошибки 404 в момент реорганизации вашего сайта. Например, вы переделываете сайт и переместили страницу www.example.com/myarticle.html по новому адресу www.example.com/articles/myarticle.html . С помощью mod_rewrite вы можете перенаправить www.example.com/myarticle.html на www.example.com/articles/myarticle.html , так что посетитель не получит ошибку 404 "не найдена" при посещении старого адреса URL. Благодаря гибкости mod_rewrite, можно легко создать правило, которое будет перенаправлять запросы на старые адреса URL на новые адреса.

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

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

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

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

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

RewriteEngine on RewriteRule ^dummy\.html$ http://www.google.com/

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

  • RewriteRule ^dummy\.html$ http://www.google.com/ - перенаправялем запросы к странице dummy.html на сайт Google, используя перенаправление 301.

Если теперь открыть веб-браузер и посетить страницу dummy.html на вашем сайте (например, введя в адресной строке http://www.example.com/dummy.html), то, если все было сделано без ошибок, произойдет перенаправление на сайт http://www.google.com .

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

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

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

RewriteRule Pattern Substitution

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

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

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

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

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

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

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

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

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

RewriteEngine on RewriteRule ^my-old-url\.html$ /my-new-url.html

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

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

Пример 2: создание дружественных адресов URL

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

Http://www.example.com/display_article.php?articleId=my-article

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

Http://www.example.com/articles/my-article/

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

RewriteEngine on RewriteRule ^articles/([^/]+)/?$ display_article.php?articleId=$1 [L]

Описание правила 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.

Выше приведенное правило RewriteRule берет запрашиваемый URL в формате http://www.example.com/articles/my-article/ и преобразует его в URL вида http://www.example.com/display_article.php?articleId=my-article .

Пример 3: предотвращаем использование ссылок на изображения на вашем сайте

Еще одной типовой задачей, которую решает использование модуля mod_rewrite, является предотвращение использования ссылок на изображения на вашем сайте другими веб проектами. Допустим, на вашем сайте есть страница http://www.example.com/mypage.html , которая содержит следующий тег img:

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

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

Вы можете использовать следующие директивы mod_rewrite для того, чтобы прекратить использование ссылок на изображения всеми другими сайтами, кроме вашего собственного. Разместите ниже приведенный код в файле.htaccess в корневом каталоге вашего сайта или в папке с изображениями, которые надо защитить. Измените example.com на имя вашего домена.

RewriteEngine on RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !^http://(www\.)?example\.com/.*$ RewriteRule .+\.(gif|jpg|png)$ - [F]

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

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

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

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

Заключение

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

Htaccess. правило RewriteRule: просто, понятно, с примерами и объяснениями
Мы, как веб программисты, часто сталкиваемся с файлом .htaccess и в частности с его модулем MOD_REWRITE и синтаксисом RewriteRule . И по началу трудно разобраться и понять принцип его работы, правила по которым он работает и механизм преобразования динамических ссылок в статические и наоборот. В этой статье я постараюсь максимально просто, максимально доступно, с объяснениями и примерами растолковать так, что бы у Вас не осталось каких либо вопросов.
За преобразование динамических ссылок в статические отвечает модуль mod_rewrite с синтаксисом RewriteRule , принцип работы и правило преобразования, которого я и буду объяснять.
Для примера возьмем динамическую ссылку, которую нам надо преобразовать:

В этой ссылке мы включили максимально возможное количество передаваемых параметров на нашем сайте.
То есть, в каталоге выбрали авто BMW, модель X5, состояние – новое, страница 5.

В файле .htaccess , который мы разместим в корневой папке каталога catalog/ записываем (файл .htaccess действует только на каталог где он расположен и на его дочерние каталоги):
RewriteEngine on (включаем процесс преобразования ссылок)
RewriteRule ^(+)/([^/]+)/(.*)/(+).html$ index.php?auto=$1&model=$2&state=$3&page=$4 [L]

Давайте подробней разберемся, что здесь написано:
^ Начало строки;
(+) Скобки создают переменную, которую подставляем в динамическую ссылку $1. То есть
Переменная $1 = ([ A- Za- z0-9-]+)
Переменная $2 = ([^/]+)
Переменная $3 = (.*)
Переменная $4 = (+)
В скобках [ A- Za- z0-9-] класс допустимых символов. В данном случае допустимыми символами являются A B C D…Z a b c…z 0 1 2 3…9 – Если мы хотим добавить символы, например, ? ; : то получим следующее то есть просто дописали их.
+ означает что мы добавляем еще один символ для подстановки.
Выражение ([^/]+) означает любой символ кроме(^ означает кроме) слеша назад. + означает добавить еще символ.
Выражение (.*) Точка означает любой единичный символ, * означает как и плюс – добавить еще символ.
Выражение (+) думаю, тут понятно.
.html – означает что статическая строка оканчивается на.html
Слеши / означают слеши в статической ссылке.

Следует отметить, что данный мод преобразовывает ссылки не с динамической в статические ссылки а НАОБОРОТ! То есть, на сайте мы пишем статические ссылки, а мод рерайт преобразовывает статическую ссылку с сайта на динамическую. То есть представленную выше ссылку мы должны записать на сайте в виде статической:
site.ru/catalog/ BMW/X5/NEW/5.html
А модуль RewriteRule эту ссылку преобразовывает в динамическую по правилу записанному в .htaccess и выдает сайту:

На выходе получается ссылка: site.ru/catalog/index.php?auto=BMW&model=X5&state=NEW&page=5
Которая и понятно нашим php скриптам и страницам сайта.
Так же к выше изложенному правилу преобразования следует добавить правила для ссылки без переменной номера страницы page, а так же возможных вариантов с отсутствием переменных.
RewriteRule ^(+)/([^/]+)/(.*).html$ index.php?auto=$1&model=$2&state=$3 [L]
RewriteRule ^(+)/([^/]+).html$ index.php?auto=$1&model=$2 [L]
RewriteRule ^(+).html$ index.php?auto=$1 [L]
Ниже приведу возможные обозначения и символы используемые в модуле MOD_REWRITE:
. Любой одиночный символ . Если нам в круглых скобках нужна именно точка а не любой одиночный символ ее нужно экранировать. Обратный слеш экранирует какой либо символ () ? > и т.п. и передает его истинное значение.
Класс симвлолв : Один из символов например {2,5}- фигурные скобки означают диапозон количества символов, в данном случае допускается от 2 до 5 символов.
[^chars] Класс симвлолв : Ни один из символов. [^fg57] – символы f g 5 7 запрещены.
text1|text2 Альтернатива: text1 или text2. например означает или a или b или c
Кванторы (символы для обозначения количественных отношений):
? 0 или 1 из предшествующего текста Означает либо есть символ или какое-то значение символов или их может не быть.
* 0 или N из предшествующего текста (N > 0)
+ 1 или N из предшествующего текста (N > 1)
макрос "$1 " обозначает ту часть исходного пути, которая расположена внутри первой пары скобок "RewriteRule ^(.*)....." , $2 – внутри второй пары и так далее.
Маркеры:
^ Маркер начала строки
$ Маркер конца строки

Пример RewriteRule с пояснениями:
Допустим, у нас на сайте есть статьи, которые имеют динамические страницы:
http://www.site.ru/articles?id=(id статьи)
Сделаем, чтобы ссылка на наши статьи была более красива, например:
http://www.site.ru/nazvanie-stati/ или
http://www.site.ru/nazvanie-stati.html
Для этого, в нашей MySQL таблице, добавляем дополнительную строку, в которой будем хранить уникальное название статьи латинскими буквами без пробелов, слешов и специальных символов, недопустимых в ссылках. Например: Moya-pervaya-statya ну и по такому принципу. Назавем строку в нашей таблице, например eng_name_stati
Динамическая ссылка теперь будет иметь вид:
http://www.site.ru/articles?eng_name_stati=(Moya-pervaya-statya и т.д.)
Главный момент, который нужно понять, файл .htaccess , как я говорил выше, не преобразует динамические ссылки в статические, а наоборот, статические преобразовывает в динамические.
Правило преобразования RewriteRule будет иметь вид:
RewriteRule ^(.*)/$ articles?eng_name_stati=$1 [L] для вида статической ссылки: http://www.site.ru/nazvanie-stati/ или
RewriteRule ^(.*).html$ articles?eng_name_stati=$1 [L] для вида
Теперь, когда мы введем ссылку http://www.site.ru/nazvanie-stati.html в браузере, мы попадем на нашу статью http://www.site.ru/articles?eng_name_stati=nazvanie-stati и эти обе ссылки будут рабочими. На нашем сайте мы просто ставим ссылки в статическом виде для поисковых систем. И когда люди заходят по статической ссылке, наш файл .htaccess преобразовывает ее в динамическую, понятную для нашего сайта и видную только ему.

Дополнение:

Бывает так, нужно сначала проверить, не является ли это ссылка на существующий файл на нашем сервере, например /catalog/webmaster/index.html может оказаться существующим файлом, но если эта ссылка попадет под соответствующее правило RewriteRule она согласно этому правилу преобразуется. Поэтому, если нам сначала нужно проверить, не является ли этот файл или директория прямая, нужно пред правилом RewriteRule написать условие если :

Если нет такой папки
Если нет такого файла
Выполнить преобразование

Выглядеть это будет так:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)/([^/]+)/([^/]+).html$ index.php?catalog=$1&webmaster=$2&file=$3 [L]

Где, RewriteCond – условие если , %{REQUEST_FILENAME} – полный системный путь к запрашиваемому файлу или директории, Восклицательный знак ! означает отрицание не , -d – дериктория, -f – файл.

Теперь, прежде чем применить правило RewriteRule, будет проверено условие RewriteCond

Почему Вы еще не прокомментировали?
Оставьте свой



Рекомендуем почитать

Наверх