fix(api): preserve sunset middleware headers

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-01 23:51:05 +00:00
parent 159f8d3b9f
commit 799de22d4d
2 changed files with 30 additions and 5 deletions

View file

@ -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;
}

View file

@ -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', '<https://example.com/docs>; 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('<https://example.com/docs>; rel="help"');
expect($response->headers->all('Link'))->toContain('</api/v2/users>; rel="successor-version"');
});
it('formats the sunset date and keeps the replacement link', function () {
Config::set('api.headers.include_deprecation', true);