Основные приёмы .htaccess
Регулярные выражения в файле .htaccess
Регулярные выражения в файле .htaccess используются в RewriteCond и RewriteRule, то есть для описания условий срабатывания правил и для описания самих правил. С помощью регулярных выражений задаются шаблоны строк. Синтаксис - такой же как в языке Perl.
Элементы
Метасимволы
Используются для задания групп символов или «меток» в шаблоне. Например, метки начала или конца строки.
\ | Экранирование. Считать следующий метасимвол обычным символом. |
^ | Метка начала строки. |
$ | Метка конца строки. |
.(точка) | Заменяет собой любой произвольный символ, но только один. Кроме символа конца строки. |
| | Логическое ИЛИ, варианты выборки. |
() | Группировка. |
[] | Класс символов. Например, [abc]. |
[^...] | Инвертированный класс символов. Например, [^abc]. |
Группировка () также используется для обратной связи с шаблоном, вернее для части строки, которая попадёт под группировку.
Модификаторы
Ставятся после обычных символов, метасимволов или их групп. Расширяют возможности использования шаблонов.
? | Символ повторяется 0 или 1 раз. |
* | Повторяется от 0 до 65536 раз. |
+ | Повторяется от 1 до 65536 раз. |
{n} | Точно n раз. |
{n,} | От n до 65536 раз включительно. |
{n,m} | От n до m раз включительно. |
Примеры шаблонов
^linux
Любые строки, начинающиеся со слова linux. Строка, начинающаяся со слова altlinux не удовлетворит критерию.
windows$
Любые строки, заканчивающиеся набором символов windows. Строка, заканчивающаяся на windows-suck под выбор не попадёт.
.*
Любой символ повторяется любое количество раз. Под критерий попадут все строки.
^(.*)$
Выбрать любую строку и сохранить её как переменную $1 для дальнейшего использования.
^(.+)/(.+)$
Разбить строку на две части: до слэша и после, части строки будут доступны по переменным $1 и $2.
Слеш является таким же символом, как и все остальные. Пример для ясности:
RewriteRule ^(.+)/(.+)$ /?a=$1&b=$2 [R=301,L]
http://www.it-simple.ru/1/2/3/4/5 →
http://www.it-simple.ru/?a=1/2/3/4&b=5
[0-9]{1,6}$
Выбрать все строки, оканчивающиеся от 1 до 6 цифами из диапазона от 0 до 9.
Примеры правил
В начало .htaccess обычно ставят:
RewriteEngine On RewriteBase /
Первая строка включает обработку правил, вторая — обрезает полный путь (от корня сервера) до корня сайта./home/papka-s-saitom/public_html/razdel/podrazdel/
— таким был путь до RewriteBase /
/razdel/podrazdel/
— таким станет после
Благодаря «RewriteBase /» удобнее делать преобразования URI (убирается привязка к физическому расположению файлов сайта на сервере).
Ставим 301 редирект с www.имя.сайта на имя.сайта
(убираем "www").
RewriteCond %{HTTP_HOST} ^www.имя.сайта$ RewriteRule (.*) http://имя.сайта/$1 [R=301,L]
Делается для поисковых машин, чтобы не бить статистику.
При запросе файла .htaccess
говорим, что он не существует (410, GONE).
RewriteRule ^/.htaccess$ - [G]
Запрещаем вход на сайт Интернет Експлореру (вернее, кто себя так определяет) и пользователям с определённого IP-адреса (xxx.xxx.xxx.xxx).
RewriteCond %{HTTP_USER_AGENT} MSIE RewriteCond %{REMOTE_ADDR} ^xxx\.xxx\.xxx\.xxx$ RewriteRule ^.*$ - [F]
Изменяем переменные php и передаём обработку другому скрипту.
RewriteCond %{QUERY_STRING} ^parameter=(.+)$ RewriteRule (.*) parameter.php\?%1 [L]
В этом примере запрос вида
index.php?parameter=some
преобразуется в
parameter.php?some
Убираем переменные php из запроса
(вырезаем из URI всё, что находится после знака вопроса)
RewriteRule (.*) $1? [R=301,L]
Синтаксис и регулярные выражения .htaccess
Для создания правил в .htaccess, в частности при использовании RewriteRule, RewriteCond или RedirectMatch, используется специальный синтаксис и регулярные выражение. Для многих это темный лес, хотя сложного в этом ничего нет. Под синтаксисом подразумевается использование специальных символов, которые имеют особое значение. На регулярных выражениях стоит остановиться отдельно — это рабочие лошадки для созданий гибких правил в .htaccess. По своей сути регулярное выражение является шаблоном, с которым сравнивается исходная строка. Ниже список специальных символов и их описание:
- “^” — символ обозначающий начало строки. При создании правил с использованием директив RedirectMatch и RewriteRule, в начале шаблона следует указывать этот символ, для обозначения начала строки.
RewriteRule ^test$ /test2.html В этом примере строка должна начинаться с "test". То есть, адрес вида cat/test не будет преобразован, потому что начало строки у него "cat", а не "test"
- “$” — символ обозначающий конец строки. Следует указывать в конце шаблона для обозначения конца строки.
RewriteRule ^test$ /test2.html В этом примере строка должна заканчиваться на "test". То есть, адрес test/some_url не будет преобразован, потому что конец строки у него "some_url, а не "test".
- “()” — круглые скобки. Используются для выделения группы символов. Группировка, в том числе необходима для использования обратных RewriteCond и RewriteRule связей.
RewriteRule ^test/(.*).html$ /test2/$1.html В этом примере в скобах сгруппированы символы находящиеся после /test/ и перед .html.
- “.” — точка. Обозначает любой символ.
RewriteRule ^te.t$ /test2.html В этом примере вместо точки может быть использован любой символ, в том числе и точка. То есть teet -> test2.html или tezt -> test2.html и т.д.
- “|” — альтернативный выбор. Например, выражения "A|B" означают "A или B".
RewriteRule ^te(s|z|r|g)t$ /test2.html [R=301,L] Символы для выбора следует объединять в группы. В этом примере только с адресов /test, /tezt, /tert и /tegt будет произведен редирект на адрес /test2.html.
- “?” — ставится после символа или группы символов. Обозначает, что этот символ (группа) может как присутствовать, так и отсутствовать.
RewriteRule ^tes?t$ /test2.html "test" или "tet" будут преобразованы в test2.html. То же самое с группами символов в скобках.
- “*” — ставится после символа (группы). Обозначает, что символ (группа) может отсутствовать или присутствовать неограниченное число раз подряд.
RewriteRule ^te*st$ /test2.html tst, test или teeeeeeeeest будут преобразованы в test2.html. То же самое с группами символов в скобках.
- “+” — действует аналогично символу “*”, но предшествующий ему символ обязательно должен присутствовать хотя бы один раз.
RewriteRule ^tes+t$ /test2.html test или tessssssst будут преобразованы в test2.html. То же самое с группами символов в скобках.
- “[]” — квадратные скобки. Используются для перечисления допустимых диапазонов символов. Работает аналогично символу “|”, но является более оптимальным вариантом по удобству и быстродействию. Поддерживается указание диапазонов значений. [0-9] — все символы от 0 до 9, [a-z] или [A-Z] — все символы латинского алфавита. Если в в начале скобок стоит символ “^”, это означает перечисление недопустимых символов. [^0-9] — допускаются любые символы кроме цифр.
RewriteRule ^te[a-z]t$ /test2.html На третьей позиции может находится любой символ латинского алфавита, /teat, /tebt, tect и т.д. RewriteRule ^te[a-z,0-9]t$ /test2.html Можно указывать диапазоны значений через запятую.
- “{}” — фигурные скобки, указываются после символа, группы символов или диапазона символов. Означает минимальное и максимальное количество символов (групп), которое может присутствовать.
RewriteRule ^(test){1,9}$ /test2 [R=301,L] В этом примере словосочетание "test" может присутствовать в строке 1 или 9 раз. То есть для /test, /testtest, или /testtesttesttesttesttesttesttesttest будет сработано перенаправление RewriteRule ^[a-z]{3,5}$ /test2 [R=301,L] В этом примере перенаправление сработает только для адресов состоящих только из латинских символов и содержащих от 3-х до 5-ти символов.
- “\” — обратный слэш. Используется для экранирования спецсимволов, когда нужно использовать их именно как обычный символ, а не как спецсимвол.
RewriteRule ^test.html$ /test2.html В этом примере перед "." стоит обратный слеш, соответственно точка будет воспринята именно как точка, а не как любой символ. Если его убрать, вместо точки может быть использован абсолютно любой символ.
- “$N” — "N" это число от 0 до 9. Используется для обращения к группам символов из шаблона RewriteRule для последующей подстановки, обратная RewriteRule связь.
RewriteRule ^test/(.*).html$ /test2/$1.html В этом примере все символы в круглых скобках подставляются вместо $1. /test/some-url -> /test2/some-url
- “%N” — "N" это число от 0 до 9. Используется для обращения к группам символов из шаблона RewriteCond для последующей подстановки, обратная RewriteRule связь.
RewriteCond %{QUERY_STRING} ^id=(.*)$ RewriteRule ^(.*)$ /test/%1? [R=301,L] В этом примере группа символов в директиве RewriteCond будет подставлена вместо %1.
Три важных совета и четырнадцать конкретных примеров установки 301 переадресации страниц через htaccess!
Советы
- Располагайте переадресации страниц в файле от частных к более глобальным (сверху вниз). Например: простая переадресация двух страниц стоит выше, чем глобальное правило редиректов с www на без www.
- Избегайте двух, трех и т.д. последовательных редиректов. Правила должны быть настроены так, что при возникновении редиректа он должен перенаправлять пользователя (робота) только один (!) раз. Каждое лишнее переадресация – это секунды драгоценного времени отдачи страницы, это нагрузка на сервер, это нечеткие команды для поисковых роботов.
- Не забывайте, что многие браузеры кешируют (запоминают редиректы), поэтому проверять переадресации лучше на сайте — http://www.bertal.ru .
Правила переадресаций
1. 301 редирект с одной страницы на другую
Самый простой вариант
Redirect 301 /test-1/ http://site.ru/test-2/
Более подробный
RewriteCond %{REQUEST_URI} ^/test/$ RewriteRule ^.*$ http://site.ru/new-test/? [R=301,L]
Массовая замена категории
Бывает, что вы переименовали категорию, а за ней закреплены тысячи урлов. Чтобы не состарится во время написания тысяч одинаковых перенаправлений юзаем:
RewriteRule ^(.*)/old-category/(.*)$ $1/new-category/$2 [R=301,L]
Если у вас категория идет сразу после домена (типа site.ru/category/), то используем другой вариант:
RewriteRule old-category /(.*) / new-category /$1 [R=301,L]
2. 301 редирект с www на без www (главное зеркало – домен без www)
RewriteCond %{HTTP_HOST} ^www\.(.*)$ RewriteRule ^(.*)$ http://%1/$1 [L,R=301]
3. 301 редирект с без www на www (главное зеркало – домен с www)
RewriteCond %{HTTP_HOST} ^([^www].*)$ RewriteRule ^(.*)$ http://www.%1/$1 [L,R=301]
4. 301 редирект со страниц со слешем на без слеша (весь сайт)
RewriteCond %{REQUEST_URI} !\? RewriteCond %{REQUEST_URI} !\& RewriteCond %{REQUEST_URI} !\= RewriteCond %{REQUEST_URI} !\. RewriteCond %{REQUEST_URI} ![^\/]$ RewriteRule ^(.*)\/$ /$1 [R=301,L]
5. 301 редирект со страниц без слеша на слеш (часто в CMS системах устанавливается автоматически)
RewriteCond %{REQUEST_URI} !\? RewriteCond %{REQUEST_URI} !\& RewriteCond %{REQUEST_URI} !\= RewriteCond %{REQUEST_URI} !\. RewriteCond %{REQUEST_URI} !\/$ RewriteRule ^(.*[^\/])$ /$1/ [R=301,L]
6. Один (а не два последовательных!) 301 редирект на без www и с слешем на конце адреса страницы
RewriteCond %{REQUEST_URI} !\? RewriteCond %{REQUEST_URI} !\& RewriteCond %{REQUEST_URI} !\= RewriteCond %{REQUEST_URI} !\. RewriteCond %{REQUEST_URI} !\/$ RewriteCond %{HTTP_HOST} ^www\.(.*)$ RewriteRule ^(.*)$ http://%1/$1/ [L,R=301] RewriteCond %{REQUEST_URI} !\? RewriteCond %{REQUEST_URI} !\& RewriteCond %{REQUEST_URI} !\= RewriteCond %{REQUEST_URI} !\. RewriteCond %{REQUEST_URI} ![^\/]$ RewriteCond %{HTTP_HOST} ^www\.(.*)$ RewriteRule ^(.*)$ http://%1/$1 [L,R=301] RewriteCond %{REQUEST_URI} !\? RewriteCond %{REQUEST_URI} !\& RewriteCond %{REQUEST_URI} !\= RewriteCond %{REQUEST_URI} !\. RewriteCond %{REQUEST_URI} !\/$ RewriteCond %{HTTP_HOST} ^([^www].*)$ RewriteRule ^(.*)$ http://%1/$1/ [L,R=301]
7. Один (а не два последовательных!) 301 редирект на c www и со слешем на конце адреса страницы
RewriteCond %{REQUEST_URI} !\? RewriteCond %{REQUEST_URI} !\& RewriteCond %{REQUEST_URI} !\= RewriteCond %{REQUEST_URI} !\. RewriteCond %{REQUEST_URI} !\/$ RewriteCond %{HTTP_HOST} ^www\.(.*)$ RewriteRule ^(.*)$ http://www.%1/$1/ [L,R=301] RewriteCond %{REQUEST_URI} !\? RewriteCond %{REQUEST_URI} !\& RewriteCond %{REQUEST_URI} !\= RewriteCond %{REQUEST_URI} !\. RewriteCond %{REQUEST_URI} !\/$ RewriteCond %{HTTP_HOST} ^([^www].*)$ RewriteRule ^(.*)$ http://www.%1/$1/ [L,R=301] RewriteCond %{REQUEST_URI} !\? RewriteCond %{REQUEST_URI} !\& RewriteCond %{REQUEST_URI} !\= RewriteCond %{REQUEST_URI} !\. RewriteCond %{REQUEST_URI} ![^\/]$ RewriteCond %{HTTP_HOST} ^([^www].*)$ RewriteRule ^(.*)$ http://www.%1/$1 [L,R=301]
8. Один (а не два последовательных!) 301 редирект на c www и без слеша на конце адреса страницы
RewriteCond %{REQUEST_URI} ^\/$ RewriteCond %{HTTP_HOST} ^([^www].*)$ RewriteRule ^(.*)$ http://www.%1/$1 [L,R=301] RewriteCond %{REQUEST_URI} !\? RewriteCond %{REQUEST_URI} !\& RewriteCond %{REQUEST_URI} !\= RewriteCond %{REQUEST_URI} !\. RewriteCond %{REQUEST_URI} \/$ RewriteCond %{HTTP_HOST} ^www\.(.*)$ RewriteRule ^(.*)\/$ http://www.%1/$1 [L,R=301] RewriteCond %{REQUEST_URI} !\? RewriteCond %{REQUEST_URI} !\& RewriteCond %{REQUEST_URI} !\= RewriteCond %{REQUEST_URI} !\. RewriteCond %{REQUEST_URI} !\/$ RewriteCond %{HTTP_HOST} ^([^www].*)$ RewriteRule ^(.*)$ http://www.%1/$1 [L,R=301] RewriteCond %{REQUEST_URI} !\? RewriteCond %{REQUEST_URI} !\& RewriteCond %{REQUEST_URI} !\= RewriteCond %{REQUEST_URI} !\. RewriteCond %{REQUEST_URI} \/$ RewriteCond %{HTTP_HOST} ^([^www].*)$ RewriteRule ^(.*)\/$ http://www.%1/$1 [L,R=301]
9. Один (а не два последовательных!) 301 редирект на без www и без слеша на конце адреса страницы
RewriteCond %{REQUEST_URI} ^\/$ RewriteCond %{HTTP_HOST} ^www\.(.*)$ RewriteRule ^(.*)$ http://%1/$1 [L,R=301] RewriteCond %{REQUEST_URI} !\? RewriteCond %{REQUEST_URI} !\& RewriteCond %{REQUEST_URI} !\= RewriteCond %{REQUEST_URI} !\. RewriteCond %{REQUEST_URI} \/$ RewriteCond %{HTTP_HOST} ^www\.(.*)$ RewriteRule ^(.*)\/$ http://%1/$1 [L,R=301] RewriteCond %{REQUEST_URI} !\? RewriteCond %{REQUEST_URI} !\& RewriteCond %{REQUEST_URI} !\= RewriteCond %{REQUEST_URI} !\. RewriteCond %{REQUEST_URI} !\/$ RewriteCond %{HTTP_HOST} ^www\.(.*)$ RewriteRule ^(.*)$ http://%1/$1 [L,R=301] RewriteCond %{REQUEST_URI} !\? RewriteCond %{REQUEST_URI} !\& RewriteCond %{REQUEST_URI} !\= RewriteCond %{REQUEST_URI} !\. RewriteCond %{REQUEST_URI} \/$ RewriteCond %{HTTP_HOST} ^([^www].*)$ RewriteRule ^(.*)\/$ http://%1/$1 [L,R=301]
10. 301 редирект только адреса site.ru/index.php (без GET параметров) на основное зеркало site.ru
RewriteCond %{REQUEST_URI} /index.php RewriteCond %{QUERY_STRING} ^\z RewriteRule ^(.*)$ http://site.ru/? [R=301,L]
11. 301 редирект всех адресов с index.php и GET параметрами на страницы только с GET параметрами (вырезать в url index.php)
Пример: типа site.ru/index.php?n=1 на site.ru/?n=1
RewriteCond %{REQUEST_URI} /index.php RewriteRule ^(.*)$ http://site.ru/ [R=301,L]
12. 301 редирект для index.php, index.html или index.htm (например в Joomla), массовая склейка
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.(php|html|htm)\ HTTP/ RewriteRule ^(.*)index\.(php|html|htm)$ http://site.ru/$1 [R=301,L]
13. 301 редирект url с GET параметрами (динамический URL) на статический
1 вариант (простой адрес с GET параметром)
RewriteCond %{QUERY_STRING} ^id=229 RewriteRule ^.*$ /supermodel/? [R=301,L]
2 вариант (со страницы и GET параметром)
RewriteCond %{REQUEST_URI} /test/ RewriteCond %{QUERY_STRING} ^id=229 RewriteRule ^.*$ /supermodel/? [R=301,L]
14. Все страницы одного домена на главную страницу другого домена
RewriteCond %{REQUEST_URI} (.*) RewriteRule ^(.*)$ http://site.ru/ [L,R=301]
15. Каждая страница одного домена на такой же адрес другого url
RewriteCond %{REQUEST_URI} (.*) RewriteRule ^(.*)$ http://site.ru/$1 [L,R=301]
16. Редирект с протокола http на https.
RewriteCond %{HTTPS} !=on RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
Если возникает циклический редирект, то воспользуйтесь этим вариантом:
RewriteCond %{HTTPS} off RewriteCond %{HTTP:X-Forwarded-Proto} !https RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
17. Редирект с протокола https на http.
Обратный редирект, если перестали использовать SSL сертификат.
RewriteCond %{HTTPS} =on RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1 [R=301,L]