使用服务器端包含
与 ESI (Edge Side Includes) 类似,SSI 可用于控制响应片段的 HTTP 缓存。最重要的区别是 SSI 可以被大多数 Web 服务器直接识别,例如 Apache、Nginx 等。
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 许可协议获得许可。