Динамические вставки в кэшированные страницы
После того, как я сделал себе защиту от хотлинкинга, я не мог воспользоваться ни плагином кэширования для WP, ни встроенной фичей кэширования в nginx, так как ссылки на видяшки у меня генерировались уникальные для каждого захода на страницу, уникальные для каждого посетителя. Так что я был поставлен перед нелегким выбором — либо кэширование (и в 3-5 раз меньшая нагрузка), либо защита от хотлинкинга (и отсутствие гигантского траффика из-за воришек). Но, погуглив, я узнал, что можно сделать и то и то одновременно!
Проблема на самом деле довольно серьезная, и я попросту не знал что делать. Единственным выходом я видел использование Ajax, когда уже после отдачи статической страницы ява-скрипт отдельным запросом лез бы на сервер и генерил ссылку на видео. Но я сильно этому противился, т.к. во1, очень плохо знал Ajax, во2, это дополнительный запрос и дополнительное время ожидания, в3, яваскрипт не у всех включен, в4, есть девайсы (мобильные), где он по-просту не работает, или работает хреново.
Однако, гуглив сабж, я нашел тему, когда можно вставлять динамические блоки в страницы, которые были закешированы, перед тем, как они будут переданы клиенту. Все на самом деле очень просто — мы будем пользоваться давно забытой технологией SSI. Напомню — это такой квази-язык, поставляется как модуль к веб-серверу. Главным применением его в давние времена было собирать из разных частей (обычно это шапка и подвал) страничку перед отдачей ее клиенту. Для примера, если в hml-код страницы вставить вот такую конструкцию:
<!--# include virtual="/header.php" -->
то веб-сервер сначала лезет по этому адресу, выполняет код, а потом результат этого кода вставляет вместо этой конструкции. Однако, его применение забылось вскоре после быстрого распространения полноценных серверных языков perl, php, asp.
— И какого хуя ты мне это все рассказываешь? — спросит нетерпеливый читатель. Дада, я бы тоже сразу не догадался. Хотя, чего тут сложного — посмотрите на конструкцию выше, с точки зрения php это простой комментарий. Для веб-сервера — нет, но сервер задействует эту конструкцию только при отсылки всей страницы клиенту. Получается, это тот самый инструмент, который мы искали: при кэшировании преобразования не происходит, и в кэш попадает страница с таким вот «комментарием». НО! при взятии из кэша и перед отправкой происходит выполнение php-кода, который таким образом инклудится. И происходит это каждый раз, когда дергается страница из кэша. Красота!
Но тут я столкнулся с еще одной проблемой — дело в том, что попытки инклудить такую конструкцию:
<!--# include virtual="/get-secret-url.php?url_to_video=http://myhost.org/video/cool_video.avi" -->
ни к чему не привели. Ну то есть, файл инклудится, но параметр, заданый через GET — не проходит. И не только в виде урла, но и простой вида /header.php?a=1. Пришлось мне немного извратиться и генерить имя php-файла уникальным для каждой видяшки. Получилось вот так:
<!--# include virtual="/get-secret-url-myhost.org-video-cool_video.avi.php" -->
А в конфиге nginx делать rewrite, что-то вроде такого:
rewrite /get-secret-url-([a-z\.]*)-([a-z]*)-([_a-z0-9\.]*)\.php /get-secret-url.php?host=$1&folder=$2&filename=$3
А соответственно в файле get-secret-url.php будет тот самый php код (ну, примерно), который я уже описал в посте про защиту.
В итоге мы получили динамическую ссылку в статических кэшированных страницах. Кстати, таким же образом можно делать любые динамические вставки, которым необходима какая-то серверная обработка (счетчики, ротаторы баннеров, «случайные» выборки из БД и пр.)
PS: не забудьте включить поддержку ssi в nginx, прописав ssi=on; в директиве server.