The Page Cache module caches whole responses for requests. It does not respect the Http Vary header though.
The Page Cache module calculates the CID as follows:
<?php
/**
* Gets the page cache ID for this request.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* A request object.
*
* @return string
* The cache ID for this request.
*/
protected function getCacheId(Request $request) {
$cid_parts = [
$request->getSchemeAndHttpHost() . $request->getRequestUri(),
$request->getRequestFormat(),
];
return implode(':', $cid_parts);
}
?>
-> It does not include cache contexts, which is a critical thing to consider, and developers might oversee this very easily.
Example
Suppose you have a controller which sets cache contexts for HTTP request headers Origin
(for cross-origin resource sharing). The controller legitimately adds 'Origin
' to the 'Vary
' response header entry. The Page Cache does not respect this, and thus a mismatched response might be returned. Browsers might then react with a blocked resource by the same origin principle.
How to avoid this problem
When writing custom controllers: One current workaround for this problem is to completely skip Page Cache by not creating CacheableResponseInterface
responses. This is a huge minus though, because then you might have no cache at all for the backend.
Another way is to use Drupal's
opt-in CORS support β
. This can be sufficient if the response header generation is kind of static and especially not conditionally. One use case I have found where this opt-in support is not sufficient, is when to implement a resource for serving Accelerated Mobile Pages, since these ones require a certain logic for generating an acceptable response header. Especially when having a site running on multiple domains and protocols, this might get really tough.
Proposed solution
Currently know of 3 options:
- Page Cache must automatically create a cache context on its own regards the Vary header entry, if it's something different than
Cookie
value or
- Page Cache must either include cache contexts during its CID calculation, at least a minimum of the available ones which affect anonymous request variation - especially HTTP request headers or
- Page Cache must skip (but not set Cache-Control to must-revalidate, no-cache etc.) caching for anonymous requests having other values than Cookie in the Vary entry of the response header. Or
- One other possibility could be to introduce an alternative to CacheableResponseInterface: CacheableProxyResponseInterface. When page_cache makes an instanceof CacheableProxyResponseInterface it would then bypass caching for such response. Other subscribers like the FinishResponseSubscriber would need some adjustment for that too then. This would enable developers to bypass page_cache but still delivering cacheable responses for their proxies.