diff --git a/src/Proxy.php b/src/Proxy.php index e90a67c..5398983 100644 --- a/src/Proxy.php +++ b/src/Proxy.php @@ -68,25 +68,29 @@ public function response(string $file, ?Options $options = null, array $headers $newResponse->setContent($response->getContent()); - $copiedHeaders = [ + $standardHeaders = [ 'last-modified', 'expires', 'etag', 'cache-control', - 'content-encoding', 'content-type', - 'content-length', 'vary', - 'x-content-type-options', - 'x-dominant-color', ]; - foreach ($copiedHeaders as $header) { - if (false === \array_key_exists($header, $response->getHeaders())) { + $responseHeaders = $response->getHeaders(); + + foreach ($standardHeaders as $header) { + if (false === \array_key_exists($header, $responseHeaders)) { continue; } - $newResponse->headers->set($header, $response->getHeaders()[$header]); + $newResponse->headers->set($header, $responseHeaders[$header]); + } + + foreach ($responseHeaders as $header => $values) { + if (true === str_starts_with($header, 'x-')) { + $newResponse->headers->set($header, $values); + } } $newResponse->headers->set(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER, 'true'); diff --git a/tests/ProxyTest.php b/tests/ProxyTest.php index 98b5c72..0b329d3 100644 --- a/tests/ProxyTest.php +++ b/tests/ProxyTest.php @@ -75,6 +75,7 @@ public function testResponseFetchesCdnAndCopiesWhitelistedHeaders(): void 'vary' => ['Accept'], 'x-content-type-options' => ['nosniff'], 'x-dominant-color' => ['#ff0000'], + 'x-custom-header' => ['custom-value'], ], ] ) @@ -89,6 +90,7 @@ public function testResponseFetchesCdnAndCopiesWhitelistedHeaders(): void self::assertSame('"abc123"', $response->headers->get('etag')); self::assertSame('nosniff', $response->headers->get('x-content-type-options')); self::assertSame('#ff0000', $response->headers->get('x-dominant-color')); + self::assertSame('custom-value', $response->headers->get('x-custom-header')); } public function testResponseSetsNoCacheControlHeader(): void @@ -99,20 +101,36 @@ public function testResponseSetsNoCacheControlHeader(): void self::assertSame('true', $response->headers->get(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER)); } - public function testResponseIgnoresNonWhitelistedHeaders(): void + public function testResponseIgnoresNonXNonWhitelistedHeaders(): void { $client = new MockHttpClient( new MockResponse( 'content', [ - 'response_headers' => ['x-secret' => ['value']], + 'response_headers' => ['server' => ['Apache']], ] ) ); $response = $this->makeProxy($client)->response('image.jpg'); - self::assertFalse($response->headers->has('x-secret')); + self::assertFalse($response->headers->has('server')); + } + + public function testResponseForwardsAllXPrefixedHeaders(): void + { + $client = new MockHttpClient( + new MockResponse( + 'content', + [ + 'response_headers' => ['x-my-custom' => ['my-value']], + ] + ) + ); + + $response = $this->makeProxy($client)->response('image.jpg'); + + self::assertSame('my-value', $response->headers->get('x-my-custom')); } public function testResponseNormalizesFileStrippingLeadingSlash(): void