我们有一个无头 Drupal 站点,它使用 JSON:API 公开 API。我们公开的资源之一是一种内容类型,它内部有一个计算/计算字段,可生成限时链接。该链接仅在 120 秒内有效,但 JSON:API 似乎希望将包含字段数据的响应缓存更长的时间。
理想情况下,我们不想完全关闭这些节点的缓存,因为它们确实会非常频繁地被请求。相反,我们只想将缓存限制在 60 秒左右。所以,
\Drupal::service('page_cache_kill_switch')->trigger()
不是一个理想的解决方案。
我已经研究过通过
EventSubscriber
上的 KernelEvents::RESPONSE
来改变响应的缓存能力,但这只会影响顶层的处理。例如,JSON:API 单独缓存响应的所有部分(“规范化”),以实现最大缓存效率,因此即使响应不是从缓存提供的,每个节点的 JSON:API 版本也是如此。
我还尝试使用服务注入来包装 JSON:API 的规范器,以便我可以调整缓存最大期限。看起来我需要在字段规范化级别执行此操作,但 JSON:API 模块通过抛出
LogicException
和错误 JSON:API does not allow adding more normalizers!
来阻止这种情况。
因此,经过一番努力后,解决方案出人意料地简单——不要在响应级别或 JSON:API 级别操作缓存,而是在实体级别操作它!
这有效:
/**
* Implements hook_ENTITY_TYPE_load() for nodes.
*/
function my_module_node_load(array $entities) {
foreach ($entities as $entity) {
assert($entity instanceof NodeInterface);
if ($entity->bundle() === 'my_content_type') {
// Cache "my_content_type" entities for up to 60 seconds.
$entity->addCacheableDependency(
(new CacheableMetadata())->setCacheMaxAge(60)
);
}
}
}
作为奖励,这使用了核心的正常缓存机制;因此,即使这些节点显示在我们的管理页面上,也只会缓存最多 60 秒。
此外,还可以使用 JSON:API Response Alter 模块。