mateusz / controllerpolicy
SilverStripe 模块,提供针对每个控制器策略的框架。包括比框架默认设置更灵活的缓存策略实现。
Requires
- silverstripe/framework: ^4.2
Requires (Dev)
This package is not auto-updated.
Last update: 2022-02-01 12:35:28 UTC
README
摘要
本模块不再适用于 SilverStripe 3.7 及以上版本。 SilverStripe 框架中的 HTTPCacheControl API 提供了更高层次的缓存行为抽象。
概述
本模块旨在提供配置针对特定控制器应用的响应策略的能力。
它包含了一些用于实现缓存的策略选择
CachingPolicy
:对 SilverStripe 默认的HTTP::add_cache_headers()
进行重写。CustomHeaderPolicy
:允许通过配置系统添加任何头。
还提供了一个示例页面扩展 PageControlledPolicy,它利用了 CachingPolicy 的自定义最大存活时间(max-age)功能,该功能基于 CMS 在特定对象上的配置。
安装
使用 Composer 进行安装
composer require silverstripe/controllerpolicy ^2
注意:本版本支持 SilverStripe 4。对于与 SilverStripe 3 兼容的版本,请参阅 1.x 发布线。
策略
简单策略
假设我们只想将最大存活时间(max-age)为 300 的缓存头应用于主页。本模块提供了一个 CachingPolicy
,它通过实现 ControllerPolicy
接口可以应用于从 Controller
派生的任何内容。该类还可以通过(注入的)属性配置来指定自定义的最大存活时间。
使用此策略的方法是通过您项目的特定 config.yml。我们通过依赖注入配置伪单例,并将其直接应用于 HomePage_Controller
。
SilverStripe\Core\Injector\Injector: StandardCachingPolicy: class: SilverStripe\ControllerPolicy\Policies\CachingPolicy properties: CacheAge: 300 HomePageController: dependencies: Policies: '%$StandardCachingPolicy'
每个策略都会在默认框架的 HTTP::add_cache_headers
之上设置头,这正是我们想要的。这允许我们例如根据策略自定义 Vary
头,这些之前是硬编码的。它还允许我们在每个控制器的基础上配置这些设置,而不是全局默认设置。
忽略域名
如果您希望完全排除某些策略,可以这样做
SilverStripe\ControllerPolicy\ControllerPolicyMiddleware: ignore_regex_domains: - '/.*\.uat.server.com$/'
例如,如果您希望在测试服务器上禁用缓存,或者如果您正在进行激进缓存并且希望编辑者能够立即看到更改的资源,这可能很有用。
Vary 头
CachingPolicy
还允许通过配置系统自定义 Vary
头
SilverStripe\Core\Injector\Injector: StandardCachingPolicy: class: SilverStripe\ControllerPolicy\Policies\CachingPolicy properties: CacheAge: 300 Vary: 'Cookie, X-Forwarded-Protocol, Accept-Language'
任何内容依赖于访客的即时操作 URL 都应该使用 Vary 头来编码这种依赖,否则缓存可能会向错误用户(甚至可能是机密数据!)提供错误的内容。
以下是更多明显的 Vary
头部的表格。 CachingPolicy
使用相对安全的组合 Cookie, X-Forwarded-Protocol
。请注意,您指定的越多,缓存分区越多,这可能会抵消潜在的收益。使用您有信心使用最少的。
Vary 开启 | 描述 | 缓存分区影响 |
---|---|---|
Accept-Encoding | 根据接受的编码进行内容压缩方法 Vary - Apache 会根据接受的编码提供不同的内容。由 Apache mod_header 自动添加。 | 低 |
Cookie | 根据用户会话进行 Vary。基本上将响应分为通用和个性化。请注意,为了使此功能正常工作,缓存需要从请求中清除前端仅cookie,例如 __utma。一个明智的补充。 | 低 |
X-Forwarded-Protocol | 根据协议(如 http 或 https)进行 Vary - 当缓存位于反向代理后面时使用,因为 "BaseURL" 之间通常存在差异,而缓存看到的 URL 中没有反映出来。一个明智的补充。 | 低 |
X-Forwarded-Proto | X-Forwarded-Protocol 的一个变体,选择适合您的反向代理的一个。 | 低 |
Accept | 根据响应格式进行 Vary。一些 URL,尤其是 API 端点,可以根据用户接受的格式产生不同的输出:即 JSON 与 XML。如果可能的话避免,相反,在 URL 中编码内容类型。 | 中等 |
Accept-Language | 根据接受的语言进行 Vary,如果您根据用户浏览器的设置提供不同语言的内容。如果可能的话避免,相反,在 URL 中编码语言。 | 中等 |
User-Agent | 根据用户的设备进行 Vary。由于存在许多用户字符串,这将有效地禁用您的缓存。不惜一切代价避免,相反使用响应式主题。 | 极端 |
覆盖策略
如果您将策略应用于某个特定的 Controller
,则它将应用于所有继承的控制器。例如,如果我们有 FooPageController extends PageController
,那么 PageController
策略也将影响 FooPageController
。
只要您不是使用数组进行配置(您通常不会这样做 - 但请参阅下面的 "复杂策略" 章节),您就可以通过将策略应用于继承的控制器来轻松打破这个链。
FooPageController: dependencies: Policies: null
在 SilverStripe 4 中,配置系统允许您设置虚假值,您可以使用这些值来取消已定义的策略,对于控制器或全局。例如,对于基于 GET 的多步骤表单(通过 silverstripe-multiform 模块),步骤是通过 GET 请求遍历的,因此 URI 没有差异,从而阻止您真正地通过表单。
请注意,您也可以使用任何其他策略来覆盖现有策略 - 您不必取消它。
PageControlledPolicy
以下是如何实现 CMS 功能以覆盖特定页面的 max-age 的示例。在您的配置文件中放入以下语句
SilverStripe\Core\Injector\Injector: GeneralCachingPolicy: class: SilverStripe\ControllerPolicy\Policies\CachingPolicy properties: CacheAge: 900 PageController: dependencies: Policies: '%$GeneralCachingPolicy' Page: extensions: - SilverStripe\ControllerPolicy\PageControlledPolicy
在这里,将 PageControlledPolicy
扩展应用于 Page
将导致在 DB 中写入新的 "MaxAge" 字段,并出现一个新标签页("缓存"),允许管理员用户调整缓存 max-age 头部(以分钟为单位)。
通过数组合并的复杂策略
此示例说明了配置系统的数组合并功能的使用,这将使您能够模拟策略继承,这将反映您的类图。
在此示例中,我们想要配置一个由两个策略组成的全局设置,一个将 max-age 设置为 300,另一个配置自定义头。然后我们想要为主页 max-age 添加更具体的策略,同时保持自定义头。以下是使用配置系统实现此目标的方法
SilverStripe\Core\Injector\Injector: ShortCachingPolicy: class: SilverStripe\ControllerPolicy\Policies\CachingPolicy properties: CacheAge: 300 LongCachingPolicy: class: SilverStripe\ControllerPolicy\Policies\CachingPolicy properties: CacheAge: 3600 CustomPolicy: class: SilverStripe\ControllerPolicy\Policies\CustomHeaderPolicy properties: Headers: Custom-Header: "Hello" HomePageController: dependencies: Policies: LongCachingPolicy: '%$LongCachingPolicy' PageController: dependencies: Policies: ShortCachingPolicy: '%$ShortCachingPolicy' CustomPolicy: '%$CustomPolicy'
主页数组合并的结果如下
- LongCachingPolicy
- ShortCachingPolicy
- CustomPolicy
我们按相反的顺序处理这个数组,这意味着默认情况下,最顶部的策略(最具体的控制器)将覆盖其他策略。这并不意味着许多控制器策略都会触发,而是说一个控制器将应用一个合并后的集合。
注意:您可以使用数组语法或值语法。选择您觉得更简单的。如果使用数组,我们建议给每个值也提供一个键,这样您就可以在其他的配置块中取消之前定义的值,否则这是不可能的。
开发者说明
对于策略的更高级使用(例如,提前返回304头),您可以查看ControllerPolicyMiddleware::process
方法。在这种情况下,您的自定义策略可以使用一个带有304代码的新HTTPResponse替换其applyToResponse
方法中的HTTPResponse $response
参数。
另一件事是,策略将按照控制器初始化的顺序应用,所以如果有多个控制器被调用,后面的控制器将覆盖前面的控制器。但是,这种情况非常不可能,并且与类的继承无关。这关系到SilverStripe中控制器栈的调用方式。在ControllerPolicyApplicator
中的扩展点被选择,使得ModelAsController
和RootURLController
不会触发策略的应用,并且预期只有一个控制器会触发策略。