RewriteMap
нет
Директива RewriteMap
ассоциативный массив преобразований, который может
быть использован в правилах преобразований и использующий соответствующие функции для вставки/извлечения
элементов, для поиска по ключу соответствующих значений. Источник этого поиска может иметь различный тип.
MapName это имя массива которое будет использоваться для поиска соответствующего значения из массива в правиле преобразования через один из следующих конструкторов:
${
MapName :
LookupKey }
${
MapName :
LookupKey |
DefaultValue
}
Когда встречается подобная конструкция, происходит обращение к массиву MapName и поиск значения сопоставленного ключу LookupKey. Если найдено искомое значение ключа, происходит извлечение значения SubstValue с помощью соответствующей функции. Если ключ не найден тогда происходит подстановка DefaultValue или пустой строки если не указана DefaultValue.
Могут быть использованы следующие комбинации типа функции - MapType для вставки/извлечения элементов массива и MapSource - самого ассоциативного массива:
- Простой текст
MapType:txt
, MapSource: Путь к существующему файлу в файловой системе UnixЭто стандартная опция для создания ассоциативного массива где MapSource это простой текстовый ASCII файл содержащий либо пустый строчки, строчки комментариев (начинающиеся с символа '#') либо пары подобные следующим - одна в строчке:
MatchingKey SubstValue
Пример
## ## map.txt -- массив преобразований ## Ralf.S.Engelschall rse # Bastard Operator From Hell Mr.Joe.Average joe # Mr. Average
RewriteMap real-to-user txt:/path/to/file/map.txt
- Произвольный простой текст
MapType:rnd
, MapSource: Путь к существующему файлу в файловой системе UnixЭтот вариант идентичен варианту с простым текстом приведённом выше но со специальной особенностью пост-обработки: После нахождения какую-либо величину производится её анализ на предмет нахождения символов "
|
" которые имеют значение логического "или". Другими словами они означают набор альтернативных вариантов и выбор возвращаемой величины из них производится произвольно. Хотя это кажется безумием и абсолютно бесполезным, это в действительности используется для балансировки нагрузки в ситуациях с обратным прокси где происходит поиск имен серверов. Например:## ## map.txt -- массив преобразований ## static www1|www2|www3|www4 dynamic www5|www6
RewriteMap servers rnd:/path/to/file/map.txt
- Хэш файл
MapType:dbm[=type]
, MapSource: Путь к существующему файлу в файловой системе UnixЗдесь, источник - это двоичный файл DBM формата содержащий то же самое содержимое что и простой текстовый файл, однако в специальном виде, оптимизированном для действительно быстрого поиска. Этот тип может быть sdbm, gdbm, ndbm, или db в зависимости от настроек при компиляции. Если тип опущен, выбирается тип установленный по-умолчанию при компиляции. Вы можете создавать такой файл любой утилитой DBM или следующим Perl скриптом. Убедитесь что он настроен для создания требуемого типа DBM файла. Этот пример создает файл NDBM.
#!/path/to/bin/perl ## ## txt2dbm -- convert txt map to dbm format ## use NDBM_File; use Fcntl; ($txtmap, $dbmmap) = @ARGV; open(TXT, "<$txtmap") or die "Couldn't open $txtmap!\n"; tie (%DB, 'NDBM_File', $dbmmap,O_RDWR|O_TRUNC|O_CREAT, 0644) or die "Couldn't create $dbmmap!\n"; while (<TXT>) { next if (/^\s*#/ or /^\s*$/); $DB{$1} = $2 if (/^\s*(\S+)\s+(\S+)/); } untie %DB; close(TXT);
$ txt2dbm map.txt map.db
- Внутренняя функция
MapType:int
, MapSource: внутренняя функция ApacheЗдесь, источник - это какая-либо внутренняя функция Apache. В настоящее время вы не можете создавать свои собственные функции, однако уже существуют следующие функции:
- toupper:
Преобразует ключ поиска в верхний регистр. - tolower:
Преобразует ключ поиска в нижний регистр. - escape:
Транслирует специальные символы в ключе поиска в их числовые коды. - unescape:
Транслирует числовые коды в ключе поиска обратно в специальные символы.
- toupper:
- Внешняя программа преобразования
MapType:prg
, MapSource: Путь к существующему файлу в файловой системе UnixЗдесь, источник - это программа, а не файл с ассоциативным массивом. Для её создания вы можете использовать любой выбранный язык, однако результат должен быть исполняемым файлом (т.е., либо объектным кодом либо скриптом с магической первой строчкой '
#!/path/to/interpreter
').Эта программа запускается один раз при запуске сервера Apache и затем взаимодействует с механизмом преобразований через файловые обработчики
stdin
(поток ввода) иstdout
(поток вывода). Для каждого поиска в массиве, соответствующий ключ для поиска, будет получаться в виде строки, подаваемой наstdin
и оканчивающейся символом перевода строки. Затем эта программа должна вернуть значение найденной величины вstdout
в виде строки оканчивающейся символом перевода строки либо строкой из четырёх символов "NULL
" если поиск неудачен (т.е., для соответствующего значения ключа не найдено никакого значения). Тривиальная программа реализующая массив 1:1 (т.е., ключ == значение) может выглядеть так:#!/usr/bin/perl $| = 1; while (<STDIN>) { # ...put here any transformations or lookups... print $_; }
Однако будьте очень осторожны:
- "Keep it simple, stupid" (KISS) - делай это проще, дурачок, потому что если эта программа зависнет - это повесит сервер Apache когда встретится правило использующее этот массив (создаваемый внешней программой).
- Для избежания распространенной ошибки: никогда не делайте буферизованный ввод/вывод для
stdout
! Это вызовет бесконечное зацикливание! Отсюда "$|=1
" в вышеприведенном примере... - Используйте директиву
RewriteLock
для определения файла блокировок который mod_rewrite может использовать для синхронизации связи с этой программой. По-умолчанию такая синхронизация не производится.
Директива RewriteMap
может встречаться более одного раза. Для каждого массива
используйте одну RewriteMap
директиву для объявления файла с массивом
преобразований. В то время как вы не можете определять массив в контексте каталога, его
использование в этом контексте конечно же возможно.
Замечание
Для простого текстового и DBM файлов ключи поиска кэшируются ядром до тех пор пока не изменится типmtime
файла с массивом или пока не произойдет рестарт сервера. Таким образом, вы
можете использовать ассоциативные массивы в правилах которые используются для каждого запроса.
Это не проблема, потому что внешний поиск происходит только один раз!