diff --git a/doc/10_GraphQL/10_Events.md b/doc/10_GraphQL/10_Events.md index efa1f72f..60503345 100644 --- a/doc/10_GraphQL/10_Events.md +++ b/doc/10_GraphQL/10_Events.md @@ -230,6 +230,8 @@ class GraphQlSubscriber implements EventSubscriberInterface - `OutputCacheEvents::PRE_LOAD`: is triggered before trying to load an entry from cache, if cache is enabled. You can disable the cache for this request by setting `$event->setUseCache(false)`. If you disable the cache, the entry won't be loaded nor saved - `OutputCacheEvents::PRE_SAVE`: if cache is enabled, it's triggered before saving an entry into the cache. You can use it to modify the response before it gets saved. +Uncacheable headers, such as CORS Access-Control-Allow-Origin, are removed from the response before the PRE_SAVE event and re-added after the cached response is loaded. + ```php headers->set('Access-Control-Allow-Origin', $origin); - $response->headers->set('Access-Control-Allow-Credentials', 'true'); - $response->headers->set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); - $response->headers->set('Access-Control-Allow-Headers', 'Origin, Content-Type, X-Auth-Token'); - $this->cacheService->save($request, $response); return $response; diff --git a/src/Service/OutputCacheService.php b/src/Service/OutputCacheService.php index ac3c95a1..dc8d50d0 100644 --- a/src/Service/OutputCacheService.php +++ b/src/Service/OutputCacheService.php @@ -71,7 +71,12 @@ public function load(Request $request) $cacheKey = $this->computeKey($request); - return $this->loadFromCache($cacheKey); + $response = $this->loadFromCache($cacheKey); + if ($response) { + $this->addCorsHeaders($response); + } + + return $response; } /** @@ -81,15 +86,43 @@ public function load(Request $request) public function save(Request $request, JsonResponse $response, $extraTags = []): void { if ($this->useCache($request)) { - $cacheKey = $this->computeKey($request); $clientname = $request->attributes->getString('clientname'); $extraTags = array_merge(['output', 'datahub', $clientname], $extraTags); + $this->removeCorsHeaders($response); + $cacheKey = $this->computeKey($request); + $event = new OutputCachePreSaveEvent($request, $response); $this->eventDispatcher->dispatch($event, OutputCacheEvents::PRE_SAVE); - $this->saveToCache($cacheKey, $event->getResponse(), $extraTags); + $this->saveToCache($cacheKey, $response, $extraTags); + + $this->addCorsHeaders($response); + } + } + + /** + * Removes CORS headers including Access-Control-Allow-Origin that should not be cached. + */ + protected function removeCorsHeaders(JsonResponse $response): void + { + $response->headers->remove('Access-Control-Allow-Origin'); + $response->headers->remove('Access-Control-Allow-Credentials'); + $response->headers->remove('Access-Control-Allow-Methods'); + $response->headers->remove('Access-Control-Allow-Headers'); + } + + protected function addCorsHeaders(JsonResponse $response): void + { + $origin = '*'; + if (!empty($_SERVER['HTTP_ORIGIN'])) { + $origin = $_SERVER['HTTP_ORIGIN']; } + + $response->headers->set('Access-Control-Allow-Origin', $origin); + $response->headers->set('Access-Control-Allow-Credentials', 'true'); + $response->headers->set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); + $response->headers->set('Access-Control-Allow-Headers', 'Origin, Content-Type, X-Auth-Token'); } /**