Description
The change in stac-fastapi that proxies app.add_middleware causes the middleware stack to be rebuilt or duplicated every time StacApi is initialized. It duplicates internal business logic from Starlette and now it seems incompatible with the new FastAPI/Starlette (0.110.3/0.37.2) versions. This behavior results in repeated middleware entries in the stack, leading to unintended side effects.
Steps to Reproduce:
Initialize a FastAPI app and add custom middleware.
Initialize StacApi with the FastAPI app.
Observe the middleware stack before and after each StacApi initialization.
Sample Code:
from fastapi import FastAPI, Request
from stac_fastapi.api.app import StacApi
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from stac_fastapi.types.config import ApiSettings
from stac_fastapi.pgstac.core import CoreCrudClient
from stac_fastapi.extensions.core import (
FieldsExtension,
ContextExtension,
QueryExtension,
SortExtension,
)
app = FastAPI()
app.middleware = []
extensions = [FieldsExtension(), ContextExtension(), QueryExtension(), SortExtension()]
PCClient = CoreCrudClient()
settings = ApiSettings()
# First initialization of StacApi
stac_api = StacApi(
app=app,
settings=settings,
extensions=extensions,
client=PCClient,
)
app.middleware = []
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
return JSONResponse(
status_code=400,
content={"customerrordetail": exc.errors(), "body": exc.body},
)
# Test route to trigger RequestValidationError
@app.post("/items/")
async def create_item(item: dict):
return item
Steps to Reproduce:
uvicorn main:app --reload
curl -X POST "http://127.0.0.1:8000/items/" -H "Content-Type: application/json"
Expected Output:
{"customerrordetail":[{"type":"missing","loc":["body"],"msg":"Field required","input":null}],"body":null}
Actual Output:
{"code":"RequestValidationError","description":"[{'type': 'missing', 'loc': ('body',), 'msg': 'Field required', 'input': None}]"}
Sample Code with the workaround:
.....
# no middleware
stac_api = StacApi(
app=app,
settings=settings,
extensions=extensions,
client=PCClient,
middlewares=[],
)
..........
This does return the expected outcome which points to the middleware call causing the custom exception handlers to not be properly registered with the starlette exception handling middleware.