1

I have a requirement to expose a specific content type data via REST end point. Below is my code:

public function get() {
    $current_user = $this->currentUser->id();
    $user = $this->entityTypeManager->getStorage('user')->load($current_user);
    $userLangId = $user->language()->getId();

    // You must to implement the logic of your REST Resource here.
    // Use current user after pass authentication to validate access.
    if (!$this->currentUser->hasPermission('access content')) {
      throw new AccessDeniedHttpException();
    }
    $news_values = [
      'langcode' => $userLangId,
      'type' => ['story'],
      'status' => 1,
    ];
    $news_data = $this->entityTypeManager->getStorage('node')->loadByProperties($news_values);
    $newsfeed = [];
    $newsfeed['stories'] = ['Story' => array_values($news_data)];
    if (empty($newsfeed)) {
      return new ResourceResponse('No Newsfeed exist for this user.', 400);
    }
    $response = new ResourceResponse($newsfeed, 200);
//    $response->addCacheableDependency($current_user);

    $response->addCacheableDependency(CacheableMetadata::createFromRenderArray([
      '#cache' => [
        'context' => ['user.roles'],
        'tags' => ['user:3', 'languages:' . $userLangId],
      ],
    ]));
    return $response;
  }

I am getting a proper response with this but I am facing issues in handling the cache. This content is user specific. Based on user language content will popup when they access.

In Response Headers I am getting below things:

X-Drupal-Cache-Contexts: languages:language_interface theme url.site user.permissions
X-Drupal-Cache-Tags: config:filter.format.basic_html config:rest.resource.newsfeed_rest_resource config:rest.settings config:system.site http_response languages:fr node:7 node:9 user:3
X-Drupal-Dynamic-Cache: MISS/HIT

In Cache-tags i have not added node key but its automatically coming and its working once node updated. But if i try to login with different user via basic auth on postman client, content is not changing at all. Its showing cached content for previous user. How I can cache the content per user. Please help me in this regard.

6
  • Looks like your cache context is by the users role. Is that what you want? As if 2 of your users have the same roles so they'd get the same cached response
    – Leigh
    Commented May 1, 2020 at 14:15
  • Ohh right. But how I can make it user specific instead of roles or permissions?
    – Suraj
    Commented May 1, 2020 at 14:18
  • 1
    Just change ['user.roles'] to ['user'] and clear your caches should work
    – Leigh
    Commented May 1, 2020 at 14:22
  • Its not working. As i can see in this article drupal.org/docs/8/api/cache-api/cache-contexts there is no ['user'] context.
    – Suraj
    Commented May 1, 2020 at 15:13
  • When i changed the weight for USER in Detection and selection in language interface. It started working without cache context.
    – Suraj
    Commented May 1, 2020 at 15:20

1 Answer 1

3

@Leigh is right and user does exist. Cache contexts are hierarchical (see change record https://www.drupal.org/node/2451661) and user is a top level context.

So this should work (note the plural form of contexts):

  '#cache' => [
    'contexts' => ['user'],

You can also add the cache context by IDE autocompleting:

$response->getCacheableMetadata()->addCacheContexts(['user']);
2
  • Hey @4k4, Thanks for your detailed explanation. When i add above line, X-Drupal-Dynamic-Cache: UNCACHEABLE. Is it caching or not?
    – Suraj
    Commented May 4, 2020 at 4:23
  • The response might be not cacheable for a different reason, which could be for example the line you have commented out. $current_user is not a cacheable object, then Drupal doesn't raise an error, it silently adds a cache max age of 0 as fallback.
    – 4uk4
    Commented May 4, 2020 at 6:26

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.