Skip to content

Commit 029f58c

Browse files
authored
Fix CORS header caching in GraphQL responses (pimcore#896)
Ensure that that dynamic Access-Control-Allow-Origin header is not cached. - Remove Access-Control-Allow-Origin header before saving to cache - Add Access-Control-Allow-Origin dynamically when serving cached responses based on the incoming request's Origin This resolves issues with CORS headers being cached alongside GraphQL responses, which could cause incorrect Access-Control-Allow-Origin values for clients with different origins.
1 parent e55bd44 commit 029f58c

File tree

3 files changed

+38
-13
lines changed

3 files changed

+38
-13
lines changed

doc/10_GraphQL/10_Events.md

+2
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,8 @@ class GraphQlSubscriber implements EventSubscriberInterface
230230
- `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
231231
- `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.
232232

233+
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.
234+
233235
```php
234236
<?php
235237

src/Controller/WebserviceController.php

-10
Original file line numberDiff line numberDiff line change
@@ -225,17 +225,7 @@ public function webonyxAction(
225225
];
226226
}
227227

228-
$origin = '*';
229-
if (!empty($_SERVER['HTTP_ORIGIN'])) {
230-
$origin = $_SERVER['HTTP_ORIGIN'];
231-
}
232-
233228
$response = new JsonResponse($output);
234-
$response->headers->set('Access-Control-Allow-Origin', $origin);
235-
$response->headers->set('Access-Control-Allow-Credentials', 'true');
236-
$response->headers->set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
237-
$response->headers->set('Access-Control-Allow-Headers', 'Origin, Content-Type, X-Auth-Token');
238-
239229
$this->cacheService->save($request, $response);
240230

241231
return $response;

src/Service/OutputCacheService.php

+36-3
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,12 @@ public function load(Request $request)
7171

7272
$cacheKey = $this->computeKey($request);
7373

74-
return $this->loadFromCache($cacheKey);
74+
$response = $this->loadFromCache($cacheKey);
75+
if ($response) {
76+
$this->addCorsHeaders($response);
77+
}
78+
79+
return $response;
7580
}
7681

7782
/**
@@ -81,15 +86,43 @@ public function load(Request $request)
8186
public function save(Request $request, JsonResponse $response, $extraTags = []): void
8287
{
8388
if ($this->useCache($request)) {
84-
$cacheKey = $this->computeKey($request);
8589
$clientname = $request->attributes->getString('clientname');
8690
$extraTags = array_merge(['output', 'datahub', $clientname], $extraTags);
8791

92+
$this->removeCorsHeaders($response);
93+
$cacheKey = $this->computeKey($request);
94+
8895
$event = new OutputCachePreSaveEvent($request, $response);
8996
$this->eventDispatcher->dispatch($event, OutputCacheEvents::PRE_SAVE);
9097

91-
$this->saveToCache($cacheKey, $event->getResponse(), $extraTags);
98+
$this->saveToCache($cacheKey, $response, $extraTags);
99+
100+
$this->addCorsHeaders($response);
101+
}
102+
}
103+
104+
/**
105+
* Removes CORS headers including Access-Control-Allow-Origin that should not be cached.
106+
*/
107+
protected function removeCorsHeaders(JsonResponse $response): void
108+
{
109+
$response->headers->remove('Access-Control-Allow-Origin');
110+
$response->headers->remove('Access-Control-Allow-Credentials');
111+
$response->headers->remove('Access-Control-Allow-Methods');
112+
$response->headers->remove('Access-Control-Allow-Headers');
113+
}
114+
115+
protected function addCorsHeaders(JsonResponse $response): void
116+
{
117+
$origin = '*';
118+
if (!empty($_SERVER['HTTP_ORIGIN'])) {
119+
$origin = $_SERVER['HTTP_ORIGIN'];
92120
}
121+
122+
$response->headers->set('Access-Control-Allow-Origin', $origin);
123+
$response->headers->set('Access-Control-Allow-Credentials', 'true');
124+
$response->headers->set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
125+
$response->headers->set('Access-Control-Allow-Headers', 'Origin, Content-Type, X-Auth-Token');
93126
}
94127

95128
/**

0 commit comments

Comments
 (0)