Я использую SSI в Nginx и мне это нравится. Но есть проблема.
Дано
Есть страница, которую почти полностью можно кешировать на час. В нее нужно встраивать блок со случайной картинкой. Заголовок страницы () зависит от картинки.
Решение
Backend выдает отдельно страницу /page/ и случайный блок /random/. Случайный блок хитро кешируется на 30 секунд, а страница — просто, но на час. Далее Nginx.SSI вставляет блок в страницу.
Проблема
Я не знаю, как вставить title в страницу. Текст заголовка — это название случайной картинки. Она вставляется внутри body, поэтому переменные, которым я присваиваю значение внутри /random/, еще не инициализированы в момент вывода title.
Я придумал, как обойти проблему:
random.html
<!--# set var="title" value="бла-бла" -->
<img src="bla-bla.jpg" />
page.html
<!-- HTML-комментарий
<!--# include virtual="/random/?$args" wait="yes" -->
-->
<head>
<title><!--# echo var="title" encoding="none" default="без заголовка" --></title>
</head>
<body>
....
<!--# include virtual="/random/?$args" -->
</body>
Видно, что блок /random/ включается в страницу два раза. Это плохо, поскольку на самом деле блок содержит не только картинку но и приличное количество верстки, которая зависит от картинки. Весь этот код дублируется на странице
и ест мой трафик.
Очевидно, можно было бы сохранить код, возвращаемый первым вызовом в переменной, а затем вставить в страницу значение этой переменной.
page.html
<!-- HTML-комментарий
<!--# include virtual="/random/?$args" wait="yes" set="random_html" -->
-->
<head>
<title><!--# echo var="title" encoding="none" default="без заголовка" --></title>
</head>
<body>
....
<!--# echo var="random_html" encoding="none" default="" -->
</body>
Но в этом случае (если использовать параметр set у директивы include) значения переменных, установленных внутри /random/ не передаются в /page/ — title оказывается пустым. У меня есть подозрение, что это досадный баг. Напишу об этом разработчику. Правда, не знаю, куда именно…
Можно положить верстку в отдельную переменную, но будут проблемы с экранированием всяких там $ и чего-то еще.
Еще пробовал сделать замену при помощи sub_filter, но она, видимо, выполняется до SSI и тамошних переменных не видит.
Внимание, вопрос
Как сделать все это за один include?