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\HttpCacheCode
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;
}