跳到内容

使用服务器端包含

编辑此页

ESI (Edge Side Includes) 类似,SSI 可用于控制响应片段的 HTTP 缓存。最重要的区别是 SSI 可以被大多数 Web 服务器直接识别,例如 ApacheNginx 等。

SSI 指令通过 HTML 注释完成

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

        <!-- Embed the content of another page here -->
        <!--#include virtual="/..." -->

        <!-- ... more content -->
    </body>
</html>

还有一些其他的 可用指令,但 Symfony 仅管理 #include virtual 指令。

危险

请注意 SSI,您的网站可能会成为注入攻击的受害者。请先阅读这篇 OWASP 文章

当 Web 服务器读取 SSI 指令时,它会请求给定的 URI 或直接从其缓存中获取。它重复此过程,直到没有更多 SSI 指令需要处理。然后,它将所有响应合并为一个并发送给客户端。

在 Symfony 中使用 SSI

首先,要使用 SSI,请确保在您的应用程序配置中启用它

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
// src/Controller/ProfileController.php
namespace App\Controller;

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

class ProfileController extends AbstractController
{
    public function index(): Response
    {
        // by default, responses are private
        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 #}

{# you can use a controller reference #}
{{ render_ssi(controller('App\\Controller\\ProfileController::gdpr')) }}

{# ... or a path (in server's SSI configuration is common to use relative paths instead of absolute URLs) #}
{{ render_ssi(path('profile_gdpr')) }}

render_ssi Twig 助手将生成类似以下内容

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

render_ssi 确保仅当请求具有标头要求(例如 Surrogate-Capability: device="SSI/1.0"(通常由 Web 服务器提供))时才生成 SSI 指令。否则,它将直接嵌入子响应。

注意

有关 Symfony 缓存片段的更多信息,请浏览 ESI 文档

本作品,包括代码示例,根据 Creative Commons BY-SA 3.0 许可协议获得许可。
目录
    版本