Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. HttpCache.php

function HttpCache::forward

Forwards the Request to the backend and returns the Response.

All backend requests (cache passes, fetches, cache validations) run through this method.

Parameters

bool $catch Whether to catch exceptions or not:

Response|null $entry A Response instance (the stale entry if present, null otherwise):

3 calls to HttpCache::forward()
HttpCache::fetch in vendor/symfony/http-kernel/HttpCache/HttpCache.php
Unconditionally fetches a fresh response from the backend and stores it in the cache if is cacheable.
HttpCache::pass in vendor/symfony/http-kernel/HttpCache/HttpCache.php
Forwards the Request to the backend without storing the Response in the cache.
HttpCache::validate in vendor/symfony/http-kernel/HttpCache/HttpCache.php
Validates that a cache entry is fresh.

File

vendor/symfony/http-kernel/HttpCache/HttpCache.php, line 455

Class

HttpCache
Cache provides HTTP caching.

Namespace

Symfony\Component\HttpKernel\HttpCache

Code

protected function forward(Request $request, bool $catch = false, ?Response $entry = null) : Response {
    $this->surrogate?->addSurrogateCapability($request);
    // always a "master" request (as the real master request can be in cache)
    $response = SubRequestHandler::handle($this->kernel, $request, HttpKernelInterface::MAIN_REQUEST, $catch);
    
    /*
     * Support stale-if-error given on Responses or as a config option.
     * RFC 7234 summarizes in Section 4.2.4 (but also mentions with the individual
     * Cache-Control directives) that
     *
     *      A cache MUST NOT generate a stale response if it is prohibited by an
     *      explicit in-protocol directive (e.g., by a "no-store" or "no-cache"
     *      cache directive, a "must-revalidate" cache-response-directive, or an
     *      applicable "s-maxage" or "proxy-revalidate" cache-response-directive;
     *      see Section 5.2.2).
     *
     * https://tools.ietf.org/html/rfc7234#section-4.2.4
     *
     * We deviate from this in one detail, namely that we *do* serve entries in the
     * stale-if-error case even if they have a `s-maxage` Cache-Control directive.
     */
    if (null !== $entry && \in_array($response->getStatusCode(), [
        500,
        502,
        503,
        504,
    ]) && !$entry->headers
        ->hasCacheControlDirective('no-cache') && !$entry->mustRevalidate()) {
        if (null === ($age = $entry->headers
            ->getCacheControlDirective('stale-if-error'))) {
            $age = $this->options['stale_if_error'];
        }
        
        /*
         * stale-if-error gives the (extra) time that the Response may be used *after* it has become stale.
         * So we compare the time the $entry has been sitting in the cache already with the
         * time it was fresh plus the allowed grace period.
         */
        if ($entry->getAge() <= $entry->getMaxAge() + $age) {
            $this->record($request, 'stale-if-error');
            return $entry;
        }
    }
    
    /*
        RFC 7231 Sect. 7.1.1.2 says that a server that does not have a reasonably accurate
        clock MUST NOT send a "Date" header, although it MUST send one in most other cases
        except for 1xx or 5xx responses where it MAY do so.
    
        Anyway, a client that received a message without a "Date" header MUST add it.
    */
    if (!$response->headers
        ->has('Date')) {
        $response->setDate(\DateTimeImmutable::createFromFormat('U', time()));
    }
    $this->processResponseBody($request, $response);
    if ($this->isPrivateRequest($request) && !$response->headers
        ->hasCacheControlDirective('public')) {
        $response->setPrivate();
    }
    elseif ($this->options['default_ttl'] > 0 && null === $response->getTtl() && !$response->headers
        ->getCacheControlDirective('must-revalidate')) {
        $response->setTtl($this->options['default_ttl']);
    }
    return $response;
}
RSS feed
Powered by Drupal