From 2fda88f845cbd98dd350826817460dc6860b9f23 Mon Sep 17 00:00:00 2001 From: Luke Leber Date: Mon, 3 Mar 2025 22:23:57 -0500 Subject: [PATCH] Prevent loss of custom vary headers --- src/CorsService.php | 4 ++-- tests/CorsTest.php | 44 +++++++++++++++++++++++++++++++++----------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/CorsService.php b/src/CorsService.php index b8c3de9..569ff5b 100644 --- a/src/CorsService.php +++ b/src/CorsService.php @@ -211,8 +211,8 @@ public function varyHeader(Response $response, $header): Response { if (!$response->headers->has('Vary')) { $response->headers->set('Vary', $header); - } elseif (!in_array($header, explode(', ', $response->headers->get('Vary')))) { - $response->headers->set('Vary', $response->headers->get('Vary') . ', ' . $header); + } elseif (!in_array($header, $response->headers->all('Vary'))) { + $response->headers->set('Vary', $header, false); } return $response; diff --git a/tests/CorsTest.php b/tests/CorsTest.php index d63d004..018e504 100644 --- a/tests/CorsTest.php +++ b/tests/CorsTest.php @@ -90,7 +90,7 @@ public function it_returns_allow_headers_header_on_allow_all_headers_request() $this->assertEquals(204, $response->getStatusCode()); $this->assertEquals('Foo, BAR', $response->headers->get('Access-Control-Allow-Headers')); - $this->assertEquals('Access-Control-Request-Headers, Access-Control-Request-Method', $response->headers->get('Vary')); + $this->assertEquals(['Access-Control-Request-Headers', 'Access-Control-Request-Method'], $response->headers->all('Vary')); } /** @@ -106,7 +106,7 @@ public function it_returns_allow_headers_header_on_allow_all_headers_request_cre $this->assertEquals(204, $response->getStatusCode()); $this->assertEquals('Foo, BAR', $response->headers->get('Access-Control-Allow-Headers')); - $this->assertEquals('Access-Control-Request-Headers, Access-Control-Request-Method', $response->headers->get('Vary')); + $this->assertEquals(['Access-Control-Request-Headers', 'Access-Control-Request-Method'], $response->headers->all('Vary')); } /** @@ -164,7 +164,7 @@ public function it_adds_a_vary_header_when_wildcard_and_supports_credentials() $response = $app->handle($request); $this->assertTrue($response->headers->has('Vary')); - $this->assertEquals('Origin', $response->headers->get('Vary')); + $this->assertEquals(['Origin'], $response->headers->all('Vary')); } /** @@ -182,7 +182,7 @@ public function it_adds_multiple_vary_header_when_wildcard_and_supports_credenti $response = $app->handle($request); $this->assertTrue($response->headers->has('Vary')); - $this->assertEquals('Origin, Access-Control-Request-Method', $response->headers->get('Vary')); + $this->assertEquals(['Origin', 'Access-Control-Request-Method'], $response->headers->all('Vary')); } /** @@ -198,7 +198,7 @@ public function it_adds_a_vary_header_when_has_origin_patterns() $response = $app->handle($request); $this->assertTrue($response->headers->has('Vary')); - $this->assertEquals('Origin', $response->headers->get('Vary')); + $this->assertEquals(['Origin'], $response->headers->all('Vary')); } /** @@ -268,7 +268,7 @@ public function it_appends_an_existing_vary_header() $response = $app->handle($request); $this->assertTrue($response->headers->has('Vary')); - $this->assertEquals('Content-Type, Origin', $response->headers->get('Vary')); + $this->assertEquals(['Content-Type', 'Origin'], $response->headers->all('Vary')); } /** @@ -302,7 +302,7 @@ public function it_returns_access_control_headers_on_cors_request_with_pattern_o $this->assertTrue($response->headers->has('Access-Control-Allow-Origin')); $this->assertEquals('http://localhost', $response->headers->get('Access-Control-Allow-Origin')); $this->assertTrue($response->headers->has('Vary')); - $this->assertEquals('Origin', $response->headers->get('Vary')); + $this->assertEquals(['Origin'], $response->headers->all('Vary')); } /** @@ -316,7 +316,7 @@ public function it_adds_vary_headers_on_preflight_non_preflight_options() $response = $app->handle($request); - $this->assertEquals('Access-Control-Request-Method', $response->headers->get('Vary')); + $this->assertEquals(['Access-Control-Request-Method'], $response->headers->all('Vary')); } /** @@ -331,7 +331,7 @@ public function it_returns_access_control_headers_on_valid_preflight_request() $this->assertTrue($response->headers->has('Access-Control-Allow-Origin')); $this->assertEquals('http://localhost', $response->headers->get('Access-Control-Allow-Origin')); - $this->assertEquals('Access-Control-Request-Method', $response->headers->get('Vary')); + $this->assertEquals(['Access-Control-Request-Method'], $response->headers->all('Vary')); } /** @@ -397,7 +397,7 @@ public function it_returns_valid_preflight_request_with_allow_methods_all() $this->assertTrue($response->headers->has('Access-Control-Allow-Methods')); // it will return the Access-Control-Request-Method pass in the request $this->assertEquals('GET', $response->headers->get('Access-Control-Allow-Methods')); - $this->assertEquals('Access-Control-Request-Method', $response->headers->get('Vary')); + $this->assertEquals(['Access-Control-Request-Method'], $response->headers->all('Vary')); } @@ -415,7 +415,7 @@ public function it_returns_valid_preflight_request_with_allow_methods_all_creden // it will return the Access-Control-Request-Method pass in the request $this->assertEquals('GET', $response->headers->get('Access-Control-Allow-Methods')); // it should vary this header - $this->assertEquals('Access-Control-Request-Method', $response->headers->get('Vary')); + $this->assertEquals(['Access-Control-Request-Method'], $response->headers->all('Vary')); } /** @@ -533,6 +533,28 @@ public function it_doesnt_set_access_control_allow_origin_without_origin() $this->assertFalse($response->headers->has('Access-Control-Allow-Origin')); } + /** + * @test + */ + public function it_doesnt_lose_preexisting_vary_header_values() + { + $app = $this->createStackedApp([ + 'allowedOrigins' => ['*'], + 'supportsCredentials' => true, + ], [ + 'Vary' => [ + 'X-Custom-Header-1', + 'X-Custom-Header-2' + ] + ]); + $request = $this->createValidActualRequest(); + + $response = $app->handle($request); + + $this->assertTrue($response->headers->has('Vary')); + $this->assertEquals(['X-Custom-Header-1', 'X-Custom-Header-2', 'Origin'], $response->headers->all('Vary')); + } + private function createValidActualRequest() { $request = new Request();