Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 23 additions & 29 deletions api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@
JSONResponse,
PlainTextResponse,
)
from fastapi.routing import APIRoute, APIRouter
from fastapi.security import OAuth2PasswordRequestForm
from fastapi_pagination import add_pagination
from fastapi_users import FastAPIUsers
from fastapi_versioning import VersionedFastAPI
from jose import jwt
from jose.exceptions import JWTError
from kernelci.api.models import (
Expand Down Expand Up @@ -2300,12 +2300,19 @@ async def purge_handler(
return await purge_old_nodes(age_days=days, batch_size=batch_size)


versioned_app = VersionedFastAPI(
app,
version_format="{major}",
prefix_format="/v{major}",
enable_latest=True,
default_version=(0, 0),
# Build versioned app using include_router instead of fastapi-versioning.
# VersionedFastAPI (fastapi-versioning==0.10.0) is incompatible with
# FastAPI >= 0.118.0: it transplants route objects by directly appending
# to sub-app router.routes, which bypasses FastAPI's request_response
# wrapper and causes 'fastapi_inner_astack not found in request scope'.
# Using include_router re-creates APIRoute objects properly.
_api_router = APIRouter()
for _route in app.routes:
if isinstance(_route, APIRoute):
_api_router.routes.append(_route)

versioned_app = FastAPI(
title=app.title,
on_startup=[
pubsub_startup,
create_indexes,
Expand All @@ -2315,9 +2322,10 @@ async def purge_handler(
],
)

versioned_app.include_router(_api_router, prefix="/v0")
versioned_app.include_router(_api_router, prefix="/latest")


# traceback_exception_handler is a global exception handler that will be
# triggered for all exceptions that are not handled by specific exception
def traceback_exception_handler(request: Request, exc: Exception):
"""Global exception handler to print traceback"""
print(f"Exception: {exc}")
Expand All @@ -2328,29 +2336,15 @@ def traceback_exception_handler(request: Request, exc: Exception):
)


# Workaround to use global exception handlers for versioned API.
# The issue has already been reported here:
# https://github.com/DeanWay/fastapi-versioning/issues/30
for sub_app in versioned_app.routes:
if hasattr(sub_app.app, "add_exception_handler"):
sub_app.app.add_exception_handler(
ValueError, value_error_exception_handler
)
sub_app.app.add_exception_handler(
errors.InvalidId, invalid_id_exception_handler
)
# print traceback for all other exceptions
sub_app.app.add_exception_handler(
Exception, traceback_exception_handler
)
versioned_app.add_exception_handler(ValueError, value_error_exception_handler)
versioned_app.add_exception_handler(
errors.InvalidId, invalid_id_exception_handler
)
versioned_app.add_exception_handler(Exception, traceback_exception_handler)


class VersionRedirectMiddleware:
"""Pure ASGI middleware to redirect requests with version prefix.

Avoids BaseHTTPMiddleware which can corrupt the request scope
(fastapi_inner_astack not found in request scope).
"""
"""Pure ASGI middleware to redirect requests with version prefix."""

def __init__(self, app):
self.app = app
Expand Down
9 changes: 4 additions & 5 deletions docker/api/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
cloudevents==1.9.0
beanie == 1.29.0
fastapi[all]==0.115.0
cloudevents==2.0.0
beanie==1.29.0
fastapi[all]==0.135.3
fastapi-pagination==0.12.30
fastapi-users[beanie, oauth]==15.0.2
fastapi-versioning==0.10.0
fastapi-users[beanie, oauth]==15.0.5
MarkupSafe==2.0.1
motor==3.6.0
pymongo==4.9.0
Expand Down
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ dependencies = [
"fastapi[all] == 0.135.3",
"fastapi-pagination == 0.12.30",
"fastapi-users[beanie, oauth] == 15.0.5",
"fastapi-versioning == 0.10.0",
"MarkupSafe == 2.0.1",
"motor == 3.6.0",
"pymongo == 4.9.0",
Expand Down
Loading