From 09cd1a5fe22d98b6fe7839932ab77e65f4a71a1f Mon Sep 17 00:00:00 2001 From: Agent Zero Date: Mon, 27 Jul 2026 01:08:51 +0200 Subject: [PATCH] fix: UploadFile ForwardRef error + WebSocket 403 CSRF block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. plugin_error_handler.py: Remove return_annotation from copied signature to prevent FastAPI ForwardRef('UploadFile') resolution failure on routes with file upload endpoints (dms, calendar, mail, kommunikation, ai_assistant) 2. middleware.py: Skip CSRF check for WebSocket upgrade requests WebSocket connections use GET with upgrade header — should not be blocked by CSRF middleware --- app/core/middleware.py | 4 ++++ app/core/plugin_error_handler.py | 12 ++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/app/core/middleware.py b/app/core/middleware.py index 1b525ee..990ea58 100644 --- a/app/core/middleware.py +++ b/app/core/middleware.py @@ -69,6 +69,10 @@ class CSRFMiddleware(BaseHTTPMiddleware): UNSAFE_METHODS = {"POST", "PATCH", "PUT", "DELETE"} async def dispatch(self, request: Request, call_next): + # Skip WebSocket upgrade requests — they use GET and are handled separately + if request.headers.get("upgrade", "").lower() == "websocket": + return await call_next(request) + if request.method in self.UNSAFE_METHODS: # 1. Origin header check origin = request.headers.get("origin") diff --git a/app/core/plugin_error_handler.py b/app/core/plugin_error_handler.py index 64546bc..f1bb496 100644 --- a/app/core/plugin_error_handler.py +++ b/app/core/plugin_error_handler.py @@ -13,7 +13,7 @@ def wrap_plugin_route(handler): Copies the original handler's signature so FastAPI sees the correct parameters (path params, query params, body, etc.) instead of *args/**kwargs. - Avoids copying __annotations__ to prevent ForwardRef('UploadFile') issues. + Removes return annotation to prevent ForwardRef('UploadFile') resolution issues. """ @functools.wraps(handler) async def wrapper(*args, **kwargs): @@ -28,13 +28,17 @@ def wrap_plugin_route(handler): # Remove annotations that cause ForwardRef resolution issues wrapper.__annotations__ = {} # Remove __wrapped__ so FastAPI doesn't try to resolve the original signature - # (which may have ForwardRef('UploadFile') that can't be resolved) if hasattr(wrapper, '__wrapped__'): delattr(wrapper, '__wrapped__') - # Copy the signature from the original handler so FastAPI sees correct params + # Copy the signature from the original handler but remove return annotation try: orig_sig = inspect.signature(handler) - wrapper.__signature__ = orig_sig + # Create new signature without return annotation + new_params = list(orig_sig.parameters.values()) + wrapper.__signature__ = orig_sig.replace( + parameters=new_params, + return_annotation=inspect.Signature.empty, + ) except (ValueError, TypeError): pass return wrapper