Closed joshimai closed 1 week ago
@vincentsarago this was causing issues with the custom error handling that we discussed yesterday.
I'm not sure exactly the issue, but this code: https://github.com/stac-utils/stac-fastapi/blob/main/stac_fastapi/api/stac_fastapi/api/app.py#L442-L445 proxies the starlette add_middleware call https://github.com/encode/starlette/blob/master/starlette/applications.py#L134-L142, but calls build_middleware_stack
every time a middleware is added. Seems like that should be explicitly disallowed by the raise RuntimeError("Cannot add middleware after an application has started")
in the starlette call, though I haven't seen this exception.
This was causing the custom exception handlers to not be properly registered with the starlette exception handling middleware.
Workaround now is to set the middleware explicitly in the FastApi constructor d to pass middlewares=[]
into StacApi constructor to avoid triggering this code.
🤔 so just to be clear you're using the same app
to initialize two different StacApi
objects. Each StacApi initialization will modify the app
by adding middleware to the app middleware stack.
To me it doesn't sound like passing the same app to two different StacApi object is just not a good usage.
The StacApi init will modify the app, so by definition you shouldn't expect to be able to use the app
after the StacAPI init.
We're seeing just the middleware problem but you'll also register the endpoints twice.
This will result in the first StacApi object to be useless and it will be pretty dangerous do to something with it
To clarify, we are not actually initializing two StacApis but rather demonstrating the issue we saw with middlewares. I updated the sample code to be a better representation of our problem.
alright I see what's going on!
in StacAPI we do:
The issue is then we have app.middleware_stack
created instead of letting starlette create it on the first app call
The fix will be to remove https://github.com/stac-utils/stac-fastapi/blob/f311dc620d2a11df397f8d95c17e15483b9e302c/stac_fastapi/api/stac_fastapi/api/app.py#L445
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:
Steps to Reproduce:
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:
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.