Multiple APIs Versioning Example¶
The example demonstrates two independent versioned APIs (public and private) inside one application: each aggregating sub-application gets its own VersioningMiddleware, and their versions do not affect each other.
The example code is on GitHub.
Run it locally
The example contains the following code:
from fastapi import Depends, FastAPI, middleware
from fastapi_easy_versioning import (
VersioningMiddleware,
versioning,
)
app = FastAPI()
public_app = FastAPI(middleware=[middleware.Middleware(VersioningMiddleware)])
public_v1 = FastAPI(api_version=1)
public_v2 = FastAPI(api_version=2)
private_app = FastAPI(middleware=[middleware.Middleware(VersioningMiddleware)])
private_v1 = FastAPI(api_version=1)
private_v2 = FastAPI(api_version=2)
app.mount("/api/public", public_app)
public_app.mount("/v1", public_v1)
public_app.mount("/v2", public_v2)
app.mount("/api/private", private_app)
private_app.mount("/v1", private_v1)
private_app.mount("/v2", private_v2)
@private_v1.get("/endpoint", dependencies=[Depends(versioning(until=1))])
def private_endpoint() -> str:
return "I'm v1 private endpoint"
@private_v1.get("/another-endpoint", dependencies=[Depends(versioning())])
def private_another_endpoint() -> str:
return "I'm v1 private another endpoint"
@private_v2.get("/endpoint", dependencies=[Depends(versioning())])
def private_endpoint_v2() -> str:
return "I'm v2 private endpoint"
@public_v1.get("/endpoint", dependencies=[Depends(versioning(until=1))])
def public_endpoint() -> str:
return "I'm v1 public endpoint"
@public_v1.get("/another-endpoint", dependencies=[Depends(versioning())])
def public_another_endpoint() -> str:
return "I'm v1 public another endpoint"
@public_v2.get("/endpoint", dependencies=[Depends(versioning())])
def public_endpoint_v2() -> str:
return "I'm v2 public endpoint"
This code creates two independent versioned APIs: public and private. Each has two versions (v1 and v2). Swagger documentation for them is available at:
- Public API v1: http://127.0.0.1:8000/api/public/v1/docs
- Public API v2: http://127.0.0.1:8000/api/public/v2/docs
- Private API v1: http://127.0.0.1:8000/api/private/v1/docs
- Private API v2: http://127.0.0.1:8000/api/private/v2/docs
The resulting structure is as follows:
- In the public API:
/endpointis available only in version v1 (withuntil=1restriction)/another-endpointis available in all versions (starting from v1)-
in v2, a new
/endpointis added, which overrides the version from v1 -
In the private API:
/endpointis available only in version v1 (withuntil=1restriction)/another-endpointis available in all versions (starting from v1)- in v2, a new
/endpointis added, which overrides the version from v1
Both APIs operate independently thanks to the use of separate VersioningMiddleware instances.
graph TD
A[Endpoint Availability] --> B[Public API]
A --> C[Private API]
B --> B1[v1<br/>api_version=1]
B --> B2[v2<br/>api_version=2]
C --> C1[v1<br/>api_version=1]
C --> C2[v2<br/>api_version=2]
B1 --> B11["/endpoint ✓<br/>(until=1)"]:::available
B1 --> B12["/another-endpoint ✓"]:::available
B2 --> B21["/endpoint ✓<br/>(from v2)"]:::available
B2 --> B22["/another-endpoint ✓"]:::available
C1 --> C11["/endpoint ✓<br/>(until=1)"]:::available
C1 --> C12["/another-endpoint ✓"]:::available
C2 --> C21["/endpoint ✓<br/>(from v2)"]:::available
C2 --> C22["/another-endpoint ✓"]:::available
classDef available fill:#90EE90,stroke:#333,color:#1b1b1b