4

We want to display customer (actually customer-group) specific information on product detail pages in Shopware 6.

There seems to be the HTTP cache and we are afraid that the page would be cached if a specific customer group displays the page and the information would be leaked to non-customers.

Is this assumption correct?

The documentation does not reveal much information about this.

Is there a way to set specific cache tags, so that the information is only displayed to the correct customer group?

Or do we need to fetch the data dynamically via AJAX?

Bonus question: Can the HTTP cache be simulated in automatic tests to ensure the functionality works?

What I found out so far:

  • The is annotation @httpCache for controller, which seems to control whether a page is cached or not

  • The cache key is generated in \Shopware\Storefront\Framework\Cache\HttpCacheKeyGenerator::generate. It take the full request URI into account, and some cacheHash which is injected. I believe it would not take the customer group into account

  • Maybe this generate() method could be decorated, but I am not sure if that is the right way.

  • There is a cookie being set sw-cache-hash which influences the caching. It takes the customer into account.

  • sw-cache-hash is created here:

      if ($context->getCustomer() || $cart->getLineItems()->count() > 0) {
          $cookie = Cookie::create(self::CONTEXT_CACHE_COOKIE, $this->buildCacheHash($context));
          $cookie->setSecureDefault($request->isSecure());
    
          $response->headers->setCookie($cookie);
      } else {
          $response->headers->removeCookie(self::CONTEXT_CACHE_COOKIE);
          $response->headers->clearCookie(self::CONTEXT_CACHE_COOKIE);
      }
    

So as soon you are logged in or have some items in the cart, a different cache hash is used. This depends on the following, but not on the customer group it self:

private function buildCacheHash(SalesChannelContext $context): string
{
    return md5(json_encode([
        $context->getRuleIds(),
        $context->getContext()->getVersionId(),
        $context->getCurrency()->getId(),
    ]));
}
Alex
  • 32,506
  • 16
  • 106
  • 171

2 Answers2

2

Additionally there is the notion of cache-invalidation states, that describe when the caching should not be used.

You can configure that inside the shopware.yaml config file for the http-cache as a whole or on route level for the store-api routes.

From the default config inside platform:

shopware:
   cache:
      invalidation:
            http_cache: ['logged-in', 'cart-filled']
            product_listing_route: []

As you can see by default the http-cache won't be used if a user logs in or has something in his cart.

j_elfering
  • 2,707
  • 6
  • 15
  • Ah okay, so we probably don't need to do anything about it, as long as we do not want to use the http cache for logged in users. – Alex Jan 28 '22 at 14:59
1

As you can see in the last code snippet, it takes into account the active Rule ids. This means that if you create a rule (through Settings > Rule Builder) that is active on a certain group, but not on another or no group, it will be taken into account & create a different cache hash for the different customer groups.

Rune Laenen
  • 243
  • 1
  • 7
  • Pretty cool - thanks. We were thinking about making the customer group configurable in our Plugin, but instead it looks like we should create a rule and somehow assign an action to it like "special information visible". By this the cache problem would solve itself, I guess. – Alex Jan 28 '22 at 14:57