Skip to content

Commit f3ef5d4

Browse files
committed
Enhance CORS exposed headers handling for dynamic response (#26)
- Update CorsService to merge existing exposed headers with configured - Add deduplication for exposed headers
1 parent 98c1493 commit f3ef5d4

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

src/CorsService.php

+10-1
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,17 @@ private function configureAllowCredentials(Response $response, Request $request)
260260

261261
private function configureExposedHeaders(Response $response, Request $request): void
262262
{
263+
$existingExposedHeaders = $response->headers->get('Access-Control-Expose-Headers');
264+
$exposedHeaders = $existingExposedHeaders ? array_map('trim', explode(',', $existingExposedHeaders)) : [];
265+
263266
if ($this->exposedHeaders) {
264-
$response->headers->set('Access-Control-Expose-Headers', implode(', ', $this->exposedHeaders));
267+
$exposedHeaders = array_merge($this->exposedHeaders, $exposedHeaders);
268+
}
269+
270+
$uniqueExposedHeaders = array_unique(array_filter($exposedHeaders));
271+
272+
if (!empty($uniqueExposedHeaders)) {
273+
$response->headers->set('Access-Control-Expose-Headers', implode(', ', $uniqueExposedHeaders));
265274
}
266275
}
267276

tests/CorsTest.php

+37
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,43 @@ public function itDoesntSetAccessControlAllowOriginWithoutOrigin(): void
535535
$this->assertFalse($response->headers->has('Access-Control-Allow-Origin'));
536536
}
537537

538+
/**
539+
* @test
540+
*/
541+
public function itConfiguresExposedHeadersWhenResponseHasNoExistingHeaders(): void
542+
{
543+
$app = $this->createStackedApp([], [
544+
'Access-Control-Expose-Headers' => 'X-Custom-1, X-Custom-2',
545+
]);
546+
$request = $this->createValidActualRequest();
547+
548+
$response = $app->handle($request);
549+
550+
$this->assertTrue($response->headers->has('Access-Control-Expose-Headers'));
551+
$this->assertEquals('X-Custom-1, X-Custom-2', $response->headers->get('Access-Control-Expose-Headers'));
552+
}
553+
554+
/**
555+
* @test
556+
*/
557+
public function itMergesExposedHeadersWhenResponseHasExistingHeaders(): void
558+
{
559+
$app = $this->createStackedApp(
560+
[
561+
'exposedHeaders' => ['X-Option-1', 'X-Option-2'],
562+
],
563+
[
564+
'Access-Control-Expose-Headers' => 'X-Custom-1',
565+
]
566+
);
567+
$request = $this->createValidActualRequest();
568+
569+
$result = $app->handle($request);
570+
571+
$this->assertTrue($result->headers->has('Access-Control-Expose-Headers'));
572+
$this->assertEquals('X-Option-1, X-Option-2, X-Custom-1', $result->headers->get('Access-Control-Expose-Headers'));
573+
}
574+
538575
private function createValidActualRequest(): Request
539576
{
540577
$request = new Request();

0 commit comments

Comments
 (0)