«Главное преимущество даваемое Вам mod_rewrite это все возможности по изменению конфигурации и гибкость присутствующие в Sendmail. Обратная сторона mod_rewrite это все возможности по изменению конфигурации и гибкость присутствующие в Sendmail.»
-- Brian Behlendorf
Apache Group
«Несмотря на тонны примеров и документацию, mod_rewrite это Вуду. Чертовски клёвый Вуду, но все-таки Вуду.»
-- Brian Moore
[email protected]
Добро пожаловать в мир mod_rewrite, швейцарский армейский нож для преобразований URL!
Этот модуль использует механизм основанный на правилах (синтаксический анализатор основанный на регулярных выражениях) для преобразований запрошенных URL на лету. Он поддерживает неограниченное количество правил и неограниченное количество связанных с правилом условий для реализации действительно гибкого и мощного механизма для URL преобразований. URL преобоазования могут зависеть от разных критериев, например переменных сервера, переменных окружения, HTTP заголовков, времени и даже запросы к внешним базам данных в разных форматах могут быть использованы для достижения действительно точного соответствия преобразованных URL вашим ожиданиям.
Этот модуль оперирует с полными URL (включая path-info) и в контексте сервера
(httpd.conf
) и в контексте каталога
(.htaccess
) и даже может генерировать части строки запроса
в качестве результата. Преобразованный результат может приводить к внутренней
обработке, внешнему перенаправлению запроса или даже к прохождению
через внутренний proxy.
Однако вся эта функциональность и гибкость имеет свой недостаток: сложность. Поэтому не ожидайте что вы поймете весь этот модуль за один день.
Этот модуль был придуман и написан в апреле 1996 и эксклюзивно подарен The Apache Group в июле 1997
Ralf S.
Engelschall
[email protected]
www.engelschall.com
Внутренние процессы в этом модуле очень сложны однако их нужно объяснить хотя бы один раз даже обычному пользователю во избежание общих ошибок и позволить вам использовать всю его функциональность.
Сначала вы должны понять что когда Apache обрабатывает какой-либо
HTTP запрос он делает это в фазах. Перехватчик для каждой из этих
фаз представлен в Apache API. Mod_rewrite использует 2 из
этих перехватчиков: перехватчик трансляции из URL в имя файла который используется
после считывания HTTP запроса однако перед тем как началась
какая-либо авторизация и перехватчик адресной привязки который начинает работать
после фаз авторизации и считывания конфигурационных файлов каталога
(.htaccess
), но перед
активизацией обработчика содержания.
Поэтому, после поступления запроса и определения Apache'ем соответствующего сервера (или виртуального сервера) механизм преобрахований начинает обработку всех директив mod_rewrite из конфигурационного файла сервера в фазе трансляции из URL в имя файла. Несколько шагов спустя когда находятся каталоги с конечными данными, the конфигурационные директивы mod_rewrite запускаются в фазе Fixup. В обоих этих ситуациях mod_rewrite переделывает URL либо на новые URL либо в имена файлов, хотя между ними нет объективных различий. При создании API не предполагалось его использование таким образом, однако что касается Apache 1.x это единственный возможный способ работы mod_rewrite. Чтобы внести больше ясности запомните 2 вещи:
.htaccess
, хотя они и обрабатываются намного позже того, как
URL транслируются в имена файлов. Так должно быть потому что
.htaccess
файлы находятся в файловой системе, и поэтому
обработка уже дошла до этой стадии. Другими
словами: Согласно фазам API в это время уже слишком поздно
делать любые манипуляции с URL. Чтобы победить эту курицу
и снести яйчко(решить эту проблему) mod_rewrite использует трюк: когда вы
манипулируете URL/именем файла в контексте каталога,
mod_rewrite сначала преобразует имя файла обратно к соответствующему ему
URL (что обычно невозможно, однако смотрите
директиву RewriteBase
ниже, где написано
как сделать подобный трюк) и затем инициирует новый внутренний подзапрос
с этим новым URL. Это перезапускает процесс обработки
API фаз. И снова mod_rewrite упорно пытается сделать этот сложный шаг полностью прозрачным для пользователя, однако здесь вам следует запомнить: в то время как манипуляции с URL контексте сервера действительно быстры и эффективны, манипуляции в контексте каталога медленны и неэффективны из-за проблемы курицы и яйца. Однако с другой стороны это единственный возможный путь работы mod_rewrite (локально ограниченный) для URL преобразований, доступный обычному пользователю.
Не забывайте 2 эти вещи!
Теперь когда в этих двух фазах API запускается mod_rewrite, он считывает конфигурационные наборы правил из своей конфигурационной структуры (которая либо создается сама при запуске сервера для контекста сервера, либо ядром Apache при обходе каталогов для контекста каталога). Затем запускается механизм манипуляций с URL с имеющимся набором правил (одно или несколько правил вместе со своими условиями). Функционирование самого механизма преобразований в точности одинаково для обоих контекстов конфигурации. Различаются только конечные результы обработки.
Порядок правил в наборе важен потому что механизм преобразований
обрабатывает их в специальном (и не очень
очевидном) порядке. Вот это правило: Механизм преобразований просматривает
весь набор правил строчка за строчкой (
RewriteRule
директивы) и
когда находится соответствие конкретному правилу производится просмотр
соответствующих этому правилу условий (RewriteCond
директивы). По историческим причинам условия находятся перед правилами, и поэтому последовательность выполнения команд немного более длинная. См.
рис. 1 для более подробной информации.
Рисунок 1:Последовательность выполнения комад при обработке набора правил
Как вы можете видеть, сначала URL проверяется на соответствие Pattern(шаблону) каждого из правил. При неудаче mod_rewrite сразу же останавливает обработку этого правила и продолжает используя следующее. Если Pattern(шаблон) совпадает, mod_rewrite ищет соответствующие этому правилу условия. Если их нет, он просто заменяет URL новой величиной полученной из строки Substitution(подстановка) и продолжает дальше обрабатывать правила. Однако если существуют условия, запускается внутренний цикл для их обработки в том порядке в котором они перечислены. Для условий эта логика другая: мы не сравниваем URL на соответствие какому-либо шаблону. Вместо этого мы сначала создаем строку TestString дополняя её переменными, обратными ссылками, запросами к карте, и т.д. и затем пытаемся проверять на соответствие с CondPattern. Если шаблон не соответствует, весь набор условий и соответствующих правил считается несоответствующим условию. Если есть соответствие шаблону, в этом случае производится обработка следующего условия до тех пор пока они будут не исчерпаны. Если все условия совпадают, процесс обработки продолжается с использованием для URL подстановки из Substitution (подстановка).
Что касается Apache 1.3.20, специальные символы в
TestString и Substitution строках могут быть
экранированы (имеется ввиду, отношение к ним как к нормальным символам без их
обычного специального значения) путем предшествующего им символа слеша ('\').
Другими словами, вы можете включать символ доллара
в строку Substitution используя
'\$
'; это не позволит mod_rewrite относиться к нему
как к обратной ссылке.
Здесь нужно запомнить одну важную вещь: Всякий раз когда вы
ипользуете круглые скобки в Pattern или в одном из
CondPattern, создаются внутренние обратные связи которые могут быть использованы со строками $N
и
%N
(см. ниже). Они полезны при создании строк Substitution и TestString.
Рисунок 2 показывает в какие места при дополнении (строк Substitution и TestString) перемещаются обратные связи.
Рисунок 2: Движение обратных ссылок в правиле.
Мы знаем что это был тяжелый курс по внутренним механизмам mod_rewrite, однако вы получите выгоду из этих знаний при чтении последующей документации о доступных директивах.
Этот модуль отслеживает две дополнительные (нестандартные)
переменные окружения CGI/SSI называемые SCRIPT_URL
и SCRIPT_URI
. Они содержат
логическое веб-отображение текущего ресурса, в то время как
стандартные переменные CGI/SSI SCRIPT_NAME
и
SCRIPT_FILENAME
содержат физическое
системное отображение.
Замечание: эти переменные содержат URI/URL в том виде, в котором они были первоначально запрошены, т.е., перед тем как были сделаные какие-либо преобразования. Это важно потому что процесс преобразования в первую очередь используется для преобразования логических URL в физические пути к конкретным файлам.
SCRIPT_NAME=/sw/lib/w3s/tree/global/u/rse/.www/index.html SCRIPT_FILENAME=/u/rse/.www/index.html SCRIPT_URL=/u/rse/ SCRIPT_URI=http://en1.engelschall.com/u/rse/
У нас также есть Руководство по преобразованиям URL, в котором приведена коллекция практических решений для проблем основанных на URL. Там вы можете найти наборы правил взятые из реальной жизни и дополнительную информацию о mod_rewrite.
Описание: | Устанавливает базовый URL для преобразований в контексте каталога |
---|---|
Синтаксис: | RewriteBase URL-path |
Значение по умолчанию: |
Смотри использование для более подробной информации.
|
Контекст: | directory.htaccess |
Разрешение: | FileInfo |
Статус: | Расширение |
Модуль: | mod_rewrite |
Директива RewriteBase
устанавливает конкретный, базовый URL для преобразований в контексте каталога. Как вы увидите ниже,
RewriteRule
может быть использовано в конфигурационных файлах каталогов (.htaccess
). Это будет работать локально,
т.е., префикс локального каталога отбрасывается на этом
этапе обработки и ваши правила преобразований работают только в
оставшейся части. В конце он автоматически добавляется обратно к пути.
Настройка по-умолчанию; RewriteBase
physical-directory-path
Когда, для какого-нибудь нового URL происходит подстановка(преобразование),
этот модуль должен заново вовлечь этот URL в обработку.
Для того чтобы иметь возможность сделать это, нужно знать какие у него префикс или база URL. По-умолчанию этот префикс равен самому пути.
Однако на большинстве сайтов URL'ы НЕ прямо
соответствуют физическим путям, поэтому это
допущение обычно окажется неверным! В этом случае вы должны
использовать директиву RewriteBase
для указания правильного
префикса URL.
RewriteBase
в каждом из .htaccess
файлов где вы хотите использовать директивы
RewriteRule
.
Например, предположим следующий конфигурационный файл каталога:
# # /abc/def/.htaccess -- per-dir config file for directory /abc/def # Помните: /abc/def это физический путь /xyz, т.е., у сервера есть # директива 'Alias /xyz /abc/def' к примеру # RewriteEngine On # даем серверу знать что мы работаем через /xyz а не # через префикс физического пути /abc/def RewriteBase /xyz # теперь правила преобразований RewriteRule ^oldstuff\.html$ newstuff.html
В примере выше, запрос к
/xyz/oldstuff.html
корректно преобразуется в
физический файл /abc/def/newstuff.html
.
Следующий список дает подробную информацию об этапах внутренней обработки:
Запрос: /xyz/oldstuff.html Внутренняя обработака: /xyz/oldstuff.html -> /abc/def/oldstuff.html (per-server Alias) /abc/def/oldstuff.html -> /abc/def/newstuff.html (per-dir RewriteRule) /abc/def/newstuff.html -> /xyz/newstuff.html (per-dir RewriteBase) /xyz/newstuff.html -> /abc/def/newstuff.html (per-server Alias) Результат: /abc/def/newstuff.html
Это кажется очень сложным однако это корректная внутренняя работа Apache, из-за того что преобразования в контексте каталога происходят слишком поздно в этом процессе. Поэтому, когда это происходит (преобразование) запрос должен быть обратно возвращен ядру Apache! ОДНАКО: В то время как это кажется серъёзным накладным расходом, в действительности это не так, потому что этот возврат происходит целиком внутри сервера Apache и та же самая процедура используется многими другими операциями внутри Apache. Поэтому, вы можете быть уверены что дизайн и и реализация правильные.
Описание: | Определяет условие при котором происходит преобразование |
---|---|
Синтаксис: | RewriteCond TestString CondPattern |
Значение по умолчанию: |
None
|
Контекст: | server configvirtual host directory.htaccess |
Разрешение: | FileInfo |
Статус: | Расширение |
Модуль: | mod_rewrite |
Директива RewriteCond
определяет
условия для какого-либо правила. Перед директивой
RewriteRule
располагаются одна или
несколько директив RewriteCond
. Следующее за ними
правило преобразования используется только тогда, когда URI соответствует условиям этой директивы и также условиям этих дополительных директив.
TestString строка которая может содержать следующие дополнительные конструкции в дополении к простому тексту:
$N
RewriteRule
(единственной,
следующей сразу за текущим набором директив RewriteCond
).
%N
RewriteCond
в текущем наборе условий.
${mapname:key|default}
%{
NAME_OF_VARIABLE
}
|
Эти переменные полностью
соответствуют названным похожим образом MIME-заголовкам HTTP
, Си переменным сервера Apache или
полям struct tm
систем Unix.
Большинство из них документрованны в других местах руководства или в
спецификации CGI. Те, что являются для
mod_rewrite специальными включают:
IS_SUBREQ
API_VERSION
THE_REQUEST
GET
/index.html HTTP/1.1
»). Она не включает
какие-либо дополнительные заголовки отправляемые браузером.REQUEST_URI
REQUEST_FILENAME
Специальные примечания:
filename
внутренней структуры
request_rec
сервера Apache.
Первое имя это просто широко известное имя переменной CGI
в то время как второе это постоянная копия
REQUEST_URI (содержащая значение поля
uri
структуры request_rec
).%{ENV:переменная}
где переменная может быть
любой переменной окружения. Это ищется во внутренних структурах
Apache и (если там нет) с помощью вызова
getenv()
из процесса Apache сервера.%{HTTP:заголовок}
где заголовок может быть
любым именем HTTP MIME-заголовка. Это ищется в HTTP
запросе. Пример: %{HTTP:Proxy-Connection}
значение
HTTP заголовка
«Proxy-Connection:
».%{LA-U:переменная}
опережающих запросов которые производятся
внутренним (основанном на URL) подзапросом для определения конечного значения
переменной. Используйте это когда вы хотите использовать
переменную для преобразований, которая реально определяется позднее, в
какой-либо фазе API, и таким образом недоступна на данном этапе.
Для примера когда вы хотите преобразовать соответственно переменной
REMOTE_USER
из контекста
сервера (файл httpd.conf
) вы должны
использовать %{LA-U:REMOTE_USER}
потому что эта переменная
устанавливается в фазах авторизации которые идут
после фазы трансляции URL в которой и работает mod_rewrite.
С другой стороны, по причине реализации работы mod_rewrite в
контексте каталога (файл .htaccess
) через Fixup фазу
API и из-за того, фазы авторизации идут
до этой фазы, вы просто можете там использовать
%{REMOTE_USER}
.%{LA-F:переменная}
который создает внутренний
(основанный на имени файла) подзапрос для определения конечного значения
переменной. В основном это то же самое что и формат
LA-U приведенный выше.CondPattern это шаблон условия, т.е., какое-либо регулярное выражение применяемое к текущему экземпляру TestString, т.е., TestString просматривается на поиск соответствия CondPattern.
Помните: CondPattern это perl совместимое регулярное выражение с некоторыми дополнениями:
!
' (восклицательный знак) для указания
несоответствия шаблону.""
(два знака дюйма идущих подряд) это
сравнивает TestString с пустой строкой.Дополнительно вы можете устанавливать специальные флаги для CondPattern добавляя
[
flags
]
третьим аргументом в директиву RewriteCond
.
Flags список следующих флагов разделенных запятыми:
nocase|NC
'
(регистронезависимо)ornext|OR
'
(либо следующее условие)RewriteCond %{REMOTE_HOST} ^host1.* [OR] RewriteCond %{REMOTE_HOST} ^host2.* [OR] RewriteCond %{REMOTE_HOST} ^host3.* RewriteRule ...some special stuff for any of these hosts...Без этого флага вы должны были бы написать это условие/правило три раза.
Пример:
Для выдачи главной страницы какого-либо сайта
согласно «User-Agent:
» заголовку запроса, вы можете
использовать следующие директивы:
RewriteCond %{HTTP_USER_AGENT} ^Mozilla.* RewriteRule ^/$ /homepage.max.html [L] RewriteCond %{HTTP_USER_AGENT} ^Lynx.* RewriteRule ^/$ /homepage.min.html [L] RewriteRule ^/$ /homepage.std.html [L]
Интерпретация: Если у вас Netscape Navigator (который идентифицируется как 'Mozilla'), вы выдаете максимально навороченную страницу, с фреймами, и т.д. Если у вас Lynx (текстовый браузер), вы выдаете наименее навороченную страницу, без рисунков, таблиц и т.д. Если любой другой браузер, выдаете стандартную страницу.
Описание: | Включает или выключает работу механизма преобразования |
---|---|
Синтаксис: | RewriteEngine on|off |
Значение по умолчанию: |
RewriteEngine off
|
Контекст: | server configvirtual host directory.htaccess |
Разрешение: | FileInfo |
Статус: | Расширение |
Модуль: | mod_rewrite |
Директива RewriteEngine
включает или
выключает работу механизма преобразований. Если она установлена в положение
off
этот модуль совсем не работает.
Он даже не обновляет переменные окружения SCRIPT_URx
.
Используйте эту директиву для выключения этого модуля вместо
простого закомментирования директив
RewriteRule
!
Отметьте, что по-умолчанию, настройки преобразований не
наследуются. Это означает что вы должны иметь
RewriteEngine on
директиву для каждого виртуального хоста
в котором вы хотите использовать этот модуль.
Описание: | Устанавливает имя файла используемого для RewriteMap синхронизации |
---|---|
Синтаксис: | RewriteLock file-path |
Значение по умолчанию: |
None
|
Контекст: | server config |
Статус: | Расширение |
Модуль: | mod_rewrite |
Эта директива устанавливает имя файла файла синхронизации
который нужен mod_rewrite для связи с
RewriteMap
программами. Сделайте этот файл локальным (размещенным не на
NFS-смонтированном ресурсе) когда вы хотите использовать программу для
создания ассоциативного массива преобразований. Это не является обязательным для других типов таких массивов.
Описание: | Устанавливает имя файла используемое для ведения журнала механизма преобразования |
---|---|
Синтаксис: | RewriteLog file-path |
Контекст: | server configvirtual host |
Статус: | Расширение |
Модуль: | mod_rewrite |
Директива RewriteLog
устанавливает имя
файла а котором сервер ведет журнал любых происходящих действий
по преобразованиям URL. Если это имя не начинается со слэша
('/
') в этом случае путь считается от
Server Root. В конфигурационном файле сервера эта директива должна встерчаться только один раз.
/dev/null
, потому что
хотя механизм преобразований и не производит вывод в файл журнала в этом случае, внутри он все ещё ведет журнализацию.
Это замедлит сервер без каких-либо преимуществ
для администратора! Для отключения ведения журнала либо
удалите либо закомментируйте директиву RewriteLog
либо используйте RewriteLogLevel 0
!
RewriteLog "/usr/local/var/apache/logs/rewrite.log"
Описание: | Устанавливает уровень детализации при журнализации действий механизма преобразований |
---|---|
Синтаксис: | RewriteLogLevel Level |
Значение по умолчанию: |
RewriteLogLevel 0
|
Контекст: | server configvirtual host |
Статус: | Расширение |
Модуль: | mod_rewrite |
Директива RewriteLogLevel
устанавливает
уровень детализации журнала механизма преобразований. По-умолчанию уровень 0
означающий что журнализация не ведется, в то время как 9 или более означает
что записываются практически все действия.
Для отключения журнализации действий механизма преобразований просто установите уровень на 0. Это отключает ведение журнала для всех действий по преобразованиям.
RewriteLogLevel 3
Описание: | Определяет функцию создания ассоциативного массива для поиска по ключу |
---|---|
Синтаксис: | RewriteMap MapName MapType:MapSource |
Значение по умолчанию: |
нет
|
Контекст: | server configvirtual host |
Статус: | Расширение |
Модуль: | mod_rewrite |
Совместимость: | Выбор разных типов dbm доступен в Apache 2.0.41 и более поздних версиях |
Директива RewriteMap
ассоциативный массив преобразований, который может быть использован в правилах преобразований и использующий соответствующие функции для вставки/извлечения элементов, для поиска по ключу соответствующих значений. Источник этого поиска может иметь различный тип.
MapName это имя массива которое будет использоваться для поиска соответствующего значения из массива в правиле преобразования через один из следующих конструкторов:
${
MapName :
LookupKey }
${
MapName :
LookupKey |
DefaultValue
}
Когда встречается подобная конструкция, происходит обращение к массиву MapName и поиск значения сопоставленного ключу LookupKey. Если найдено искомое значение ключа, происходит извлечение значения SubstValue с помощью соответствующей функции. Если ключ не найден тогда происходит подстановка DefaultValue или пустой строки если не указана DefaultValue.
Могут быть использованы следующие комбинации типа функции — MapType для вставки/извлечения элементов массива и MapSource — самого ассоциативного массива:
txt
, MapSource: Путь к существующему файлу в файловой системе Unix Это стандартная опция для создания ассоциативного массива где MapSource это простой текстовый ASCII файл содержащий либо пустый строчки, строчки комментариев (начинающиеся с символа '#') либо пары подобные следующим — одна в строчке:
MatchingKey SubstValue
## ## map.txt -- массив преобразований ## Ralf.S.Engelschall rse # Bastard Operator From Hell Mr.Joe.Average joe # Mr. AverageRewriteMap real-to-user txt:/path/to/file/map.txt
rnd
, MapSource: Путь к существующему файлу в файловой системе Unix Этот вариант идентичен варианту с простым текстом приведённом выше но со специальной особенностью пост-обработки: После нахождения какую-либо величину производится её анализ на предмет нахождения символов «|
» которые имеют значение логического «или». Другими словами они означают набор альтернативных вариантов
и выбор возвращаемой величины из них производится произвольно. Хотя это кажется безумием и абсалютно бесполезным,
это в действительности используется для балансировки нагрузки в ситуациях с обратным прокси где происходит поиск имен серверов. Например:
## ## map.txt -- массив преобразований ## static www1|www2|www3|www4 dynamic www5|www6RewriteMap servers rnd:/path/to/file/map.txt
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
int
, MapSource: внутренняя функция Apache Здесь, источник — это какая-либо внутренняя функция Apache. В настоящее время вы не можете создавать свои собственные функции, однако уже существуют следующие функции:
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 $_; }
Однако будьте очень осторожны:
stdout
! Это вызовет бесконечное зацикливание! Отсюда «$|=1
» в вышеприведенном примере...
RewriteLock
для определения файла блокировок который mod_rewrite может использовать для синхронизации связи с этой программой. По-умолчанию такая синхронизация не производится.Директива RewriteMap
может встречаться более одного раза. Для каждого массива используйте одну RewriteMap
директиву для объявления файла с массивом преобразований. В то время как вы не можете определять массив в контексте каталога, его использование в этом контексте конечно же возможно.
mtime
файла с массивом или пока не произойдет рестарт сервера. Таким образом, вы можете использовать ассоциативные массивы в правилах которые используются для каждого
запроса. Это не проблема, потому что внешний поиск происходит только один раз!
Описание: | Устанавливает кое-какие специальные опции для механизма преобразований |
---|---|
Синтаксис: | RewriteOptions Options |
Значение по умолчанию: |
None
|
Контекст: | server configvirtual host directory.htaccess |
Разрешение: | FileInfo |
Статус: | Расширение |
Модуль: | mod_rewrite |
Директива RewriteOptions
устанавливает некоторые
специальные опции для текущей конфигурации в контексте сервера
или каталога. Строки Option могут иметь
следующий вид:
inherit
'.htaccess
родительских каталогов наследуются.Описание: | Определяет правила для механизма преобразований |
---|---|
Синтаксис: | RewriteRule Шаблон Подстановка |
Значение по умолчанию: |
None
|
Контекст: | server configvirtual host directory.htaccess |
Разрешение: | FileInfo |
Статус: | Расширение |
Модуль: | mod_rewrite |
Совместимость: | Флаг cookie доступен в Apache 2.0.40 и более поздних. |
Директива 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-й группы подходящего
Шаблона. Переменные сервера Это тоже самое
что и TestString директивы 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 round)next
command or
the continue
command from the C language. Use
this flag to restart the rewriting process, i.e.,
to immediately go to the top of the loop.chain|C
'
(chained with next rule).www
'' part inside a per-directory rule set
when you let an external redirect happen (where the
``.www
'' part should not to occur!).type|T
=MIME-type'
(force MIME type)mod_alias
directive
ScriptAlias
which internally forces all files
inside the mapped directory to have a MIME type of
``application/x-httpd-cgi
''.nosubreq|NS
' (used only if
no internal
sub-request)mod_include
tries to find out
information about possible directory default files
(index.xxx
). On sub-requests it is not
always useful and even sometimes causes a failure to if
the complete set of rules are applied. Use this flag to
exclude some rules.Use the following rule for your decision: whenever you prefix some URLs with CGI-scripts to force them to be processed by the CGI-script, the chance is high that you will run into problems (or even overhead) on sub-requests. In these cases, use this flag.
nocase|NC
'
(no case)qsappend|QSA
'
(query string
append)noescape|NE
'
(no URI escaping of
output)/foo/zed
' into a safe
request for '/bar?arg=P1=zed
'. passthrough|PT
'
(pass through to next
handler)uri
field of the internal
request_rec
structure to the value of the
filename
field. This flag is just a hack to
be able to post-process the output of
RewriteRule
directives by
Alias
, ScriptAlias
,
Redirect
, etc. directives from
other URI-to-filename translators. A trivial example to
show the semantics: If you want to rewrite
/abc
to /def
via the rewriting
engine of mod_rewrite
and then
/def
to /ghi
with
mod_alias
: RewriteRule ^/abc(.*) /def$1 [PT]PT
flag then
mod_rewrite
will do its job fine,
i.e., it rewrites uri=/abc/...
to
filename=/def/...
as a full API-compliant
URI-to-filename translator should do. Then
mod_alias
comes and tries to do a
URI-to-filename transition which will not work. Note: You have to use this flag if you want to
intermix directives of different modules which contain
URL-to-filename translators. The typical example
is the use of mod_alias
and
mod_rewrite
..
skip|S
=num'
(skip next rule(s))skip=N
where N is the number of rules in the
else-clause. (This is not the same as the
'chain|C' flag!)env|E=
VAR:VAL'
(set environment variable)$N
and
%N
which will be expanded. You can use this
flag more than once to set more than one variable. The
variables can be later dereferenced in many situations, but
usually from within XSSI (via <!--#echo
var="VAR"-->
) or CGI (e.g.
$ENV{'VAR'}
). Additionally you can dereference
it in a following RewriteCond pattern via
%{ENV:VAR}
. Use this to strip but remember
information from URLs.cookie|CO=
NAME:VAL:domain[:lifetime[:path]]'
(set cocookie)There is one exception: If a substitution string
starts with ``http://
'' then the directory
prefix will not be added and an
external redirect or proxy throughput (if flag
P is used!) is forced!
RewriteEngine On
'' in these files
and ``Options
FollowSymLinks
'' must be enabled. If your
administrator has disabled override of
FollowSymLinks
for a user's directory, then
you cannot use the rewriting engine. This restriction is
needed for security reasons.
Here are all possible substitution combinations and their meanings:
Inside per-server configuration
(httpd.conf
)
for request ``GET
/somepath/pathinfo
'':
Given Rule Resulting Substitution ---------------------------------------------- ---------------------------------- ^/somepath(.*) otherpath$1 not supported, because invalid! ^/somepath(.*) otherpath$1 [R] not supported, because invalid! ^/somepath(.*) otherpath$1 [P] not supported, because invalid! ---------------------------------------------- ---------------------------------- ^/somepath(.*) /otherpath$1 /otherpath/pathinfo ^/somepath(.*) /otherpath$1 [R] http://thishost/otherpath/pathinfo via external redirection ^/somepath(.*) /otherpath$1 [P] not supported, because silly! ---------------------------------------------- ---------------------------------- ^/somepath(.*) http://thishost/otherpath$1 /otherpath/pathinfo ^/somepath(.*) http://thishost/otherpath$1 [R] http://thishost/otherpath/pathinfo via external redirection ^/somepath(.*) http://thishost/otherpath$1 [P] not supported, because silly! ---------------------------------------------- ---------------------------------- ^/somepath(.*) http://otherhost/otherpath$1 http://otherhost/otherpath/pathinfo via external redirection ^/somepath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo via external redirection (the [R] flag is redundant) ^/somepath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo via internal proxy
Inside per-directory configuration for
/somepath
(i.e., file .htaccess
in dir
/physical/path/to/somepath
containing
RewriteBase /somepath
)
for request ``GET
/somepath/localpath/pathinfo
'':
Given Rule Resulting Substitution ---------------------------------------------- ---------------------------------- ^localpath(.*) otherpath$1 /somepath/otherpath/pathinfo ^localpath(.*) otherpath$1 [R] http://thishost/somepath/otherpath/pathinfo via external redirection ^localpath(.*) otherpath$1 [P] not supported, because silly! ---------------------------------------------- ---------------------------------- ^localpath(.*) /otherpath$1 /otherpath/pathinfo ^localpath(.*) /otherpath$1 [R] http://thishost/otherpath/pathinfo via external redirection ^localpath(.*) /otherpath$1 [P] not supported, because silly! ---------------------------------------------- ---------------------------------- ^localpath(.*) http://thishost/otherpath$1 /otherpath/pathinfo ^localpath(.*) http://thishost/otherpath$1 [R] http://thishost/otherpath/pathinfo via external redirection ^localpath(.*) http://thishost/otherpath$1 [P] not supported, because silly! ---------------------------------------------- ---------------------------------- ^localpath(.*) http://otherhost/otherpath$1 http://otherhost/otherpath/pathinfo via external redirection ^localpath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo via external redirection (the [R] flag is redundant) ^localpath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo via internal proxy
Пример:
Мы хотим преобразовать URL вида
/
Language /~
Realname /.../
File
в
/u/
Username /.../
File .
Language
Мы берем файл содержащий ассоциативный массив для преобразований from above and save it under
/path/to/file/map.txt
. Then we only have to
add the following lines to the Apache server configuration
file:
RewriteLog /path/to/file/rewrite.log RewriteMap real-to-user txt:/path/to/file/map.txt RewriteRule ^/([^/]+)/~([^/]+)/(.*)$ /u/${real-to-user:$2|nobody}/$3.$1Источник статьи