None
Директива RewriteRule
и есть настоящая рабочая лошадка преобразований. Эта директива может встречаться более одного раза. Каждая директива, в этом случае, определяет одно правило преобразования. Порядок определений этих правил важен, потому что этот порядок используется при обработке правил во время работы.
Шаблон это perl совместимое регулярное выражение которое применяется к текущему URL. Здесь под "текущим" подразумевается значение URL когда применяется это правило. Этот URL не обязательно совпадает с первоначально запрошенным URL, потому что любое количество правил возможно уже были применены к нему и соответственно преобразовали его.
Некоторые указания по синтаксису регулярных выражений:
Текст:
. Любой одиночный символ
[chars] Класс симвлолв: Один из символов
[^chars] Класс симвлолв: Ни один из символов
text1|text2 Альтернатива: text1 или text2
Кванторы (символы для обозначения количественных отношений):
? 0 или 1 из предшествующего текста
* 0 или N из предшествующего текста
(N > 0) + 1 или N из предшествующего текста (N > 1)
Группировка:
(text) Группировка текста
(либо установка границ альтернативы или
для создания обратных связей где N группа, которая
может быть использована в RHS директивы RewriteRule с $N)
Маркеры:
^ Маркер начала строки
$ Маркер конца строки
Экранирование:
\char экранирование конкретного символа
(к примеру для указания символов ".[]()" и т.д.)
Более подробную информацию о регулярных выражениях, смотрите в документации по регулярным выражениям Perl ("perldoc perlre"). Если вы заинтересованы в ещё более детальной информации о регулярных выражениях и их диалектах (POSIX и т.д.), смотрите следующую, специально написанную по этой теме книгу:
Mastering Regular Expressions
Jeffrey E.F. Friedl
Nutshell Handbook Series
O'Reilly & Associates, Inc. 1997
ISBN 1-56592-257-3
Кроме того, в mod_rewrite символ отрицания (NOT) ('!
') - допускаемый префикс в шаблоне. Это даёт вам возможность инвертировать действие шаблона; ну к примеру скажем: "если текущий URL не совпадает с этим шаблоном". Это может быть использовано в особых случаях, когда проще найти шаблон для несоответствия, или в качестве последнего правила, работающего по умолчанию.
$N
в строках подстановок!Подстановка в правиле преобразования это строка будет подставляться (или будет заменять) вместо оригинального URL, для которого естьсовпадение Шаблону. Кроме простого текста вы можете использовать
$N
на шаблоны в RewriteRule%N
на последний соответствующий шаблон в RewriteCond%{VARNAME}
)${mapname:key|default}
)Обратные связи это $
N (N=0..9) идентификаторы которые заменяются содержимым N-й группы подходящего Шаблона. Переменные сервера Это тоже самое что и СравниваемаяСтрока директивы RewriteCond
. Запросы к массиву пришли из директивы RewriteMap
там они и объяснены. Эти три типа переменных рассматриваются в порядке, в котором они идут в вышеприведенном списке.
Как уже было упомянуто выше, все правила преобразований применяются с использованием Подстановки (в порядке, в котором они определены в конфигурационном файле). URL полностью заменяется Подстановкой и процесс преобразования идет до тех пор, пока не останется больше никаких правил, если только он не прерван специально, с помощью флага L
- см. ниже.
Существует специальная строка подстановки вида '-
' которая означает: НЕТ подстановки! Звучит глупо? Нет, это полезно для правил преобразования которые только проверяют некоторые URL однако не производят подстановок, т.е., в связке с флагом C (цепочка) возможно иметь более чем один шаблон, применяемый перед проведением непосредственно самой подстановки.
Ещё одно замечание: Вы даже можете создавать URL, содержащие строку запроса, в строке подстановки. Просто используйте вопросительный знак внутри строки подстановки для указания того, следующее за ним содержимое должно быть преобразовано в QUERY_STRING (строку запроса). Когда вы хотите убрать существующую строку запроса, завершайте строку подстановки просто вопросительным знаком.
http://
thishost[:thisport], - mod_rewrite отрезает её автоматически. Это автоматическое усечение подразумеваемое при внешнем редиректе URL полезная и важная особенность при использовании в связке с запросами к массивам преобразований генерирующих имя хоста. Взгляните на первый пример, в разделе примеров ниже, чтобы понять это.http://thishost
из-за этой особенности. Чтобы использовать такой саморедирект, Вы должны использовать флаг R(см. ниже).В подстановке вы можете использовать, в том числе, и специальные флаги путем добавления следующей конструкции:
[
флаги]
в качестве третьего аргумента директивы 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 запрещенным)gone|G
' (делает URL "мёртвым")proxy|P
' (вызвает прокси)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
' (следуюший раунд)next
в Perl или оператору continue
из языка C. Используйте этот флаг для перезапуска процесса преобразований, т.е., безусловному переходу на начало цикла.chain|C
' (связь со следующим правилом).www
" части в конфигурационном правиле контекста каталога работающего когда вы разрешаете внешний редирект (где не должно быть ".www
"!).type|T
=MIME-тип' (принудительно установить MIME тип)mod_alias
директивы ScriptAlias
которая принудительно устанавливает для всех файлов внутри отображаемого каталога MIME тип равный "application/x-httpd-cgi
".nosubreq|NS
' (используется только в случае невнутреннего подзапроса)mod_include
пытается получить информацию о возможных файлах по-умолчанию для каталогов (index.xxx
). При подзапросах это не всегда полезно и даже иногда вызывает проблему в работе всего набора директив преобразований. Используйте этот флаг для исключения некоторых правил.Используйте следующее правило по своему усмотрению: всякий раз когда вы предваряете некоторые URL префиксом передавая их на обработку CGI-скрипту, - велик шанс что вы напоретесь на проблемы (или даже на ненужные издержки) в случае применения подзапросов. В этих случаях, используйте этот флаг.
nocase|NC
' (не учитывать регистр)qsappend|QSA
' (добавлять строку запроса)noescape|NE
' (не экранировать URI при выводе)RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE]
/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 [PT]
Alias /def /ghi
PT
, mod_rewrite
прекрасно сделаетс свою работу, т.е., он преобразует uri=/abc/...
в filename=/def/...
как должен делать полностью API-совместимый транслятор URI-имя файла. Затем настаёт очередь mod_alias
пытающегося сделать переход URI-имя файла который и не будет работать.Примечание: Вы должны использовать этот флаг если вы хотите смешивать директивы разных модулей содержащих трансляторы URL-имя файла. Типичный пример это использование модулей mod_alias
и mod_rewrite
..
skip|S
=количество' (пропустить следующее правило(а))skip=N
где N количество правил блока else. (Это не то же самое что и флаг 'chain|C'!)env|E=
VAR:VAL' (установить переменную окуржения)$N
и %N
ссылающиеся на части регулярных выражений, которые будут раскрыты соответствующим образом. Вы можете использовать этот флаг более одного раза чтобы присвоить значение более чем одной переменной. Позже, эти переменные могут быть использованы во многих ситуациях, обычно в XSSI (через <!--#echo var="VAR"-->
) или в CGI скриптах (например $ENV{'VAR'}
). Кроме того, вы можете это использовать в следующем шаблоне RewriteCond через %{ENV:VAR}
. Используйте это для удаления, но запоминания некоторой информации из URL.cookie|CO=
NAME:VAL:domain[:lifetime[:path]]' (записать cocookie)Есть одно исключение: Если строка подстановки начинается с "http://
" в этом случае префикс каталога не добавляется и происходит либо внешний редирект либо пропускание через прокси (если используется флаг P!)!
RewriteEngine On
" в этих самых файлах и, кроме того, должна быть разрешена конфигурационная директива "Options FollowSymLinks
". Если ваш администратор запретил перегрузку конфигурационной директивы FollowSymLinks
в пользовательских каталогах, в этом случае вы не сможете использовать механизм преобразований. Это ограничение нужно по соображениям безопасности.Вот все возможные комбинации подстановок с расшифровкой их значений:
В конфигурационных файлах контекста сервера (httpd.conf
)
для запроса вида "GET /somepath/pathinfo
":
Правило Подстановка
---------------------------------------------- ----------------------------------
^/somepath(.*) otherpath$1 не поддерживается, т.к. неверно
!^/somepath(.*) otherpath$1 [R] не поддерживается, т.к. неверно
!^/somepath(.*) otherpath$1 [P] не поддерживается, т.к. неверно
!---------------------------------------------- ----------------------------------
^/somepath(.*) /otherpath$1 /otherpath/pathinfo
^/somepath(.*) /otherpath$1 [R] http://thishost/otherpath/pathinfo
через внешний редирект
^/somepath(.*) /otherpath$1 [P] не поддерживается, - глупо
!---------------------------------------------- ----------------------------------
^/somepath(.*) http://thishost/otherpath$1 /otherpath/pathinfo
^/somepath(.*) http://thishost/otherpath$1 [R] http://thishost/otherpath/pathinfo
через внешний редирект
^/somepath(.*) http://thishost/otherpath$1 [P] не поддерживается, - глупо
!---------------------------------------------- ----------------------------------
^/somepath(.*) http://otherhost/otherpath$1 http://otherhost/otherpath/pathinfo
через внешний редирект
^/somepath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
через внешний редирект
(флаг [R] избыточен)
^/somepath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
через внутренний прокси
Внутри конфигурационного файла каталога, для /somepath
(т.е., файл .htaccess
в каталоге /physical/path/to/somepath
содержит RewriteBase /somepath
)
для запроса "GET /somepath/localpath/pathinfo
":
Правило Подстановка
---------------------------------------------- ----------------------------------
^localpath(.*) otherpath$1 /somepath/otherpath/pathinfo
^localpath(.*) otherpath$1 [R] http://thishost/somepath/otherpath/pathinfo через внешний редирект
^localpath(.*) otherpath$1 [P] не поддерживается, - глупо
!---------------------------------------------- ----------------------------------
^localpath(.*) /otherpath$1 /otherpath/pathinfo
^localpath(.*) /otherpath$1 [R] http://thishost/otherpath/pathinfo через внешний редирект
^localpath(.*) /otherpath$1 [P] не поддерживается, - глупо
!---------------------------------------------- ----------------------------------
^localpath(.*) http://thishost/otherpath$1 /otherpath/pathinfo
^localpath(.*) http://thishost/otherpath$1 [R] http://thishost/otherpath/pathinfo
через внешний редирект
^localpath(.*) http://thishost/otherpath$1 [P] не поддерживается, - глупо
!---------------------------------------------- ----------------------------------
^localpath(.*) http://otherhost/otherpath$1 http://otherhost/otherpath/pathinfo
через внешний редирект
^localpath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
через внешний редирект
(флаг [R] избыточен)
^localpath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
через внутренний прокси
Пример:
Мы хотим преобразовать URL вида
/
Language /~
Realname /.../
File
в
/u/
Username /.../
File .
Language
Мы берем файл, содержащий ассоциативный массив для преобразований, приведённый выше и сохраняем его под именем /path/to/file/map.txt
. Затем, нам нужно только добавить следующие строчки в конфигурационный файл сервера Apache:
RewriteLog /path/to/file/rewrite.logRewriteMap real-to-user
txt:/path/to/file/map.txtRewriteRule ^/([^/]+)/~([^/]+)/(.*)$ /u/${real-to-user:$2|nobody}/$3.$1