11

Using this tutorial Drupal Console's drupal gprr command, I've created a custom REST resource in Drupal 8. I'm able to use this resource to retrieve a simple JSON object that says hello to the current user by doing a GET on:

http://localhost/example/hello?_format=json

The JSON returned then looks like this:

{ "hello": "tyler" }

This is to be expected, as I'm logged in. But when I logout, and do another GET on the resource, the same result is returned:

{ "hello": "tyler" }

Doing a full Drupal cache clear fixes this issue, but I'd like to specifically disable caching on this resource. How can I do that?

As a workaround, I thought adding a time stamp to the query string would work:

http://localhost/example/hello?_format=json&time=123456789

But that also returns the exact same result, no matter what time stamp value is in the query string.

For brevity, here's the skeleton code for building the GET resource:

class ExampleHello extends ResourceBase {

  /**
   * {@inheritdoc}
   */
  public static function create(/* ... */) {
    return new static(/* ... */);
  }

  /**
   * Constructs a Drupal\rest\Plugin\ResourceBase object.
   */
  public function __construct(/* ... */) {
    parent::__construct(/* ... */);
    // ...
  }

  /*
   * Responds to GET requests.
   */
  public function get() {

    $account = \Drupal::currentUser()->getAccount();
    if (!$account->id()) {
      return new ResourceResponse(array(
        'welcome' => 'visitor'
      ));
    }
    return new ResourceResponse(array(
      'hello' => $account->getAccountName()
    ));
  }

}

Is there a configuration/setting I need to set on this plugin to disable caching on GET requests?

16

You want to read the Cacheability documentation. it says render arrays, but it also applies to response objects.

ResourceResponse implements CacheableResponseInterface, which has the addCacheableDependency method.

If in any way possible, you want to avoid disabling the cache (which you would do by setting the cache max age to 0), but add the necessary cache contexts and cache tags.

In your cache, that means all you need to do is $response->addCacheableDependency($account).

You also don't need getAccount(), just use currentUser() directly, it's a proxy.

  • 3
    You should also avoid using \Drupal in places where you can inject the service, which based on your commented out code, looks like you can do here. – mpdonadio Dec 8 '15 at 15:16
9

I had the same issue.

After reading through the documentation and looking through this page, I was able to shut off the cache for my custom endpoint. Here's an example of my working code inside the get() function for my endpoint:

$build = array(
  '#cache' => array(
    'max-age' => 0,
  ),
);

return (new ResourceResponse($myResponse))->addCacheableDependency($build);

Adding this for future reference, hope this helps anyone who needs it.

CacheableResponseTrait documentation page

  • Doesn't work!!!! – podarok Feb 7 '18 at 9:24
  • @podarok - this didn't work at first for me either, then after issuing one more drush cr it worked each time afterwards. – tyler.frankenstein Apr 18 at 17:54
3

I also had the same issue and the solution for that is:

$response->getCacheableMetadata()->addCacheContexts(['url.query_args', 'url.path']);

You can also see the CacheableMetadata and the cache contexts documentations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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