пятница, 9 ноября 2012 г.

Перенаправление запросов с помощью .htaccess

Большинство сайтов на Друпал используют Apache в качестве веб-сервера. Apache позволяет отдельно задавать правила обработки для каждой директории сайта с помощью файлов .htaccess. Настройки распространяются на все вложенные подпапки, если в них нет своего файла .htaccess со своим списком настроек.

Недавно передо мной встала следующая задача:
"Нужен скрипт, содержимое которого будет время от времени меняться и, к тому же, зависеть от входных GET параметров. Т.е. сайт при обращении по адресу "scripts/custom.js?city=70" запускает menu_callback, который генерирует файл скрипта в зависимости от ID города, пришедшего в GET-параметре и некоторых глобальных настроек в админке, и отдает его пользователю."



Все бы хорошо, но это действие весьма и весьма нагружает сайт, т.к. для создания и отдачи файла поднимался Drupal. К тому же этот скрипт требовался на множестве сторонних сервисов, что обеспечивало плотный поток запросов от анонимных пользователей на определенный URL (закешировать который было нельзя).

Для решения этой проблемы была создана папка для временного сохранения сгенерированных скриптов "sites/default/files/scripts/". Как это работало:

  • При запросе на "scripts/custom.js?city=70" генерируется скрипт для города с ID = 70
  • Скрипт отдается пользователю и ложится в файл "sites/default/files/scripts/custom_70.js". Имена файлов строятся по шаблону "custom_" + ID города + ".js"
  • Если администратор правит глобальные настройки для этих скриптов, то при сабмите формы настроек - папка со скриптами очищается.

Осталось "сообщить" серверу, чтобы при запросе на определенный адрес, он сначала посмотрел наличие готового файла. Если файл есть - отдать его пользователю, если нет - поднимать Drupal, передавая ему URL. А Drupal уже сгенерирует и отдаст нужный файл, положив копию в готовые скрипты.

Итак, нам потребуется установленный mod_rewrite (модуль для сервера) и следующие 2 блока в .htaccess:


RewriteCond %{REQUEST_URI} ^/scripts/custom\.js$ [NC]
RewriteCond %{QUERY_STRING} ^city=([0-9]+)$ [NC]
RewriteCond %{DOCUMENT_ROOT}/sites/default/files/banners/custom_%1.js -s
RewriteRule (.*) sites/default/files/scripts/custom_%1.js [L]

RewriteCond %{REQUEST_URI} ^/scripts/custom\.js$ [NC]
RewriteCond %{DOCUMENT_ROOT}/sites/default/files/scripts/custom.js -s
RewriteRule (.*) sites/default/files/scripts/custom.js [L]


Их нужно разместить в разделе "<If Module mod_rewrite.c>" непосредственно перед обработкой "чистых ссылок":
# Rewrite URLs of the form 'x' to the form 'index.php?q=x'.

Правила для перенаправления запросов оформляются в виде блоков из списка условий (RewriteCond), под которым пишется действие (RewriteRule), выполняемое если все предыдущие условия выполнены. Разберем что же происходит в данных блоках:

Первый блок:


RewriteCond %{REQUEST_URI} ^/scripts/custom\.js$ [NC]
RewriteCond %{QUERY_STRING} ^city=([0-9]+)$ [NC]
RewriteCond %{DOCUMENT_ROOT}/sites/default/files/banners/custom_%1.js -s
RewriteRule (.*) sites/default/files/scripts/custom_%1.js [L]


Если запрашиваемый адрес равен "/scripts/custom.js"
Если строка GET-параметров равна "city=(числовое значение)"
Если существует файл "{корневая директория сайта}/sites/default/files/banner/custom_(числовое значение, которое проверялось на ([0-9+]) в предыдущем условии).js"
То перенаправить запрос на этот файл, отдав его пользователю.

Второй блок:


RewriteCond %{REQUEST_URI} ^/scripts/custom\.js$ [NC]
RewriteCond %{DOCUMENT_ROOT}/sites/default/files/scripts/custom.js -s
RewriteRule (.*) sites/default/files/scripts/custom.js [L]



Если запрашиваемый адрес = "/scripts/custom.js"
Если существует файл "{корневая директория сайта}/sites/default/files/banner/custom.js"
То перенаправить запрос на этот файл, отдав его пользователю.

- - -

Второй блок нужен на случай, когда город в запросе не указан. Он запустится если первый блок не сработал (например, нет параметра с городом). Если не сработает и второй блок - запрос перехватится блоком "чистых ссылок" и передастся Drupal на обработку.

Таким образом, пользователям будут отдаваться временные копии файлов (если они есть), которые уникальны для каждого GET-идентификатора города и будут удалены и, по мере надобности, перегенерированы при сохранении формы настроек администратором.
Это обеспечивает гибкую работу с меняющимися скриптами с высокой скоростью и низкой нагрузкой, при этом корректно реагируя на входные параметры.

Комментариев нет:

Отправить комментарий