Продвинутые приемы работы с mod_rewrite
Этот документ дополняет mod_rewrite справочную документацию. В нем описано несколько продвинутых приемов работы с mod_rewrite.
Шардирование на основе URL между несколькими бэкендами
- Описание:
-
Распространенный способ распределения нагрузки на серверы или объема хранилища называется «шардированием». При использовании этого метода фронтенд-сервер использует URL, чтобы последовательно распределять пользователей или объекты по отдельным бэкенд-серверам.
- Решение:
-
Соответствие между пользователями и целевыми серверами хранится во внешних файлах карт. Они выглядят так:
user1 physical_host_of_user1 user2 physical_host_of_user2 # ... and so on
Поместим это в файл
map.users-to-hosts. Нужно сопоставить:/u/user1/anypathс
http://physical_host_of_user1/u/user/anypathТаким образом, путь каждого URL не обязан быть доступен на каждом физическом бэкенд-хосте. Следующий набор правил выполняет это преобразование с помощью файлов карт. Предполагается, что server0 — сервер по умолчанию, который будет использоваться, если для пользователя нет записи в карте:
RewriteEngine on RewriteMap users-to-hosts "txt:/path/to/map.users-to-hosts" RewriteRule "^/u/([^/]+)/?(.*)" "http://${users-to-hosts:$1|server0}/u/$1/$2"
Дополнительные сведения о синтаксисе этой директивы см. в документации RewriteMap и в руководстве по RewriteMap.
Генерация содержимого на лету
- Описание:
-
Нужно динамически генерировать содержимое, но после генерации сохранять его в статическом виде. Это правило проверяет, существует ли статический файл, и, если его нет, создает его. При необходимости статические файлы можно периодически удалять (например, с помощью cron), и они будут создаваться по запросу.
- Решение:
- Это выполняется следующим набором правил:
# This example is valid in per-directory context only RewriteCond "%{REQUEST_URI}" "!-U" RewriteRule "^(.+)\.html$" "/regenerate_page.cgi" [PT,L]Оператор
-Uопределяет, является ли проверяемая строка (в данном случаеREQUEST_URI) допустимым URL. Для этого выполняется подзапрос. Если этот подзапрос завершается неудачей — то есть запрошенный ресурс не существует, — правило вызывает программу CGI/regenerate_page.cgi, которая создает запрошенный ресурс и сохраняет его в каталоге документов. Поэтому при следующем запросе можно будет выдать статическую копию.Таким образом, документы, которые обновляются редко, можно выдавать в статическом виде. Если документы нужно обновить, их можно удалить из каталога документов, и при следующем запросе они будут созданы заново.
Балансировка нагрузки
- Описание:
-
Нужно случайным образом распределять нагрузку между несколькими серверами с помощью mod_rewrite.
- Решение:
-
Для этого воспользуемся
RewriteMapи списком серверов.RewriteEngine on RewriteMap lb "rnd:/path/to/serverlist.txt" RewriteRule "^/(.*)" "http://${lb:servers}/$1" [P,L]В
serverlist.txtбудет содержаться список серверов:## serverlist.txt servers one.example.com|two.example.com|three.example.com
Если вы хотите, чтобы на один из серверов приходилась большая доля нагрузки, добавьте его в список несколько раз.
- Обсуждение
-
В Apache есть модуль балансировки нагрузки —
mod_proxy_balancer, — который гораздо гибче и функциональнее всего, что можно создать с помощью mod_rewrite.
Структурированные каталоги пользователей
- Описание:
-
На некоторых сайтах с тысячами пользователей используется структурированная организация домашних каталогов: т. е. каждый домашний каталог находится в подкаталоге, имя которого начинается (например) с первой буквы имени пользователя. Так,
/~larry/anypath— это/home/l/larry/public_html/anypath, а/~waldo/anypath— это/home/w/waldo/public_html/anypath. - Решение:
-
Используем следующий набор правил, чтобы преобразовать URL с тильдой в описанную выше структуру.
RewriteEngine on RewriteRule "^/~(([a-z])[a-z0-9]+)(.*)" "/home/$2/$1/public_html$3"
Перенаправление на якоря
- Описание:
-
По умолчанию перенаправление на HTML-якорь не работает, поскольку mod_rewrite экранирует символ
#, заменяя его на%23. Это, в свою очередь, нарушает работу перенаправления. - Решение:
-
Используйте флаг
[NE]в директивеRewriteRule. NE означает No Escape (не экранировать). - Обсуждение:
- Этот прием работает и с другими специальными символами, которые mod_rewrite по умолчанию кодирует в URL.
Переписывание URL в зависимости от времени
- Описание:
-
Нужно с помощью mod_rewrite выдавать разное содержимое в зависимости от времени суток.
- Решение:
-
Для условий переписывания доступно множество переменных с именами
TIME_xxx. В сочетании со специальными шаблонами лексикографического сравнения<STRING,>STRINGи=STRINGможно выполнять перенаправления в зависимости от времени:RewriteEngine on RewriteCond "%{TIME_HOUR}%{TIME_MIN}" ">0700" RewriteCond "%{TIME_HOUR}%{TIME_MIN}" "<1900" RewriteRule "^foo\.html$" "foo.day.html" [L] RewriteRule "^foo\.html$" "foo.night.html"Это позволяет выдавать содержимое
foo.day.htmlпо URLfoo.htmlс07:01-18:59, а в остальное время — содержимоеfoo.night.html.mod_cache, промежуточные прокси и браузеры могут кэшировать ответы, из-за чего любая из страниц может отображаться вне заданного временного интервала. Для управления этим эффектом можно использоватьmod_expires. Разумеется, гораздо лучше просто выдавать содержимое динамически и изменять его в зависимости от времени суток.
Установка переменных окружения на основе частей URL
- Описание:
-
Иногда при выполнении переписывания URL нужно сохранять некое состояние. Например, может потребоваться отметить, что переписывание уже выполнено, чтобы впоследствии проверить, поступил ли запрос в результате этого переписывания. Один из способов сделать это — установить переменную окружения.
- Решение:
-
Используйте флаг [E], чтобы установить переменную окружения.
RewriteEngine on RewriteRule "^/horse/(.*)" "/pony/$1" [E=rewritten:1]
Позже в наборе правил можно проверить эту переменную окружения с помощью RewriteCond:
RewriteCond "%{ENV:rewritten}" "=1"Обратите внимание, что переменные окружения не сохраняются при внешнем перенаправлении. Можно использовать флаг [CO], чтобы установить cookie. При переписывании в контексте каталога и в файлах htaccess, когда окончательная подстановка обрабатывается как внутреннее перенаправление, к переменным окружения из предыдущего этапа переписывания добавляется префикс "REDIRECT_".
© 2018 The Apache Software Foundation
Licensed under the Apache License, Version 2.0.
https://httpd.apache.org/docs/2.4/en/rewrite/advanced.html