Skip to content

feat(api): implement extensible uri and header versioning (#92) - #224

Merged
mijinummi merged 1 commit into
MD-Creative-Production:mainfrom
rabsqueen:feat/api-versioning-strategy-92
Aug 24, 2026
Merged

feat(api): implement extensible uri and header versioning (#92)#224
mijinummi merged 1 commit into
MD-Creative-Production:mainfrom
rabsqueen:feat/api-versioning-strategy-92

Conversation

@rabsqueen

@rabsqueen rabsqueen commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements the API versioning architecture defined in #92, introducing a centralized, extensible version-resolution layer that supports both URI-based and HTTP-header-based version negotiation.

The implementation separates version dispatching from controller/domain logic, allowing multiple API versions to run concurrently while preserving backward compatibility with the existing V1 API.

What Changed

API Version Resolution

  • Added a centralized versionResolver middleware.

  • Added Strategy Pattern-based version resolution.

  • Supports version selection through:

    • URI prefixes: /api/v1/..., /api/v2/...
    • X-API-Version header
    • Vendor media types such as application/vnd.company.v2+json
  • Added fallback to the configured default version (V1) when no explicit version is provided.

  • Added validation for unsupported/invalid API versions.

Versioned Routing

  • Added version-specific API namespaces:

    • src/api/v1/
    • src/api/v2/
  • Introduced reusable createVersionedRouter() route factory.

  • Decoupled version routing from domain/controller logic.

  • Maintained strict separation between V1 and V2 controllers, DTOs, and response transformations.

Deprecation Management

  • Added centralized deprecation handling for legacy API routes.

  • Deprecated endpoints now return standardized response metadata:

    • Deprecation: true
    • Sunset: Sun, 31 Dec 2028 23:59:59 GMT
    • Link: <...>; rel="successor-version"

This allows clients to identify deprecated endpoints and migrate to their successor versions without embedding deprecation logic inside individual controllers.

OpenAPI Documentation

  • Added version-scoped OpenAPI documentation.

  • Added independent specifications for:

    • /docs/v1/swagger.json
    • /docs/v2/swagger.json
  • Added version-specific Swagger UI:

    • /docs/v1
    • /docs/v2

Version Resolution Precedence

The resolver follows a deterministic precedence order:

URI Version
    ↓
HTTP Header Version
    ↓
Default Version (V1)

For example:

GET /api/v2/resources
X-API-Version: 1

The URI version takes precedence and resolves the request against V2.

When no URI version is provided:

GET /api/resources
X-API-Version: 2

the request resolves against V2.

When neither mechanism is provided:

GET /api/resources

the request falls back to V1.

Backward Compatibility

Existing unversioned endpoints continue to execute within the V1 context.

This preserves existing client integrations while allowing V2 endpoints to be introduced incrementally without forcing synchronized client migrations.

Error Handling

Unsupported or invalid version requests are explicitly rejected rather than silently routed to an unintended controller.

The implementation covers:

  • Unsupported API versions.
  • Invalid version header values.
  • URI/header version mismatch scenarios.
  • Missing version information.
  • Default-version fallback behavior.

Depending on the validation path, invalid negotiation requests return 400 Bad Request or 406 Not Acceptable.

Testing

Added/updated unit and integration coverage for:

  • URI-based version resolution.
  • X-API-Version header resolution.
  • Vendor media-type version resolution.
  • URI-over-header precedence.
  • Default V1 fallback.
  • Unsupported version handling.
  • Invalid version values.
  • Version mismatch behavior.
  • V1/V2 route isolation.
  • Deprecation response headers.
  • OpenAPI version-specific generation.

Acceptance Criteria

  • URI-based version resolution is supported.
  • X-API-Version header resolution is supported.
  • Vendor media-type version negotiation is supported.
  • URI resolution takes precedence over header resolution.
  • Unversioned requests fall back to V1.
  • V1 and V2 controllers/DTOs remain isolated.
  • Reusable versioned route factory is implemented.
  • Legacy routes expose deprecation/sunset metadata.
  • Version-specific OpenAPI specifications are available.
  • Version-specific Swagger UI is available.
  • Invalid/unsupported versions are rejected.
  • Unit and integration tests cover resolution and fallback behavior.
  • Existing V1 integrations remain backward compatible.

Review Notes

Please pay particular attention to:

  1. Version resolution precedence — URI → header → default.
  2. Controller isolation — version-specific response behavior should not leak across V1/V2.
  3. Fallback behavior — existing unversioned clients must continue resolving to V1.
  4. Invalid version handling — unsupported versions should fail explicitly rather than silently falling back.
  5. Deprecation headers — verify that legacy endpoints consistently expose the expected metadata.
  6. OpenAPI separation — V1 and V2 documentation should accurately represent their respective contracts.

Related Issue

Closes #92

Suggested Test Commands

npm test
npm run test:e2e
npm run build

@mijinummi
mijinummi merged commit 76ca6a7 into MD-Creative-Production:main Aug 24, 2026
5 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

# [FEAT] Implement Extensible URI/Header API Versioning Architecture with Strategy-Pattern Routing

2 participants