Дата обновления перевода 2021-09-21

Работа с серверными включениями (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
    1
    2
    3
    # config/packages/framework.yaml
    framework:
        ssi: { enabled: true }
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    <!-- config/packages/framework.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/symfony"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <framework:config>
            <framework:ssi enabled="true"/>
        </framework:config>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    8
    // config/packages/framework.php
    use Symfony\Config\FrameworkConfig;
    
    return static function (FrameworkConfig $framework) {
        $framework->ssi()
            ->enabled(true)
        ;
    };
    

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

// 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.

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.