Внутренние процессы Внутренние процессы в этом модуле очень сложны, однако, их нужно объяснить хотя бы раз, и даже обычному пользователю, во избежание распространённых ошибок и раскрытия всей его функциональности.
Фазы API
Для начала, нужно просто понять, что обработку какого-либо HTTP запроса, сервер Apache делает в фазах. Перехватчик этих фаз обеспечивается Apache API. Mod_rewrite использует 2 из этих перехватчиков: транслятор из URL в имя файла используемый после считывания HTTP запроса, но до начала какой-либо авторизации и перехватчик адресной привязки начинающий работать после фаз авторизации и считывания конфигурационных файлов каталога (.htaccess), но до активизации обработчика содержания.
Поэтому, после поступления запроса и определения Apacheем соответствующего сервера (или виртуального сервера) механизм преобразований начинает обработку всех директив mod_rewrite из конфигурационного файла сервера в фазе трансляции из URL в имя файла. Несколько шагов спустя, когда находятся каталоги с конечными данными, конфигурационные директивы mod_rewrite запускаются в фазе адресной привязки. В обоих этих ситуациях mod_rewrite преобразует URL, либо в новые URL, либо в имена файлов, хотя между ними нет объективных различий. При создании API, не предполагалось его использование таким образом, однако что касается Apache 1.x это единственный возможный способ работы mod_rewrite. Чтобы внести больше ясности запомните 2 вещи:
Хотя mod_rewrite и преобразует URL в URL, URL в имена файлов и даже имена файлов в имена файлов, в настоящий момент API предоставляет только перехватчик для преобразования URL в имя файла. Во 2-м Apache будут добавлены 2 отсутствующих перехватчика для того, чтобы сделать этот процесс более логичным. Однако это никак не влияет на пользователя, — просто этот факт надо запомнить: Apache в перехватчике URL имя файла делает больше нежели чем это подразумевается в API. Бесподобный mod_rewrite проделывает URL преобразования и в контексте каталога, т.е. в файлах .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 сравнивается с Шаблон для каждого из правил. При неудаче mod_rewrite сразу же останавливает обработку этого правила и продолжает работу, используя следующее правило. Если Шаблон совпадает, mod_rewrite ищет соответствующие этому правилу условия. Если их нет, он просто заменяет URL новой величиной полученной из строки Подстановка и продолжает дальше обрабатывать правила. Однако если существуют условия, запускается внутренний цикл для их обработки в том порядке в котором они перечислены. Для условий эта логика другая: мы не сравниваем URL на соответствие какому-либо шаблону. Вместо этого мы сначала создаем строку СравниваемаяСтрока дополняя её переменными, обратными ссылками, запросами в базы данных, и т.д. и затем пытаемся проверять на соответствие с Условие. Если шаблон не соответствует, весь набор условий и соответствующих правил считается несоответствующим условию. Если есть соответствие шаблону, в этом случае производится обработка следующего условия до тех пор пока они будут не исчерпаны. Если все условия совпадают, процесс обработки продолжается с использованием для URL подстановки данных из поля Подстановка.
Экранирование специальных символов
Что касается Apache 1.3.20, специальные символы в СравниваемаяСтрока и Подстановка строках могут быть экранированы (имеется ввиду, отношение к ним как к нормальным символам без их обычного специального значения) путем предшествующего им символа слеша (). Другими словами, вы можете включать символ доллара в строку Подстановка используя $; это не позволит mod_rewrite относиться к нему как к обратной ссылке.
Наличие обратных связей в регулярных выражениях
Здесь нужно запомнить одну важную вещь: Всякий раз, когда вы используете круглые скобки в Шаблон или в одном из Условие, создаются внутренние обратные связи которые могут быть использованы со строками $N и %N (см. ниже). Они полезны при создании строк Подстановка и СравниваемаяСтрока. Рисунок 2 показывает в какие места при дополнении (строк Подстановка и СравниваемаяСтрока) перемещаются обратные связи.
Рисунок 2: Движение обратных связей в правиле.
Итак, — это был неподъёмный курс по внутренним механизмам mod_rewrite, но он вам сильно поможет при дальнейшем чтении документации по данному модулю.
Переменные окружения
Этот модуль отслеживает две дополнительные (нестандартные) переменные окружения CGI/SSI называемые SCRIPT_URL и SCRIPT_URI. Они содержат логическое представление текущего ресурса, т.е. то, каким вы видите это в адресной строке браузера, в то время как стандартные переменные CGI/SSI SCRIPT_NAME и SCRIPT_FILENAME содержат физическое или системное представление.
Замечание: эти переменные содержат URI/URL в том виде, в котором они были первоначально запрошены, т.е., перед тем как были сделаные какие-либо преобразования. Это важно, ибо процесс преобразования в первую очередь используется для преобразования логических URL в физические пути к конкретным файлам.
Имеется и Руководство по преобразованиям URL, содержащее коллекцию практических решений проблем URL преобразований. Там можно найти наборы правил взятые из реальной жизни и дополнительную информацию о mod_rewrite.
RewriteBase Директива Описание: Устанавливает базовый URL для преобразований в контексте каталога Синтаксис: RewriteBase URL-path Значение по умолчанию: Смотри использование для более подробной информации. Контекст: directory.htaccess Разрешение: FileInfo Статус: Расширение Модуль: mod_rewrite
Директива RewriteBase устанавливает конкретный, базовый URL для преобразований в контексте каталога. Как вы увидите ниже, RewriteRule может быть использовано в конфигурационных файлах каталогов (.htaccess). Это будет работать локально, т.е., префикс локального каталога отбрасывается на этом этапе обработки и ваши правила преобразований работают только в оставшейся части. В конце он автоматически добавляется обратно к пути. Настройка по-умолчанию; RewriteBase physical-directory-path
Когда, для какого-нибудь нового URL происходит подстановка(преобразование), этот модуль должен заново вовлечь этот URL в обработку. Для того чтобы иметь возможность сделать это, нужно знать какие у него префикс или база URL. По-умолчанию этот префикс равен самому пути. Однако на большинстве сайтов URLы НЕ прямо соответствуют физическим путям, поэтому это допущение обычно окажется неверным! В этом случае вы должны использовать директиву RewriteBase для указания правильного префикса URL.
Если URL вашего сервера не соответствуют физическим путям к файлам, вы должны использовать RewriteBase в каждом из .htaccess файлов где вы хотите использовать директивы RewriteRule. Например, предположим следующий конфигурационный файл каталога:
# # /abc/def/.htaccess -- конфигурационный файл каталога /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.
Для любителей поковыряться в Apache Следующий список дает подробную информацию об этапах внутренней работы:
Результат: /abc/def/newstuff.html Это кажется очень сложным однако это корректная внутренняя работа Apache, из-за того что преобразования в контексте каталога происходят слишком поздно в этом процессе. Поэтому, когда это происходит (преобразование), запрос должен быть возвращен обратно ядру Apache! НО: В то время как это кажется серъёзным накладным расходом, в действительности это не так, потому что этот возврат происходит целиком внутри сервера Apache и та же самая процедура используется многими другими операциями внутри Apache. Поэтому, вы можете быть уверены что дизайн и реализация правильные.
RewriteCond Директива Описание: Определяет условие при котором происходит преобразование Синтаксис: RewriteCond СравниваемаяСтрокаУсловие Значение по умолчанию: None Контекст: server configvirtual hostdirectory.htaccess Разрешение: FileInfo Статус: Расширение Модуль: mod_rewrite
Директива RewriteCond определяет условия для какого-либо правила. Перед директивой RewriteRule располагаются одна или несколько директив RewriteCond. Следующее за ними правило преобразования используется только тогда, когда URI соответствует условиям этой директивы и также условиям этих дополительных директив.
СравниваемаяСтрока строка которая может содержать следующие дополнительные конструкции в дополении к простому тексту:
RewriteRule обратные_связи: Это обратные связи вида $N
(0 <= N <= 9) предоставляющие доступ к сгруппированным частям (в круглых скобках!) шаблона из соответствующей директивы RewriteRule (единственной, следующей сразу за текущим набором директив RewriteCond). RewriteCond обратные_связи: Это обратные связи вида %N
(1 <= N <= 9) предоставляющие доступ к сгруппированным частям (в круглых скобках!) шаблона из соответствующей директивы RewriteCond в текущем наборе условий. RewriteMap расширения: Это расширения вида ${mapname:keydefault}
Смотрите документацию по RewriteMap для получения более подробной информации. Переменные сервера: Это переменные вида %{NAME_OF_VARIABLE}
где NAME_OF_VARIABLE может быть строкой взятой из следующего списка: HTTP заголовки: соединение & запрос: HTTP_USER_AGENT HTTP_REFERER HTTP_COOKIE HTTP_FORWARDED HTTP_HOST HTTP_PROXY_CONNECTION HTTP_ACCEPT REMOTE_ADDR REMOTE_HOST REMOTE_USER REMOTE_IDENT REQUEST_METHOD SCRIPT_FILENAME PATH_INFO QUERY_STRING AUTH_TYPE