feat(api): honour header toggles for versioning
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
ccfbe57faf
commit
cebad9b77b
4 changed files with 92 additions and 9 deletions
|
|
@ -37,6 +37,10 @@ class ApiSunset
|
|||
/** @var Response $response */
|
||||
$response = $next($request);
|
||||
|
||||
if (! (bool) config('api.headers.include_deprecation', true)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$response->headers->set('Deprecation', 'true');
|
||||
|
||||
if ($sunsetDate !== '') {
|
||||
|
|
|
|||
|
|
@ -105,11 +105,16 @@ class ApiVersion
|
|||
/** @var Response $response */
|
||||
$response = $next($request);
|
||||
|
||||
// Add version header to response
|
||||
$response->headers->set('X-API-Version', (string) $version);
|
||||
$includeVersionHeader = (bool) config('api.headers.include_version', true);
|
||||
$includeDeprecationHeaders = (bool) config('api.headers.include_deprecation', true);
|
||||
|
||||
// Add version header to response when enabled
|
||||
if ($includeVersionHeader) {
|
||||
$response->headers->set('X-API-Version', (string) $version);
|
||||
}
|
||||
|
||||
// Add deprecation headers if applicable
|
||||
if (in_array($version, $deprecated, true)) {
|
||||
if ($includeDeprecationHeaders && in_array($version, $deprecated, true)) {
|
||||
$response->headers->set('Deprecation', 'true');
|
||||
$response->headers->set('X-API-Warn', "API version {$version} is deprecated. Please upgrade to v{$current}.");
|
||||
|
||||
|
|
@ -217,6 +222,12 @@ class ApiVersion
|
|||
*/
|
||||
protected function unsupportedVersion(int $requested, array $supported, int $current): Response
|
||||
{
|
||||
$headers = [];
|
||||
|
||||
if ((bool) config('api.headers.include_version', true)) {
|
||||
$headers['X-API-Version'] = (string) $current;
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'error' => 'unsupported_api_version',
|
||||
'message' => "API version {$requested} is not supported.",
|
||||
|
|
@ -224,9 +235,7 @@ class ApiVersion
|
|||
'supported_versions' => $supported,
|
||||
'current_version' => $current,
|
||||
'hint' => 'Use Accept-Version header or URL prefix (e.g., /api/v1/) to specify version.',
|
||||
], 400, [
|
||||
'X-API-Version' => (string) $current,
|
||||
]);
|
||||
], 400, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -234,13 +243,17 @@ class ApiVersion
|
|||
*/
|
||||
protected function versionTooLow(int $requested, int $required): Response
|
||||
{
|
||||
$headers = [];
|
||||
|
||||
if ((bool) config('api.headers.include_version', true)) {
|
||||
$headers['X-API-Version'] = (string) $requested;
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'error' => 'api_version_too_low',
|
||||
'message' => "This endpoint requires API version {$required} or higher.",
|
||||
'requested_version' => $requested,
|
||||
'minimum_version' => $required,
|
||||
], 400, [
|
||||
'X-API-Version' => (string) $requested,
|
||||
]);
|
||||
], 400, $headers);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,12 @@ declare(strict_types=1);
|
|||
|
||||
use Core\Front\Api\Middleware\ApiSunset;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
it('adds deprecation headers without a sunset date', function () {
|
||||
Config::set('api.headers.include_deprecation', true);
|
||||
|
||||
$middleware = new ApiSunset();
|
||||
$request = Request::create('/legacy-endpoint', 'GET');
|
||||
|
||||
|
|
@ -19,6 +22,8 @@ it('adds deprecation headers without a sunset date', function () {
|
|||
});
|
||||
|
||||
it('adds a replacement link without a sunset date', function () {
|
||||
Config::set('api.headers.include_deprecation', true);
|
||||
|
||||
$middleware = new ApiSunset();
|
||||
$request = Request::create('/old-endpoint', 'GET');
|
||||
|
||||
|
|
@ -31,6 +36,8 @@ it('adds a replacement link without a sunset date', function () {
|
|||
});
|
||||
|
||||
it('formats the sunset date and keeps the replacement link', function () {
|
||||
Config::set('api.headers.include_deprecation', true);
|
||||
|
||||
$middleware = new ApiSunset();
|
||||
$request = Request::create('/legacy-endpoint', 'GET');
|
||||
|
||||
|
|
@ -41,3 +48,17 @@ it('formats the sunset date and keeps the replacement link', function () {
|
|||
expect($response->headers->get('Link'))->toBe('</api/v2/users>; rel="successor-version"');
|
||||
expect($response->headers->get('X-API-Warn'))->toBe('This endpoint is deprecated and will be removed on 2025-06-01.');
|
||||
});
|
||||
|
||||
it('skips deprecation headers when they are disabled in configuration', function () {
|
||||
Config::set('api.headers.include_deprecation', false);
|
||||
|
||||
$middleware = new ApiSunset();
|
||||
$request = Request::create('/legacy-endpoint', 'GET');
|
||||
|
||||
$response = $middleware->handle($request, fn () => new Response('OK'), '2025-06-01', '/api/v2/users');
|
||||
|
||||
expect($response->headers->has('Deprecation'))->toBeFalse();
|
||||
expect($response->headers->has('Sunset'))->toBeFalse();
|
||||
expect($response->headers->has('Link'))->toBeFalse();
|
||||
expect($response->headers->has('X-API-Warn'))->toBeFalse();
|
||||
});
|
||||
|
|
|
|||
45
src/php/tests/Feature/ApiVersionHeadersTest.php
Normal file
45
src/php/tests/Feature/ApiVersionHeadersTest.php
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Core\Front\Api\Middleware\ApiVersion;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
beforeEach(function () {
|
||||
Config::set('api.versioning.default', 1);
|
||||
Config::set('api.versioning.current', 2);
|
||||
Config::set('api.versioning.supported', [1, 2]);
|
||||
Config::set('api.versioning.deprecated', [1]);
|
||||
Config::set('api.versioning.sunset', [
|
||||
1 => '2025-06-01',
|
||||
]);
|
||||
Config::set('api.headers.include_version', true);
|
||||
Config::set('api.headers.include_deprecation', true);
|
||||
});
|
||||
|
||||
it('skips the api version header when it is disabled in configuration', function () {
|
||||
Config::set('api.headers.include_version', false);
|
||||
|
||||
$middleware = new ApiVersion();
|
||||
$request = Request::create('/api/users', 'GET');
|
||||
|
||||
$response = $middleware->handle($request, fn () => new Response('OK'));
|
||||
|
||||
expect($response->headers->has('X-API-Version'))->toBeFalse();
|
||||
});
|
||||
|
||||
it('skips deprecation headers when they are disabled in configuration', function () {
|
||||
Config::set('api.headers.include_deprecation', false);
|
||||
|
||||
$middleware = new ApiVersion();
|
||||
$request = Request::create('/api/v1/users', 'GET');
|
||||
|
||||
$response = $middleware->handle($request, fn () => new Response('OK'));
|
||||
|
||||
expect($response->headers->get('X-API-Version'))->toBe('1');
|
||||
expect($response->headers->has('Deprecation'))->toBeFalse();
|
||||
expect($response->headers->has('Sunset'))->toBeFalse();
|
||||
expect($response->headers->has('X-API-Warn'))->toBeFalse();
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue