如何控制在 Drupal 8/9 中通过 JSON:API 呈现的节点的可缓存性?

How do I control the cacheability of a node rendered through JSON:API in Drupal 8/9?

我们有一个无头的 Drupal 站点,它使用 JSON:API 公开 API。我们公开的资源之一是一种内容类型,其中包含一个 calculated/computed 字段,该字段会生成限时的 link。 link 仅在 120 秒内有效,但似乎 JSON:API 想要将包含字段数据的响应缓存更长的时间。

理想情况下,我们不想完全关闭这些节点的缓存,因为它们确实会被非常频繁地请求。相反,我们只想将缓存限制在 60 秒左右。所以,\Drupal::service('page_cache_kill_switch')->trigger() 不是一个理想的解决方案。

我研究过通过 KernelEvents::RESPONSE 上的 EventSubscriber 改变响应的缓存能力,但这只会影响顶层处理。例如,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 秒。