From 799de22d4d7a2729416aeddecff48eb0e1714a33 Mon Sep 17 00:00:00 2001 From: Virgil Date: Wed, 1 Apr 2026 23:51:05 +0000 Subject: [PATCH] fix(api): preserve sunset middleware headers Co-Authored-By: Virgil --- .../src/Front/Api/Middleware/ApiSunset.php | 11 +++++---- src/php/tests/Feature/ApiSunsetTest.php | 24 +++++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/php/src/Front/Api/Middleware/ApiSunset.php b/src/php/src/Front/Api/Middleware/ApiSunset.php index fbf39d1..8ec0829 100644 --- a/src/php/src/Front/Api/Middleware/ApiSunset.php +++ b/src/php/src/Front/Api/Middleware/ApiSunset.php @@ -22,7 +22,8 @@ use Symfony\Component\HttpFoundation\Response; * API Sunset Middleware. * * Adds deprecation headers to a route and optionally advertises a sunset - * date and successor endpoint. + * date and successor endpoint. Existing header values are preserved so + * downstream middleware and handlers can keep their own warning metadata. */ class ApiSunset { @@ -41,14 +42,14 @@ class ApiSunset return $response; } - $response->headers->set('Deprecation', 'true'); + $response->headers->set('Deprecation', 'true', false); if ($sunsetDate !== '') { - $response->headers->set('Sunset', $this->formatSunsetDate($sunsetDate)); + $response->headers->set('Sunset', $this->formatSunsetDate($sunsetDate), false); } if ($replacement !== null && $replacement !== '') { - $response->headers->set('Link', sprintf('<%s>; rel="successor-version"', $replacement)); + $response->headers->set('Link', sprintf('<%s>; rel="successor-version"', $replacement), false); } $warning = 'This endpoint is deprecated.'; @@ -56,7 +57,7 @@ class ApiSunset $warning = "This endpoint is deprecated and will be removed on {$sunsetDate}."; } - $response->headers->set('X-API-Warn', $warning); + $response->headers->set('X-API-Warn', $warning, false); return $response; } diff --git a/src/php/tests/Feature/ApiSunsetTest.php b/src/php/tests/Feature/ApiSunsetTest.php index 33bdb5d..50255db 100644 --- a/src/php/tests/Feature/ApiSunsetTest.php +++ b/src/php/tests/Feature/ApiSunsetTest.php @@ -35,6 +35,30 @@ it('adds a replacement link without a sunset date', function () { expect($response->headers->get('X-API-Warn'))->toBe('This endpoint is deprecated.'); }); +it('preserves existing deprecation headers while appending sunset metadata', function () { + Config::set('api.headers.include_deprecation', true); + + $middleware = new ApiSunset(); + $request = Request::create('/legacy-endpoint', 'GET'); + + $response = $middleware->handle($request, function () { + $response = new Response('OK'); + $response->headers->set('Deprecation', 'false'); + $response->headers->set('Sunset', 'Wed, 01 Jan 2025 00:00:00 GMT'); + $response->headers->set('Link', '; rel="help"'); + $response->headers->set('X-API-Warn', 'Existing warning'); + + return $response; + }, '2025-06-01', '/api/v2/users'); + + expect($response->headers->all('Deprecation'))->toHaveCount(2); + expect($response->headers->all('Sunset'))->toHaveCount(2); + expect($response->headers->all('Link'))->toHaveCount(2); + expect($response->headers->all('X-API-Warn'))->toHaveCount(2); + expect($response->headers->all('Link'))->toContain('; rel="help"'); + expect($response->headers->all('Link'))->toContain('; rel="successor-version"'); +}); + it('formats the sunset date and keeps the replacement link', function () { Config::set('api.headers.include_deprecation', true);