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

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html>
    <body>
        <!-- ... некоторое содержание -->

        <!-- Встроить содержание другой страницы здесь -->
        <!--#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, вы можете добавить окончание срока действия этому блоку, чтобы страница оставалась частной:

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

use Symfony\Component\HttpKernel\Attribute\Cache;
// ...

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

    #[Cache(smaxage: 600)]
    public function gdpr(): Response
    {
        return $this->render('profile/gdpr.html.twig');
    }
}

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

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

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

{# ... или путь (в конфигурации сервера SSI распространено использование относительных путей вместо абсолютных URL) #}
{{ render_ssi(path('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 .