Пункт 35. Введение в регулярные выражения и mod_rewrite
Этот документ дополняет mod_rewrite
справочную документацию. Он описывает основные понятия, необходимые для использования
mod_rewrite
. Другие документы содержат более подробные сведения, но этот документ должен помочь новичку освоиться.
Введение
Модуль Apache mod_rewrite
— очень мощный и сложный модуль, который позволяет выполнять манипуляции с URL. С его помощью вы можете выполнять почти все типы перезаписи URL-адресов, которые вам могут понадобиться. Это, однако, несколько сложно и может пугать новичка. Существует также тенденция рассматривать правила перезаписи как магические заклинания, используя их, не понимая, что они делают.
В этом документе делается попытка дать достаточную предысторию, чтобы все последующее было понятно, а не копировалось вслепую.
Помните, что многие распространенные задачи по обработке URL-адресов не требуют полной мощности и сложности mod_rewrite
. Для простых задач см. mod_alias
и документацию по сопоставлению URL-адресов с файловой системой.
Наконец, прежде чем продолжить, обязательно настройте
mod_rewrite
уровень журнала 's на один из уровней трассировки с помощью директивы LogLevel
. Хотя это может дать огромное количество информации, оно незаменимо при отладке проблем с mod_rewrite
конфигурацией, поскольку точно скажет вам, как обрабатывается каждое правило.
Обычные выражения
mod_rewrite использует словарь регулярных выражений, совместимых с Perl. В этом документе мы не пытаемся предоставить подробную ссылку на регулярные выражения. Для этого мы рекомендуем справочные страницы PCRE, справочную страницу регулярных выражений Perl и Mastering Regular Expressions Джеффри Фридла.
В этом документе мы пытаемся предоставить достаточный словарь регулярных выражений, чтобы вы могли начать работу, не перегружая вас, в надежде, что
RewriteRule
это будут научные формулы, а не магические заклинания.
Словарь регулярных выражений
Ниже приведены минимальные строительные блоки, которые вам понадобятся для написания регулярных выражений и RewriteRule
s. Они, конечно, не представляют собой полный словарь регулярных выражений, но они являются хорошей отправной точкой и должны помочь вам прочитать основные регулярные выражения, а также написать свои собственные.
Характер |
Значение |
Пример |
. | Соответствует любому одиночному символу | c.t будет соответствовать cat ,
cot , cut , и т.д. |
+ | Повторяет предыдущее совпадение один или несколько раз | a+ спички a , aa ,
aaa , и т.д. |
* | Повторяет предыдущее совпадение ноль или более раз. | a* соответствует всем тем же самым вещам
a+ соответствует, но также будет соответствовать пустой строке. |
? | Делает совпадение необязательным. |
colou?r будет соответствовать color и colour . |
^ | Вызывается якорем, соответствует началу строки | ^a соответствует строке, которая начинается с
a |
$ | Другой якорь соответствует концу строки. | a$ соответствует строке, которая заканчивается на
a . |
( ) | Группирует несколько символов в один блок и фиксирует совпадение для использования в обратной ссылке. | (ab)+
соответствует ababab - то есть + относится к группе. Подробнее о обратных ссылках см. ниже. |
[ ] | Класс символов - соответствует одному из символов | c[uoa]t совпадения cut или
. cot _ cat |
[^ ] | Класс отрицательных символов — соответствует любому символу, не указанному | c[^/]t совпадает cat или c=t нет c/t |
В mod_rewrite
символе !
можно использовать перед регулярным выражением, чтобы отрицать его. То есть строка будет считаться совпавшей только в том случае, если она не соответствует остальной части выражения.
Доступность обратных ссылок регулярных выражений
Здесь следует помнить одну важную вещь: всякий раз, когда вы используете круглые скобки в Pattern или в одном из
CondPattern , внутри создаются обратные ссылки, которые можно использовать со строками $N
и
%N
(см. ниже). Они доступны для создания параметра
Substitution RewriteRule
или параметра TestString для
RewriteCond
.
Захваты в RewriteRule
шаблонах (вопреки здравому смыслу) доступны для всех предшествующих
RewriteCond
директив, потому что RewriteRule
выражение вычисляется перед отдельными условиями.
На рис. 1 показано, в какие местоположения передаются обратные ссылки для расширения, а также иллюстрируется поток сопоставления RewriteRule и RewriteCond. В следующих главах мы рассмотрим, как использовать эти обратные ссылки, так что не волнуйтесь, если сначала это покажется вам немного чуждым.
Рис. 1. Обратные ссылки проходят через правило.
В этом примере запрос /test/1234
будет преобразован в /admin.foo?page=test&id=1234&host=admin.example.com
.
Основы правила перезаписи
A RewriteRule
состоит из трех аргументов, разделенных пробелами. Аргументы
- Pattern : на какие входящие URL-адреса должно распространяться правило;
- Подстановка : куда следует отправлять совпадающие запросы;
- [флаги] : параметры, влияющие на перезаписанный запрос.
Шаблон является регулярным выражением . Первоначально (для первого правила перезаписи или до тех пор, пока не произойдет подстановка) сопоставляется с URL-путем входящего запроса (частью после имени хоста, но до любого вопросительного знака, указывающего на начало строки запроса) или, в каждом каталоге контексте, по пути запроса относительно каталога, для которого определено правило. Как только замена произошла, следующие правила сопоставляются с замененным значением.
Рисунок 2: Синтаксис директивы RewriteRule.
Замена может сама по себе быть одной из трех вещей:
- Полный путь файловой системы к ресурсу
-
RewriteRule "^/games" "/usr/local/games/web"
Это сопоставляет запрос с произвольным местом в вашей файловой системе, как и Alias
директива.
- Веб-путь к ресурсу
-
Правило перезаписи "^/foo$" "/bar"
Если DocumentRoot
установлено значение /usr/local/apache2/htdocs
, то эта директива будет отображать запросы http://example.com/foo
на путь /usr/local/apache2/htdocs/bar
.
- Абсолютный URL
-
RewriteRule "^/product/view$" "http://site2.example.com/seeproduct.html" [R]
Это говорит клиенту сделать новый запрос для указанного URL-адреса.
Подстановка также может содержать обратные ссылки на части входящего URL-пути, соответствующие шаблону . Рассмотрим следующее:
RewriteRule "^/product/(.*)/view$" "/var/web/productdb/$1"
Переменная $1
будет заменена любым текстом, совпавшим с выражением внутри круглых скобок в Pattern . Например, запрос http://example.com/product/r14df/view
будет сопоставлен с путем /var/web/productdb/r14df
.
Если в скобках несколько выражений, они доступны по порядку в переменных $1
, $2
, $3
, и так далее.
Переписать флаги
Поведение RewriteRule
можно изменить, установив один или несколько флагов в конец правила. Например, поведение сопоставления правила можно сделать нечувствительным к регистру, установив флаг [NC]
:
RewriteRule "^puppy.html" "smalldog.html" [NC]
Дополнительные сведения о доступных флагах, их значениях и примерах см. в документе Rewrite Flags.
Условия перезаписи
Одну или несколько RewriteCond
директив можно использовать для ограничения типов запросов, на которые будут распространяться следующие действия RewriteRule
. Первый аргумент — это переменная, описывающая характеристику запроса, второй аргумент — это регулярное выражение, которое должно соответствовать переменной, а третий необязательный аргумент — это список флагов, которые изменяют способ оценки совпадения.
Рисунок 3: Синтаксис директивы RewriteCond
Например, чтобы отправить все запросы из определенного диапазона IP-адресов на другой сервер, вы можете использовать:
RewriteCond "%{REMOTE_ADDR}" "^10\.2\."
RewriteRule "(.*)" "http://intranet.example.com$1"
RewriteCond
Если указано более одного , все они должны совпадать для RewriteRule
применения. Например, чтобы отклонить запросы, содержащие слово «hack» в строке запроса, если они также не содержат cookie, содержащий слово «go», вы можете использовать:
RewriteCond "%{QUERY_STRING}" "взломать"
RewriteCond "%{HTTP_COOKIE}" "!go"
Правило перезаписи "." "-" [Ф]
Обратите внимание, что восклицательный знак указывает на отрицательное совпадение, поэтому правило применяется только в том случае, если файл cookie не содержит «go».
Совпадения в регулярных выражениях, содержащихся в RewriteCond
s, могут использоваться как часть подстановки при использовании RewriteRule
переменных %1
, %2
и т. д. Например, это направит запрос в другой каталог в зависимости от имени хоста, используемого для доступа к сайту:
RewriteCond "%{HTTP_HOST}" "(.*)"
Правило перезаписи "^/(.*)" "/sites/%1/$1"
Если бы запрос был для http://example.com/foo/bar
, то %1
содержал бы example.com
и $1
содержал бы foo/bar
.
Переписать карты
Директива RewriteMap
предоставляет способ вызвать внешнюю функцию, которая, так сказать, сделает вашу переписку за вас. Это обсуждается более подробно в дополнительной документации RewriteMap.
файлы .htaccess
Перезапись обычно настраивается в настройках конфигурации основного сервера (вне любого <Directory>
раздела) или внутри <VirtualHost>
контейнеров. Это самый простой и рекомендуемый способ перезаписи. Однако можно выполнить перезапись внутри <Directory>
разделов или .htaccess
файлов за счет некоторой дополнительной сложности. Этот метод называется перезаписью для каждого каталога.
Основное отличие перезаписей для каждого сервера заключается в том, что префикс пути к каталогу, содержащему файл, .htaccess
удаляется перед сопоставлением в файле RewriteRule
. Кроме того, RewriteBase
следует использовать для обеспечения правильного сопоставления запроса.