Versioning Dependency
The versioning() factory is how an endpoint is marked as versioned. It returns a VersioningSupport instance suitable for Depends(). An endpoint without this dependency does not participate in versioning and stays only in the version where it is declared.
until Semantics
versioning(*, until: int | None = None) controls the range of versions the endpoint is available in:
| Value | Behavior |
|---|---|
until=None (default) |
The endpoint is available from its own version and in all subsequent ones |
until=N |
The endpoint is available from its own version up to and including version N |
Additional rules:
- If a route has several
versioningdependencies (for example, one on the router and one on the endpoint), the minimum of the declareduntilvalues wins. - An
untillower than the version the endpoint is declared in is a contradiction: the library emits aUserWarning, and the endpoint stays available in its own version but is inherited nowhere.
Where to Attach It
The dependency is accepted everywhere FastAPI accepts dependencies:
from fastapi import APIRouter, Depends, FastAPI
from fastapi_easy_versioning import versioning
v1_app = FastAPI(api_version=1)
# On an endpoint — via the decorator
@v1_app.get('/endpoint', dependencies=[Depends(versioning())])
def endpoint() -> None: ...
# Via add_api_route
v1_app.add_api_route('/added', endpoint, dependencies=[Depends(versioning(until=2))])
# On a whole router — every endpoint of the router is versioned
router = APIRouter(dependencies=[Depends(versioning())])
@router.get('/router-endpoint')
def router_endpoint() -> None: ...
v1_app.include_router(router)
Reading Metadata Inside the Endpoint
The dependency can be injected into an endpoint — it then returns a VersionInfo named tuple with the route's resolved versioning configuration:
origin— the version the endpoint is declared in;until— the last version the endpoint is available in. Ifuntilwas not set explicitly, this is the latest existing API version.
from typing import Annotated
from fastapi import Depends, FastAPI
from fastapi_easy_versioning import VersionInfo, versioning
v1_app = FastAPI(api_version=1)
@v1_app.get('/endpoint')
def endpoint(version: Annotated[VersionInfo, Depends(versioning())]) -> str:
return f"Available from version {version.origin} to version {version.until}"
Injection also works in WebSocket endpoints:
from typing import Annotated
from fastapi import Depends, FastAPI, WebSocket
from fastapi_easy_versioning import VersionInfo, versioning
v1_app = FastAPI(api_version=1)
@v1_app.websocket('/ws')
async def ws_endpoint(
websocket: WebSocket,
version: Annotated[VersionInfo, Depends(versioning())],
) -> None:
await websocket.accept()
await websocket.send_text(f"Available since version {version.origin}")
await websocket.close()
Diagnostics
If versioning was not initialized, injecting VersionInfo raises a RuntimeError listing the possible causes:
VersioningMiddlewareis not added to the application that mounts the versions;- the sub-application does not declare
FastAPI(api_version=<int>); - the route was registered after the first request and
rebuild_versioningwas not called.