Работа с серверными включениями (SSI)

Дата обновления перевода 2022-01-19

Работа с серверными включениями (SSI)

SSI могут быть использованы для контроля HTTP-кеширования фрагментов ответа, схоже с ESI (Edge Side Includes). Наиболее важным отличием является то, что SSI напрямую известны большинству веб-серверов вроде Apache, Nginx и др.

Инструкции SSI проводятся с помощью HTML-комментариев:

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html>
    <body>
        <!-- ... some content -->

        <!-- Встроить содержание другой страницы здесь -->
        <!--#include virtual="http://..." -->

        <!-- ... больше содержания -->
    </body>
</html>

Существуют некоторые другие доступные директивы, но Symfony работает только с #include virtual.

Caution

Будьте осторожны с SSI, ваш веб-сайт может стать жертвой внедрений. Пожалуйста, для начала, прочтите это статью OWASP!

Когда веб-сервер читает SSI-директиву, он запрашивает заданный URI или дает напрямую из своего кеша. Он повторяет этот процесс до тех пор, пока SSI-директивы для обработки не заканчиваются. Затем, он слияет все ответы в один, и отправляет их клиенту.

Использование SSI в Symfony

Для начала, чтобы использовать SSI, не забудьте включить его в конфигурации вашего приложения:

  • YAML
  • XML
  • PHP
1
2
3
# config/packages/framework.yaml
framework:
    ssi: { enabled: true }

Предположим, что у вас есть страница с личным содержанием, вроде страницы Профиля, и вы хотите кешировать статический блок содержания GDPR. С SSI, вы можете добавить окончание срока действия этому блоку, чтобы страница оставалась частной:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// src/Controller/ProfileController.php
namespace App\Controller;

// ...
class ProfileController extends AbstractController
{
    public function index(): Response
    {
        // по умолчанию, ответы являются частными
        return $this->render('profile/index.html.twig');
    }

    public function gdpr(): Response
    {
        $response = $this->render('profile/gdpr.html.twig');

        // устанавливает их как публичные и добавляет срок окончания действия
        $response->setSharedMaxAge(600);

        return $response;
    }
}

Теперь главная страница профиля имеет публичное кеширование, но GDPR блок имеет 10 минут срока действия. Давайте включим этот блок в основной:

1
2
3
4
5
6
7
{# templates/profile/index.html.twig #}

{# вы можете использовать ссылку контроллера #}
{{ render_ssi(controller('App\\Controller\\ProfileController::gdpr')) }}

{# ... или URL #}
{{ render_ssi(url('profile_gdpr')) }}

Помощник twig render_ssi сгенерирует что-то вроде:

1
<!--#include virtual="/_fragment?_hash=abcdef1234&_path=_controller=App\Controller\ProfileController::gdpr" -->

render_ssi гарантирует, что SSI-директивы генерируются только, если запрос имеет требование заголовка вроде Surrogate-Capability: device="SSI/1.0" (обычно задается веб-сервером). В других случаях, он напрямую встроит суб-ответ.

Note

Чтобы узнать больше о фрагмента кеша Symfony, просмотрите документацию ESI.