Skip to content

Commit

Permalink
Merge branch 'next-36927/dont-remove-caches-on-404' into 'trunk'
Browse files Browse the repository at this point in the history
NEXT-36927 - Don't remove cache cookies on 404 pages

See merge request shopware/6/product/platform!14162
  • Loading branch information
keulinho committed Jul 4, 2024
2 parents aa6825d + 067e4d5 commit b9d43fe
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: Don't remove cache cookies for 404 pages
issue: NEXT-36927
---
# Core
* Changed `\Shopware\Core\Framework\Adapter\Cache\Http\CacheResponseSubscriber` to not remove cache cookies for 404 pages. This prevents logged in customers getting delivered cached pages for not logged-in customers after a 404 page, because the cache cookies were deleted.

2 changes: 1 addition & 1 deletion devenv.nix
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ in {
];

# Fix .env loading
process.implementation = "honcho";
process.implementation = lib.mkDefault "honcho";

dotenv.disableHint = true;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ public function setResponseCache(ResponseEvent $event): void
return;
}

if ($response->getStatusCode() === Response::HTTP_NOT_FOUND) {
// 404 pages should not be cached by reverse proxy, as the cache hit rate would be super low,
// and there is no way to invalidate once the url becomes available
// To still be able to serve 404 pages fast, we don't load the full context and cache the rendered html on application side
// as we don't have the full context the state handling is broken as no customer or cart is available, even if the customer is logged in
// @see \Shopware\Storefront\Framework\Routing\NotFound\NotFoundSubscriber::onError
return;
}

$route = $request->attributes->get('_route');
if ($route === 'frontend.checkout.configure') {
$this->setCurrencyCookie($request, $response);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,57 @@ public static function notCacheableRequestProvider(): iterable
yield 'post request' => [$postRequest];
}

#[DataProvider('cookiesUntouchedProvider')]
public function testCookiesAreUntouched(Request $request, ?Response $response = null): void
{
$subscriber = new CacheResponseSubscriber(
$this->createMock(CartService::class),
100,
true,
new MaintenanceModeResolver(new EventDispatcher()),
new RequestStack(),
false,
null,
null
);

if (!$response) {
$response = new Response();
}

$subscriber->setResponseCache(new ResponseEvent(
$this->createMock(HttpKernelInterface::class),
$request,
HttpKernelInterface::MAIN_REQUEST,
$response
));

static::assertEmpty($response->headers->getCookies(), var_export($response->headers->getCookies(), true));
static::assertFalse($response->headers->has('set-cookie'));
}

/**
* @return array<string, array{0: Request, 1?: Response}>
*/
public static function cookiesUntouchedProvider(): iterable
{
$salesChannelContext = Generator::createSalesChannelContext();
$salesChannelContext->assign(['customer' => null]);

$salesChannelRequest = new Request([], [], [PlatformRequest::ATTRIBUTE_SALES_CHANNEL_CONTEXT_OBJECT => $salesChannelContext]);
$salesChannelRequest->cookies->set(CacheResponseSubscriber::CONTEXT_CACHE_COOKIE, 'foo');
$salesChannelRequest->cookies->set(CacheResponseSubscriber::SYSTEM_STATE_COOKIE, 'logged-in');

$maintenanceRequest = clone $salesChannelRequest;
$maintenanceRequest->attributes->set(SalesChannelRequest::ATTRIBUTE_SALES_CHANNEL_MAINTENANCE, true);
$maintenanceRequest->attributes->set(SalesChannelRequest::ATTRIBUTE_SALES_CHANNEL_MAINTENANCE_IP_WHITLELIST, \json_encode([self::IP, \JSON_THROW_ON_ERROR]));
$maintenanceRequest->server->set('REMOTE_ADDR', self::IP);

yield 'no sales channel context' => [new Request()];
yield 'maintenance request' => [$maintenanceRequest];
yield 'not found response' => [$salesChannelRequest, new Response('', Response::HTTP_NOT_FOUND)];
}

public function testNoCachingWhenInvalidateStateMatches(): void
{
$cartService = $this->createMock(CartService::class);
Expand Down

0 comments on commit b9d43fe

Please sign in to comment.