Skip to content

Middleware Stack Rebuilt on Each StacApi Initialization #719

Closed
@joshimai

Description

@joshimai

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions