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

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

Редиректы

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


<IfModule mod_rewrite.c>
  Options +FollowSymLinks
  RewriteEngine On

  [СЮДА ПИШЕМ ПРАВИЛА]  

</IfModule>

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


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

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

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

%{REQUEST_URI} Строка запроса (без доменного имени, и GET параметров), пример "/server/htaccess/"
%{HTTP_HOST} Доменное имя, например "max22.ru"
%{QUERY_STRING} Строка GET параметров

[УСЛОВИЕ] также как и [ШАБЛОН] представляют собой perl совместимое регулярное выражение, с некоторыми дополнениями, позволяющими например проверить файл ли это, или существующий url.

[ФЛАГИ] Флаги пишутся в квадратных скодках через запятую: [NC,OR]. Флаги для условий:

NC Регистронезависимая проверка
OR Условие сопостовляется с остальными про правилу ИЛИ

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

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

NC Регистронезависимая проверка
R=301 Будет редирект с кодом 301, можно указать другой код
L Это последнее правило, больше не применять правил преобразований

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

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

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

Примеры

 

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

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


RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
RewriteRule ^(.*)$ http://%1/<span< a=""> class="variable">$1 [R=301,L]

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

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


RewriteCond %{HTTP_HOST} ^(.*)$ [NC]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%1/$1 [R=301,L]

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

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


RewriteRule ^news/happy.* /news.html [R=301,L]

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

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


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 [NC]
RewriteCond %{QUERY_STRING} id=(\d+) [NC]
RewriteRule .* /page/%1/? [R=301,L]

Поясню, первым условиям проверяем что есть 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) [NC] 
RewriteCond %{HTTP_HOST} site.ru
RewriteRule ^$ http://m.site.com/ [R=302,L]

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

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

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

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

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


RewriteCond %{HTTP_HOST} ^(.*)$ [NC]
RewriteCond %{HTTP_USER_AGENT} (?i:midp|samsung|nokia|j2me|avant|docomo|novarra|palmos|palmsource|opwv|chtml|pda|mmp|blackberry|mib|symbian|wireless|nokia|hand|mobi|phone|cdm|upb|audio|SIE|SEC|samsung|HTC|mot-|mitsu|sagem|sony|alcatel|lg|eric|vx|NEC|philips|mmm|xx|panasonic|sharp|wap|sch|rover|pocket|benq|java|pt|pg|vox|amoi|bird|compal|kg|voda|sany|kdd|dbt|sendo|sgh|gradi|jb|dddi|moto|iphone|android) [NC]
RewriteRule ^$  http://m.%1 [R=302,L]

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

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

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

 

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


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

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


RewriteRule ^index.php$  /about/ [R=301,L]

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


RewriteRule ^$  /about/ [L]

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


RewriteRule ^$  /about/ [R=301,L]

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


 

В этой статье обсуждается — что такое .htaccess, зачем он нужен, и как его можно использовать.

.htaccess (с точкой в начале имени) – это файл, который дает возможность конфигурировать работу сервера в отдельных директориях (папках), не предоставляя доступа к главному конфигурационному файлу. Например, устанавливать права доступа к файлам в директории, менять названия индексных файлов, самостоятельно обрабатывать ошибки Apache, перенаправляя посетителей на специальные страницы ошибок.

Как известно, конфигурационные директивы сервера Apache находятся в файлe httpd.conf. Но далеко не всегда у Вас будут права доступа к этому файлу. Например, если Вы используете для хостинга виртуальный сервер, когда один сервер Apache обслуживает множество сайтов, то, естественно, Вам никто не позволит менять его конфигурацию. Но, тем не менее, вы можете конфигурировать работу сервера в своих директориях. И делать вы это можете с помощью файлов .htaccess.

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

Изменения, вносимые в файлы .htaccess, вступают в силу немедленно и не требуют перезагрузки сервера, в отличие от изменений, вносимых в главный конфигурационный файл httpd.conf.

Настройки httpd.conf, разрешающие применение файлов .htaccess

Для того, что бы эти файлы .htaccess можно было использовать — необходимы соответствующие настройки главного конфигурационного файла. В файле httpd.conf должны быть прописаны директивы, которые разрешат файлу .htaccess переопределять конфигурацию web-сервера в каталоге. Эта директива называется AllowOverride. Она может быть установлена как для всего сервера (глобально), так и для отдельного каталога.

Директива AllowOverride может включать в себя одну из следующих директив или их комбинацию: All, None, AuthConfig, FileInfo, Indexes, Limit, Options.

Для того чтобы дать директивам файлов .htaccess максимальные права следует прописать в httpd.conf:

AllowOverride All 



 

Примечание

При желании название конфигурационного файла можно изменить, и например, назвать его не .htaccess, a access.conf. За название этого файла отвечает директива AccessFileName в файле httpd.conf. Но все же рекомендуется этого не делать.

Синтаксис .htaccess

Перед тем, как будут рассмотрены примеры, остановимся на синтаксисе директив в файлах .htaccess.

  • Пути к файлам и директориям должны указываться от корня сервера, например, /pub/home/server1/html/

Если вы не знаете путь от корня сервера, то Вы можете его узнать, спросив у администратора сервера, либо можете посмотреть сами, запустив на сайте функцию PHP — phpinfo(). Она выведет на экран конфигурацию PHP в виде фиолетовых таблиц. В них Вам необходимо найти переменную doc_root и посмотреть ее значение — это будет путь от корня сервера до Вашей основной директории.

  • В именах доменов обязательно должны быть указаны протоколы, например:

Redirect / http://www.newsite.ru 



 

Примеры использования .htaccess

Глобальное перенаправление (редирект) на другой адрес:

Redirect / http://www.newsite.ru 




 

Перенаправление (редирект) только при запросе определенных страниц:

redirect /company http://www.newsite.com/newcompany
redirect /forum http://www.newsite.com/newforum 




При запросе страниц из каталогов company и forum будет произведено перенаправление на новые адреса.

 

Перенаправление (редирект) только посетителей с определенным IP-адресом:

SetEnvIf REMOTE_ADDR 192.145.121.1 REDIR="redir"
RewriteCond %{REDIR} redir
RewriteRule ^/$ /only_for_you.html 




Если посетитель имеет IP-адрес 192.145.121.1, то ему будет открыта страница only_for_you.html.

 

Изменение названия индексной страницы:

DirectoryIndex index.html index.php index.shtml 




Можно указать несколько индексных страниц. При запросе каталога они будут искаться в том порядке, в котором перечислены в директиве DirectoryIndex. Если не будет найден файл index.html, то будет произведен поиск файла index.php и т.д.

 

Выполнять код PHP в файлах HTML

RemoveHandler .html .htm
AddType application/x-httpd-php .php .htm .html .phtml 




Добавив эти строки в .htaccess вы дадите директиву серверу выполнять инструкции PHP не только в файлах с расширением *.php и *.phtml, но и в файлах с расширением *.htm и *.html.

 

Обработка ошибок Apache

ErrorDocument 401 /401.html
ErrorDocument 403 /403.html
ErrorDocument 404 /404.html
ErrorDocument 500 /500.html 




При возникновении этих ошибок посетитель будет перенаправлен на специально созданные страницы.

 

  • 401 ошибка — Требуется авторизация (Authorization Required).
  • 403 ошибка — пользователь не прошел аутентификацию, доступ запрещен (Forbided).
  • 404 ошибка — Документ не найден (Not Found).
  • 500 ошибка — Внутренняя ошибка сервера (Internal Server Error).

Запрет на отображение содержимого каталога при отсутствии индексного файла

Options –Indexes 



 

Определение кодировки, в которой сервер "отдает" файлы

AddDefaultCharset windows-1251 




 

Определение кодировки на загружаемые файлы

CharsetSourceEnc windows-1251 




 

Запрет доступа ко всем файлам

deny from all 




Запрещен доступ ко всем файлам и каталогам в текущей директории.

 

Разрешить доступ только с определенного IP-адреса

order deny,allow
deny from all
allow from 195.135.232.70 




Строка order deny,allow определяет, в каком порядке следует выполнять директивы. Сначала выполняется директива запрета доступа, а затем разрешается доступ только для IP-адреса 195.135.232.70. Если в первой строке поменять порядок следования директив на order allow,deny, то доступ для данного IP-адреса не будет открыть, так как директива deny, выполняемая последней перекроет действия директивы allow.

 

Запретить доступ с определенного IP-адреса

deny from 195.135.232.70 




 

Запретить доступ к определенному файлу

<Files config.php>
  deny from all
</Files> 




Запрещен доступ посетителей к файлам config.php. Этот запрет не действует на скрипты web-сервера. Они по прежнему будут иметь доступ к этому файлу.

 

Запретить доступ к файлам с определенным расширением

<Files "*.conf">
  deny from all
</Files> 




Здесь запрещен доступ к файлам с расширением *.conf. Директива , при указании имени файлов, позволяет использовать подстановочные символы.

? - любой одиночный символ
* - любая последовательность символов, исключая символ / (слеш)


 

Запретить доступа к файлам с несколькими типа расширений

<Files ~ "\.(inc|conf|cfg)$">
  deny from all
</Files> 




Запрещен доступ к файлам с расширением *.inc, *.conf и *.cfg. Хотя директива , по умолчанию, не работает с регулярными выражениями, но их можно включить поставив символ тильды(~) в опциях директивы. Синтаксис следующий:
[тильда] [пробел] [далее_все_без_пробелов]

 

Установка пароля на директорию

AuthName "Admin page"
AuthType Basic
AuthUserFile /pub/home/server/.pass
require valid-user
</Files> 




Установка прав доступа с помощью файлов .htaccess более подробно рассмотрена рассмотрена статье:

.htaccess и .htpasswd - защита доступа