<?php
namespace App\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Security;
class GlobalHttpCacheSubscriber implements EventSubscriberInterface
{
public function __construct(private Security $security)
{
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::RESPONSE => ['onResponse', -10],
];
}
public function onResponse(ResponseEvent $event): void
{
if (!$event->isMainRequest()) {
return;
}
$request = $event->getRequest();
if ($request->getMethod() !== 'GET') {
return;
}
$response = $event->getResponse();
if ($response->getStatusCode() < 200 || $response->getStatusCode() >= 300) {
return;
}
$cacheControl = $response->headers->get('Cache-Control');
if ($cacheControl && (str_contains($cacheControl, 'no-store') || str_contains($cacheControl, 'no-cache'))) {
return;
}
if ($cacheControl) {
return;
}
$isAuthenticated = (bool) $this->security->getUser();
if ($isAuthenticated) {
$response->setPrivate();
$response->setMaxAge(30);
$response->setSharedMaxAge(0);
$response->headers->set('Vary', 'Cookie, Authorization', false);
} else {
$response->setPublic();
$response->setMaxAge(300);
$response->setSharedMaxAge(600);
$response->headers->set('Vary', 'Accept-Encoding, Accept-Language', false);
$response->headers->set(
'Cache-Control',
trim($response->headers->get('Cache-Control') . ', stale-while-revalidate=30, stale-if-error=600')
);
$contentType = (string) $response->headers->get('Content-Type');
if (str_contains($contentType, 'application/json') && !$response->getEtag()) {
$response->setEtag(sha1((string) $response->getContent()));
}
}
}
}