diff --git a/backend/open_webui/utils/asgi_middleware.py b/backend/open_webui/utils/asgi_middleware.py index 89154b6103..7189bfcad8 100644 --- a/backend/open_webui/utils/asgi_middleware.py +++ b/backend/open_webui/utils/asgi_middleware.py @@ -227,7 +227,15 @@ class RedirectMiddleware: return path = scope.get('path', '') - query_string = scope.get('query_string', b'').decode('latin-1', errors='replace') + raw_query = scope.get('query_string', b'') + # This middleware only acts on /watch?v= and ?shared= URLs; skip the + # decode + parse_qs work for every other GET. (A false positive on the + # substring check just falls through to the full parse below.) + if not (path.endswith('/watch') or b'shared' in raw_query): + await self.app(scope, receive, send) + return + + query_string = raw_query.decode('latin-1', errors='replace') query_params = parse_qs(query_string) redirect_params: dict[str, str] = {} diff --git a/backend/open_webui/utils/security_headers.py b/backend/open_webui/utils/security_headers.py index 090abeea33..c6cbbce2ba 100644 --- a/backend/open_webui/utils/security_headers.py +++ b/backend/open_webui/utils/security_headers.py @@ -15,16 +15,19 @@ class SecurityHeadersMiddleware: def __init__(self, app: ASGIApp) -> None: self.app = app + # Headers derive only from env vars, which are static for the process + # lifetime — compute them once instead of per response. + self._headers = list(set_security_headers().items()) async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: - if scope['type'] != 'http': + if scope['type'] != 'http' or not self._headers: await self.app(scope, receive, send) return async def send_with_security_headers(message: Message) -> None: if message['type'] == 'http.response.start': headers = MutableHeaders(scope=message) - for key, value in set_security_headers().items(): + for key, value in self._headers: headers[key] = value await send(message)