Использование RewriteMap
Этот документ дополняет документацию по справочнику. Он описывает использование директивы RewriteMap, и предоставляет примеры каждого из различных типов RewriteMap.
Введение
Директива RewriteMap определяет внешнюю функцию, которая может быть вызвана в контексте директивы RewriteRule или RewriteCond для выполнения переписывания, которое слишком сложно или слишком специализировано для выполнения только с помощью регулярных выражений. Источником этого поиска может быть любой из типов, перечисленных в разделах ниже, и перечисленных в справочной документации RewriteMap.
Синтаксис директивы RewriteMap следующий:
RewriteMap MapName MapType:MapSource
ИмяКарты — произвольное имя, которое вы присваиваете карте и которое будете использовать в директивах позже. Аргументы передаются в карту следующим образом:
${ ИмяКарты : КлючПоиска }
${ ИмяКарты : КлючПоиска | ЗначениеПоУмолчанию }
Когда встречается такая конструкция, карта ИмяКарты консультируется, и ключ КлючПоиска ищется. Если ключ найден, конструкция функции карты заменяется на ЗначениеЗамены. Если ключ не найден, он заменяется на ЗначениеПоУмолчанию или на пустую строку, если ЗначениеПоУмолчанию не было указано.
Например, вы можете определить RewriteMap как:
RewriteMap examplemap "txt:/path/to/file/map.txt"
Вы можете использовать эту карту в директиве RewriteRule следующим образом:
RewriteRule "^/ex/(.*)" "${examplemap:$1}" Значение по умолчанию может быть указано в случае, если ничего не найдено в карте:
RewriteRule "^/ex/(.*)" "${examplemap:$1|/not_found.html}" Контекст каталога и .htaccess
Директива RewriteMap не может использоваться в разделах <Directory> или файлах .htaccess. Вы должны объявить карту в контексте сервера или виртуального хоста. После создания карты вы можете использовать её в ваших директивах RewriteRule и RewriteCond в этих областях. Вы просто не можете её объявлять в этих областях.
Следующие разделы описывают различные типы MapType, которые могут быть использованы, и приводят примеры каждого из них.
int: Внутренняя функция
Когда используется MapType int, MapSource — это одна из доступных внутренних функций RewriteMap. Авторы модулей могут предоставлять дополнительные внутренние функции, регистрируя их с помощью API ap_register_rewrite_mapfunc. Функции, которые предоставляются по умолчанию:
-
toupper:
Преобразует ключ в верхний регистр. -
tolower:
Преобразует ключ в нижний регистр. -
escape:
Преобразует специальные символы в ключе в шестнадцатеричные кодировки. -
unescape:
Преобразует шестнадцатеричные кодировки в ключе обратно в специальные символы.
Чтобы использовать одну из этих функций, создайте RewriteMap со ссылкой на функцию int, а затем используйте её в вашей директиве RewriteRule:
Перенаправить URI на версию с маленькими буквами
RewriteMap lc int:tolower
RewriteRule "(.*)" "${lc:$1}" [R] Обратите внимание, что пример, представленный здесь, предназначен только для иллюстрации и не является рекомендацией. Если вы хотите сделать URL-адреса регистронезависимыми, используйте mod_speling вместо этого.
txt: Карты простого текста
Когда используется MapType txt, MapSource — это путь к файлу сопоставления простого текста, содержащий одну пару ключ/значение, разделенных пробелом, на строку. Допускается наличие комментариев в строке, начинающихся с символа '#'.
Валидный файл карты переписывания текста будет иметь следующий синтаксис:
# Comment line MatchingKey SubstValue MatchingKey SubstValue # comment
При вызове RewriteMap аргумент ищется в первом аргументе строки, и если он найден, возвращается значение подстановки.
Например, мы можем использовать файл карты для перевода названий продуктов в идентификаторы продуктов для более запоминающихся URL-адресов, используя следующий рецепт:
Конфигурация продукта для ID
RewriteMap product2id "txt:/etc/apache2/productmap.txt"
RewriteRule "^/product/(.*)" "/prods.php?id=${product2id:$1|NOTFOUND}" [PT] Мы предполагаем здесь, что скрипт prods.php знает, что делать, если он получил аргумент id=NOTFOUND, когда продукт не найден в карте поиска.
Файл /etc/apache2/productmap.txt затем содержит следующее:
Карта продукта для ID
## ## productmap.txt - Product to ID map file ## television 993 stereo 198 fishingrod 043 basketball 418 telephone 328
Таким образом, при запросе http://example.com/product/television, применяется RewriteRule, и запрос внутренне отображается на /prods.php?id=993.
Примечание: файлы .htaccess
Приведенный пример предназначен для использования в контексте сервера или виртуального хоста. Если вы планируете использовать его в файле.htaccess, вам нужно удалить начашй слеш из шаблона переписывания, чтобы он соответствовал любому значению: RewriteRule "^product/(.*)" "/prods.php?id=${product2id:$1|NOTFOUND}" [PT] Кеширование поисков
Найденные ключи кэшируются httpd до тех пор, пока не изменится время модификации mtime файла карты или не перезапустится сервер httpd. Это обеспечивает лучшую производительность для карт, которые вызываются многими запросами.
rnd: Случайный текст
Когда используется MapType rnd, MapSource — это путь к файлу сопоставления простого текста, каждая строка которого содержит ключ и одно или несколько значений, разделенных |. Одно из этих значений будет выбрано случайным образом, если ключ будет сопоставлен.
Например, вы можете использовать следующий файл карты и директивы для обеспечения случайного балансирования нагрузки между несколькими серверами back-end через обратный прокси. Изображения отправляются на один из серверов в пуле 'static', а всё остальное — на один из серверов в пуле 'dynamic'.
Файл карты переписывания
## ## map.txt -- rewriting map ## static www1|www2|www3|www4 dynamic www5|www6
Директивы конфигурации
RewriteMap servers "rnd:/path/to/file/map.txt"
RewriteRule "^/(.*\.(png|gif|jpg))" "http://${servers:static}/$1" [NC,P,L]
RewriteRule "^/(.*)" "http://${servers:dynamic}/$1" [P,L] Итак, когда запрашивается изображение и совпадает первое из этих правил, RewriteMap ищет строку static в файле карты, что возвращает один из указанных хостов случайным образом, который затем используется в целевом адресе RewriteRule.
Если вы хотите, чтобы один из серверов выбирался чаще (например, если один из серверов имеет больше памяти, чем другие, и поэтому может обрабатывать больше запросов), просто перечислите его большее количество раз в файле карты.
static www1|www1|www2|www3|www4
dbm: Файл хеша DBM
Когда используется MapType dbm, MapSource — это путь к файлу базы данных DBM, содержащей пары ключ/значение, которые будут использоваться в сопоставлении. Это работает точно так же, как карта txt, но намного быстрее, потому что DBM индексирован, в то время как текстовый файл нет. Это позволяет более быстрому доступу к нужному ключу.
Вы можете дополнительно указать определённый тип dbm:
RewriteMap examplemap "dbm=sdbm:/etc/apache/mapfile.dbm"
Тип может быть sdbm, gdbm, ndbm или db. Однако рекомендуется использовать утилиту httxt2dbm, которая предоставляется с Apache HTTP Server, так как она будет использовать правильную библиотеку DBM, соответствующую той, которая использовалась при построении самого httpd.
Для создания файла dbm сначала создайте файл карты текста, как описано в разделе txt. Затем запустите httxt2dbm:
$ httxt2dbm -i mapfile.txt -o mapfile.map
Затем вы можете сослаться на получившийся файл в своей директиве RewriteMap:
RewriteMap mapname "dbm:/etc/apache/mapfile.map"
Обратите внимание, что с некоторыми типами dbm генерируется более одного файла с общим базовым именем. Например, у вас могут быть два файла с именем mapfile.map.dir и mapfile.map.pag . Это нормально, и вам нужно использовать только базовое имя mapfile.map в вашей директиве RewriteMap.
Кеширование поисков
Найденные ключи кэшируются httpd до тех пор, пока не изменится время модификации mtime файла карты или не перезапустится сервер httpd. Это обеспечивает лучшую производительность для карт, которые вызываются многими запросами.
prg: Внешняя программа переписывания
Когда используется MapType prg, MapSource — это путь к исполняемой программе, которая обеспечит поведение сопоставления. Это может быть скомпилированный двоичный файл или программа на интерпретируемом языке, таком как Perl или Python.
Эта программа запускается один раз при запуске Apache HTTP Server и затем общается с движком переписывания через STDIN и STDOUT. То есть для каждого запроса поиска функции карты она ожидает один аргумент через STDIN, и должна вернуть одну строку ответа, завершенную новой строкой, в STDOUT. Если соответствующего значения поиска нет, программа карты должна вернуть четырёхсимвольную строку "NULL", чтобы указать это.
Внешние программы переписывания не запускаются, если они определены в контексте, в котором RewriteEngine не установлено в on.
По умолчанию внешние программы переписывания выполняются как пользователь и группа, которые запустили httpd. Это можно изменить в системах Unix, передав имя пользователя и имя группы как третий аргумент в RewriteMap в формате username:groupname.
Эта функция использует мьютекс rewrite-map, который необходим для надёжной связи с программой. Механизм мьютекса и файл блокировки могут быть настроены с помощью директивы Mutex.
Вот простой пример, который заменит все дефисы на подчёркивания в запросе URI.
Конфигурация переписывания
RewriteMap d2u "prg:/www/bin/dash2under.pl" apache:apache
RewriteRule "-" "${d2u:%{REQUEST_URI}}" dash2under.pl
#!/usr/bin/perl
$| = 1; # Turn off I/O buffering
while (<STDIN>) {
s/-/_/g; # Replace dashes with underscores
print $_;
} Внимание!
- Сделайте свою программу переписывания карты максимально простой. Если программа зависает, httpd будет бесконечно ждать ответа от карты, что в свою очередь заставит httpd перестать отвечать на запросы.
- Убедитесь, что вы выключили буферизацию в своей программе. В Perl это делается на второй строке в примере скрипта:
$| = 1;Это, конечно, будет отличаться в других языках. Буферизированный ввод/вывод заставит httpd ждать вывода, и поэтому он зависнет. - Помните, что существует только одна копия программы, запущенная при запуске сервера. Все запросы должны пройти через эту единственную узкую точку. Это может привести к значительным задержкам, если многие запросы должны пройти через этот процесс или если сам скрипт очень медленный.
dbd или fastdbd: Запрос SQL
Когда используется MapType dbd или fastdbd, MapSource — это оператор SQL SELECT, который принимает один аргумент и возвращает одно значение.
mod_dbd необходимо настроить на указание правильной базы данных для выполнения этого оператора.
Существует два типа MapType. Использование MapType dbd вызывает выполнение запроса при каждом запросе карты, в то время как использование fastdbd кэширует запросы к базе данных внутри. Поэтому, хотя fastdbd более эффективен и, следовательно, быстрее, он не будет отражать изменения в базе данных до перезапуска сервера.
Если запрос возвращает более одной строки, используется случайная строка из набора результатов.
Пример
RewriteMap myquery "fastdbd:SELECT destination FROM rewrite WHERE source = %s"
Примечание
Имя запроса передается драйверу базы данных в качестве метки подготовленного оператора SQL и, следовательно, должно соответствовать любым правилам (таким как чувствительность к регистру), требуемым для вашей базы данных.
Краткое описание
Директива RewriteMap может встречаться более одного раза. Для каждого использования функции отображения используйте одну директиву RewriteMap для объявления файла переписывания отображения.
Хотя вы не можете объявить отображение в контексте каталога (файлы .htaccess или блоки <Directory> ), вы можете использовать это отображение в контексте каталога.
© 2018 The Apache Software Foundation
Licensed under the Apache License, Version 2.0.
https://httpd.apache.org/docs/2.4/en/rewrite/rewritemap.html