8

I'm using Drupal 8 in headless mode with Angular 8 as my client, but Drupal caches the API calls. For example, I have an end point which suppose to give items in random order, but this doesn't happen. I only get cache items in a particular order.

How can I overcome this? I have tried to disable the cache modules, but I still get the same behavior.

2 Answers 2

15

There are two level of caching in Drupal.

1.) Dynamic Page Cache

You have to provide the correct cache metadata on the json response.

For example use the cache properties from a config or content entity

$response->addCacheableDependency($entitiy);

or build a cacheable metadata object and add this to the response:

$build = [
  '#cache' => [
    'contexts' => ['url.query_args'],
    'tags' => ['node:1', 'node_list'],
    'max-age' => 300,
  ],
];
$cache_metadata = \Drupal\Core\Cache\CacheableMetadata::createFromRenderArray($build);
$response->addCacheableDependency($cache_metadata);

You can use this in a custom controller or implement this in an event subscriber to alter responses from other modules (core or contrib).

2.) Internal Page Cache

The module Internal Page Cache caches all responses for anonymous requests regardless of the cache metadata. You can uninstall this module to disable this cache.

Alternative solution

On the client side append a different query string on every request to get a fresh response:

node/123?_format=json&time=123456789

This will disable the Internal Page Cache and parts of the Dynamic Page Cache.

Reference: https://www.drupal.org/docs/8/core/modules/rest/javascript-and-drupal-8-restful-web-services

5
  • 1
    You can also disable Internal Page Cache for specific routes with \Drupal::service('page_cache_kill_switch')->trigger(); And if drupal.org/node/2352009 gets in, it will also respect the max-age.
    – Berdir
    Commented Dec 8, 2016 at 20:16
  • 1
    I had to add Berdir's suggestion of \Drupal::service('page_cache_kill_switch')->trigger(); otherwise it still cached for anonymous users for me
    – Amy
    Commented Sep 7, 2017 at 16:09
  • I found that drupal-8 only used the path component as cache key. I was using get query parameters but always getting the same result regardless of what was in the parameter. The time get parameter would not work.
    – Interlated
    Commented Apr 21, 2021 at 3:28
  • 1
    @Interlated, for response (page) caching there are two levels as described. Level 2 builds cache keys based on the entire URL including the query string. Level 1 builds cache keys based on routes + contexts. See the code example.
    – 4uk4
    Commented Apr 21, 2021 at 6:33
  • If the time parameter is in seconds you probably want to disable caching in level 1 by adding cache max-age of 0. Doesn't make much sense to add a new cache entry every 1 second.
    – 4uk4
    Commented Apr 21, 2021 at 6:50
5

I prefer to disable cache entirely for my endpoints. You can do it adding a cacheable dependency with a zero MaxAge to the ResourceResponse object.

Here is an example:

$response = new ResourceResponse($data);
$disable_cache = new CacheableMetadata();
$disable_cache->setCacheMaxAge(0);

$response->addCacheableDependency($disable_cache);

return $response;
1
  • This seems like a great idea for development, but for a production site you would want to add the parameters that might vary the response to your addCacheableDependency so that your site can be more performant/scalable.
    – greggles
    Commented Feb 7, 2019 at 23:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.