vendor/api-platform/core/src/HttpCache/EventListener/AddHeadersListener.php line 55

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the API Platform project.
  4.  *
  5.  * (c) Kévin Dunglas <dunglas@gmail.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. declare(strict_types=1);
  11. namespace ApiPlatform\HttpCache\EventListener;
  12. use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
  13. use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
  14. use ApiPlatform\Util\OperationRequestInitiatorTrait;
  15. use ApiPlatform\Util\RequestAttributesExtractor;
  16. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  17. /**
  18.  * Configures cache HTTP headers for the current response.
  19.  *
  20.  * @author Kévin Dunglas <dunglas@gmail.com>
  21.  */
  22. final class AddHeadersListener
  23. {
  24.     use OperationRequestInitiatorTrait;
  25.     private $etag;
  26.     private $maxAge;
  27.     private $sharedMaxAge;
  28.     private $vary;
  29.     private $public;
  30.     private $resourceMetadataFactory;
  31.     private $staleWhileRevalidate;
  32.     private $staleIfError;
  33.     /**
  34.      * @param ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory
  35.      */
  36.     public function __construct(bool $etag falseint $maxAge nullint $sharedMaxAge null, array $vary nullbool $public null$resourceMetadataFactory nullint $staleWhileRevalidate nullint $staleIfError null)
  37.     {
  38.         $this->etag $etag;
  39.         $this->maxAge $maxAge;
  40.         $this->sharedMaxAge $sharedMaxAge;
  41.         $this->vary $vary;
  42.         $this->public $public;
  43.         $this->resourceMetadataFactory $resourceMetadataFactory;
  44.         $this->staleWhileRevalidate $staleWhileRevalidate;
  45.         $this->staleIfError $staleIfError;
  46.     }
  47.     public function onKernelResponse(ResponseEvent $event): void
  48.     {
  49.         $request $event->getRequest();
  50.         if (!$request->isMethodCacheable()) {
  51.             return;
  52.         }
  53.         $attributes RequestAttributesExtractor::extractAttributes($request);
  54.         if (\count($attributes) < 1) {
  55.             return;
  56.         }
  57.         $response $event->getResponse();
  58.         if (!$response->getContent() || !$response->isSuccessful()) {
  59.             return;
  60.         }
  61.         $operation $this->initializeOperation($request);
  62.         $resourceCacheHeaders $attributes['cache_headers'] ?? [];
  63.         if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) {
  64.             $resourceMetadata $this->resourceMetadataFactory->create($attributes['resource_class']);
  65.             $resourceCacheHeaders $resourceMetadata->getOperationAttribute($attributes'cache_headers', [], true);
  66.         } elseif ($operation) {
  67.             $resourceCacheHeaders $operation->getCacheHeaders();
  68.         }
  69.         if ($this->etag && !$response->getEtag()) {
  70.             $response->setEtag(md5((string) $response->getContent()));
  71.         }
  72.         if (null !== ($maxAge $resourceCacheHeaders['max_age'] ?? $this->maxAge) && !$response->headers->hasCacheControlDirective('max-age')) {
  73.             $response->setMaxAge($maxAge);
  74.         }
  75.         $vary $resourceCacheHeaders['vary'] ?? $this->vary;
  76.         if (null !== $vary) {
  77.             $response->setVary(array_diff($vary$response->getVary()), false);
  78.         }
  79.         // if the public-property is defined and not yet set; apply it to the response
  80.         $public = ($resourceCacheHeaders['public'] ?? $this->public);
  81.         if (null !== $public && !$response->headers->hasCacheControlDirective('public')) {
  82.             $public $response->setPublic() : $response->setPrivate();
  83.         }
  84.         // Cache-Control "s-maxage" is only relevant is resource is not marked as "private"
  85.         if (false !== $public && null !== ($sharedMaxAge $resourceCacheHeaders['shared_max_age'] ?? $this->sharedMaxAge) && !$response->headers->hasCacheControlDirective('s-maxage')) {
  86.             $response->setSharedMaxAge($sharedMaxAge);
  87.         }
  88.         if (null !== ($staleWhileRevalidate $resourceCacheHeaders['stale_while_revalidate'] ?? $this->staleWhileRevalidate) && !$response->headers->hasCacheControlDirective('stale-while-revalidate')) {
  89.             $response->headers->addCacheControlDirective('stale-while-revalidate', (string) $staleWhileRevalidate);
  90.         }
  91.         if (null !== ($staleIfError $resourceCacheHeaders['stale_if_error'] ?? $this->staleIfError) && !$response->headers->hasCacheControlDirective('stale-if-error')) {
  92.             $response->headers->addCacheControlDirective('stale-if-error', (string) $staleIfError);
  93.         }
  94.     }
  95. }
  96. class_alias(AddHeadersListener::class, \ApiPlatform\Core\HttpCache\EventListener\AddHeadersListener::class);