diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index d5c8cb45cd4be..59e974d62d557 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -774,8 +774,10 @@ public function getMaxAge(): ?int return (int) $this->headers->getCacheControlDirective('max-age'); } - if (null !== $this->getExpires()) { - return (int) $this->getExpires()->format('U') - (int) $this->getDate()->format('U'); + if (null !== $expires = $this->getExpires()) { + $maxAge = (int) $expires->format('U') - (int) $this->getDate()->format('U'); + + return max($maxAge, 0); } return null; @@ -819,7 +821,7 @@ public function setSharedMaxAge(int $value): object * * It returns null when no freshness information is present in the response. * - * When the responses TTL is <= 0, the response may not be served from cache without first + * When the response's TTL is 0, the response may not be served from cache without first * revalidating with the origin. * * @final @@ -828,7 +830,7 @@ public function getTtl(): ?int { $maxAge = $this->getMaxAge(); - return null !== $maxAge ? $maxAge - $this->getAge() : null; + return null !== $maxAge ? max($maxAge - $this->getAge(), 0) : null; } /** diff --git a/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php index 5885ab4b1f356..580099903bb2b 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php @@ -353,9 +353,8 @@ public function testGetMaxAge() $this->assertEquals(3600, $response->getMaxAge(), '->getMaxAge() falls back to Expires when no max-age or s-maxage directive present'); $response = new Response(); - $response->headers->set('Cache-Control', 'must-revalidate'); $response->headers->set('Expires', -1); - $this->assertLessThanOrEqual(time() - 2 * 86400, $response->getExpires()->format('U')); + $this->assertSame(0, $response->getMaxAge()); $response = new Response(); $this->assertNull($response->getMaxAge(), '->getMaxAge() returns null if no freshness information available'); @@ -436,7 +435,7 @@ public function testGetTtl() $response = new Response(); $response->headers->set('Expires', $this->createDateTimeOneHourAgo()->format(\DATE_RFC2822)); - $this->assertLessThan(0, $response->getTtl(), '->getTtl() returns negative values when Expires is in past'); + $this->assertSame(0, $response->getTtl(), '->getTtl() returns zero when Expires is in past'); $response = new Response(); $response->headers->set('Expires', $response->getDate()->format(\DATE_RFC2822)); diff --git a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php index 28be364c17bfa..5688fc0c13ccd 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php @@ -718,7 +718,11 @@ private function mayServeStaleWhileRevalidate(Response $entry): bool $timeout = $this->options['stale_while_revalidate']; } - return abs($entry->getTtl() ?? 0) < $timeout; + $age = $entry->getAge(); + $maxAge = $entry->getMaxAge() ?? 0; + $ttl = $maxAge - $age; + + return abs($ttl) < $timeout; } /** diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php index 96f66354ba7e4..365afd6dff2d6 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php @@ -590,6 +590,30 @@ public function testResponseHeadersMaxAgeAndExpiresDefaultValuesIfSessionStarted $this->assertFalse($response->headers->has(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER)); } + public function testPrivateResponseMaxAgeIsRespectedIfSessionStarted() + { + $kernel = $this->createMock(HttpKernelInterface::class); + + $session = $this->createMock(Session::class); + $session->expects($this->once())->method('getUsageIndex')->willReturn(1); + $request = new Request([], [], [], [], [], ['SERVER_PROTOCOL' => 'HTTP/1.0']); + $request->setSession($session); + + $response = new Response(); + $response->headers->set('Cache-Control', 'no-cache'); + $response->prepare($request); + + $listener = new SessionListener(new Container()); + $listener->onKernelResponse(new ResponseEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST, $response)); + + $this->assertSame(0, $response->getMaxAge()); + $this->assertFalse($response->headers->hasCacheControlDirective('public')); + $this->assertTrue($response->headers->hasCacheControlDirective('private')); + $this->assertTrue($response->headers->hasCacheControlDirective('must-revalidate')); + $this->assertLessThanOrEqual(new \DateTimeImmutable('now', new \DateTimeZone('UTC')), new \DateTimeImmutable($response->headers->get('Expires'))); + $this->assertFalse($response->headers->has(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER)); + } + public function testSurrogateMainRequestIsPublic() { $session = $this->createMock(Session::class); diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index 09682db49d2e6..180a79b336adc 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -20,7 +20,7 @@ "symfony/deprecation-contracts": "^2.1|^3", "symfony/error-handler": "^4.4|^5.0|^6.0", "symfony/event-dispatcher": "^5.0|^6.0", - "symfony/http-foundation": "^5.3.7|^6.0", + "symfony/http-foundation": "^5.4.21|^6.2.7", "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-php73": "^1.9", "symfony/polyfill-php80": "^1.16", pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy