""" API versioning middleware. NOTE: This module is currently not used. To enable API versioning: 1. Import VersionMiddleware in main.py 2. Add it to the app middleware stack Example usage: from app.middleware.versioning import APIVersionMiddleware app.add_middleware(APIVersionMiddleware) This middleware adds X-API-Version header to responses based on the version extracted from the URL path (e.g., /v1/... or /v2/...). """ from __future__ import annotations from datetime import datetime from fastapi import Request from starlette.middleware.base import BaseHTTPMiddleware class APIVersionMiddleware(BaseHTTPMiddleware): """API versioning middleware.""" # API version definitions VERSIONS = { "v1": { "status": "stable", "deprecated": False, "sunset_date": None, "release_date": "2026-06-17", }, "v2": { "status": "development", "deprecated": False, "sunset_date": None, "release_date": None, }, } async def dispatch(self, request: Request, call_next): # Extract version from URL path version = self._extract_version(request.url.path) # Process request response = await call_next(request) # Add version header if version: response.headers["X-API-Version"] = version # Add deprecation headers if version is deprecated version_info = self.VERSIONS.get(version, {}) if version_info.get("deprecated"): response.headers["X-API-Deprecated"] = "true" sunset_date = version_info.get("sunset_date") if sunset_date: response.headers["X-API-Sunset-Date"] = sunset_date response.headers["X-API-Deprecation-Info"] = f"https://docs.xiaoxia-saas.com/api/deprecation/{version}" return response def _extract_version(self, path: str) -> str | None: """Extract version from URL path.""" parts = path.split("/") for part in parts: if part.startswith("v") and part[1:].isdigit(): return part return None class VersionNotFoundMiddleware(BaseHTTPMiddleware): """Middleware to reject requests for unsupported API versions.""" UNSUPPORTED_VERSIONS = [] # Add deprecated versions here async def dispatch(self, request: Request, call_next): version = self._extract_version(request.url.path) if version in self.UNSUPPORTED_VERSIONS: from fastapi.responses import JSONResponse return JSONResponse( status_code=410, content={ "error": { "code": "API_VERSION_SUNSET", "message": f"API {version} has been sunset and is no longer available", "sunset_date": "2028-07-01", "migration_guide": f"https://docs.xiaoxia-saas.com/api/migration/{version}", } }, ) return await call_next(request) def _extract_version(self, path: str) -> str | None: """Extract version from URL path.""" parts = path.split("/") for part in parts: if part.startswith("v") and part[1:].isdigit(): return part return None