function PageCache::storeResponse

Same name in other branches
  1. 9 core/modules/page_cache/src/StackMiddleware/PageCache.php \Drupal\page_cache\StackMiddleware\PageCache::storeResponse()
  2. 8.9.x core/modules/page_cache/src/StackMiddleware/PageCache.php \Drupal\page_cache\StackMiddleware\PageCache::storeResponse()
  3. 10 core/modules/page_cache/src/StackMiddleware/PageCache.php \Drupal\page_cache\StackMiddleware\PageCache::storeResponse()

Stores a response in the page cache.

Parameters

\Symfony\Component\HttpFoundation\Request $request: A request object.

\Symfony\Component\HttpFoundation\Response $response: A response object that should be stored in the page cache.

Return value

bool TRUE if the response has been stored successfully, FALSE otherwise.

1 call to PageCache::storeResponse()
PageCache::fetch in core/modules/page_cache/src/StackMiddleware/PageCache.php
Fetches a response from the backend and stores it in the cache.

File

core/modules/page_cache/src/StackMiddleware/PageCache.php, line 223

Class

PageCache
Executes the page caching before the main kernel takes over the request.

Namespace

Drupal\page_cache\StackMiddleware

Code

protected function storeResponse(Request $request, Response $response) {
    // Drupal's primary cache invalidation architecture is cache tags: any
    // response that varies by a configuration value or data in a content
    // entity should have cache tags, to allow for instant cache invalidation
    // when that data is updated. However, HTTP does not standardize how to
    // encode cache tags in a response. Different CDNs implement their own
    // approaches, and configurable reverse proxies (e.g., Varnish) allow for
    // custom implementations. To keep Drupal's internal page cache simple, we
    // only cache CacheableResponseInterface responses, since those provide a
    // defined API for retrieving cache tags. For responses that do not
    // implement CacheableResponseInterface, there's no easy way to distinguish
    // responses that truly don't depend on any site data from responses that
    // contain invalidation information customized to a particular proxy or
    // CDN.
    // - Drupal modules are encouraged to use CacheableResponseInterface
    //   responses where possible and to leave the encoding of that information
    //   into response headers to the corresponding proxy/CDN integration
    //   modules.
    // - Custom applications that wish to provide internal page cache support
    //   for responses that do not implement CacheableResponseInterface may do
    //   so by replacing/extending this middleware service or adding another
    //   one.
    if (!$response instanceof CacheableResponseInterface) {
        $response->headers
            ->set(static::HEADER, 'UNCACHEABLE (no cacheability)');
        return FALSE;
    }
    // Currently it is not possible to cache binary file or streamed responses:
    // https://github.com/symfony/symfony/issues/9128#issuecomment-25088678.
    // Therefore exclude them, even for subclasses that implement
    // CacheableResponseInterface.
    if ($response instanceof BinaryFileResponse || $response instanceof StreamedResponse) {
        return FALSE;
    }
    // Allow policy rules to further restrict which responses to cache.
    if ($this->responsePolicy
        ->check($response, $request) === ResponsePolicyInterface::DENY) {
        $response->headers
            ->set(static::HEADER, 'UNCACHEABLE (response policy)');
        return FALSE;
    }
    $request_time = $request->server
        ->get('REQUEST_TIME');
    // The response passes all of the above checks, so cache it. Page cache
    // entries default to Cache::PERMANENT since they will be expired via cache
    // tags locally. Because of this, page cache ignores max age.
    // - Get the tags from CacheableResponseInterface per the earlier comments.
    // - Get the time expiration from the Expires header, rather than the
    //   interface, but see https://www.drupal.org/node/2352009 about possibly
    //   changing that.
    $expire = 0;
    // 403 and 404 responses can fill non-LRU cache backends and generally are
    // likely to have a low cache hit rate. So do not cache them permanently.
    if ($response->isClientError()) {
        // Cache for an hour by default. If the 'cache_ttl_4xx' setting is
        // set to 0 then do not cache the response.
        $cache_ttl_4xx = Settings::get('cache_ttl_4xx', 3600);
        if ($cache_ttl_4xx > 0) {
            $expire = $request_time + $cache_ttl_4xx;
        }
    }
    elseif ($expires = $response->getExpires()) {
        $date = $expires->getTimestamp();
        $expire = $date > $request_time ? $date : Cache::PERMANENT;
    }
    else {
        $expire = Cache::PERMANENT;
    }
    if ($expire === Cache::PERMANENT || $expire > $request_time) {
        $tags = $response->getCacheableMetadata()
            ->getCacheTags();
        $this->set($request, $response, $expire, $tags);
    }
    return TRUE;
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.