From 96758176cc6cd80a7bf9ba198e5d6cd2ffa39664 Mon Sep 17 00:00:00 2001 From: Athanasios Oikonomou Date: Thu, 10 Jul 2025 22:00:14 +0300 Subject: [PATCH] fix: don't over quote forwarded headers Fix introduced on #15035 is over quoting headers. Eg mails instead of user@example.com shown as user%40example.com Eg names instead of First Last shown as First%20Last Also we are spending some time quoting ids and roles without required. Keep quote only on user name, initially had problem based on the discussion https://github.com/open-webui/open-webui/discussions/14391 Also add space in safe characters, in order remove %20 from names. --- backend/open_webui/retrieval/utils.py | 24 ++++----- backend/open_webui/routers/audio.py | 8 +-- backend/open_webui/routers/images.py | 8 +-- backend/open_webui/routers/ollama.py | 72 +++++++++++++-------------- backend/open_webui/routers/openai.py | 56 ++++++++++----------- 5 files changed, 84 insertions(+), 84 deletions(-) diff --git a/backend/open_webui/retrieval/utils.py b/backend/open_webui/retrieval/utils.py index 71f6390d6b..74d396d25d 100644 --- a/backend/open_webui/retrieval/utils.py +++ b/backend/open_webui/retrieval/utils.py @@ -727,10 +727,10 @@ def generate_openai_batch_embeddings( "Authorization": f"Bearer {key}", **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS and user else {} @@ -776,10 +776,10 @@ def generate_azure_openai_batch_embeddings( "api-key": key, **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS and user else {} @@ -826,10 +826,10 @@ def generate_ollama_batch_embeddings( "Authorization": f"Bearer {key}", **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS else {} diff --git a/backend/open_webui/routers/audio.py b/backend/open_webui/routers/audio.py index cac9c9e5a2..c63ad3bfe7 100644 --- a/backend/open_webui/routers/audio.py +++ b/backend/open_webui/routers/audio.py @@ -345,10 +345,10 @@ async def speech(request: Request, user=Depends(get_verified_user)): "Authorization": f"Bearer {request.app.state.config.TTS_OPENAI_API_KEY}", **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS else {} diff --git a/backend/open_webui/routers/images.py b/backend/open_webui/routers/images.py index 2832a11577..5cd07e3d54 100644 --- a/backend/open_webui/routers/images.py +++ b/backend/open_webui/routers/images.py @@ -499,10 +499,10 @@ async def image_generations( headers["Content-Type"] = "application/json" if ENABLE_FORWARD_USER_INFO_HEADERS: - headers["X-OpenWebUI-User-Name"] = quote(user.name) - headers["X-OpenWebUI-User-Id"] = quote(user.id) - headers["X-OpenWebUI-User-Email"] = quote(user.email) - headers["X-OpenWebUI-User-Role"] = quote(user.role) + headers["X-OpenWebUI-User-Name"] = quote(user.name, safe=" ") + headers["X-OpenWebUI-User-Id"] = user.id + headers["X-OpenWebUI-User-Email"] = user.email + headers["X-OpenWebUI-User-Role"] = user.role data = { "model": ( diff --git a/backend/open_webui/routers/ollama.py b/backend/open_webui/routers/ollama.py index c52946add8..000f4b48d2 100644 --- a/backend/open_webui/routers/ollama.py +++ b/backend/open_webui/routers/ollama.py @@ -89,10 +89,10 @@ async def send_get_request(url, key=None, user: UserModel = None): **({"Authorization": f"Bearer {key}"} if key else {}), **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS and user else {} @@ -140,10 +140,10 @@ async def send_post_request( **({"Authorization": f"Bearer {key}"} if key else {}), **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS and user else {} @@ -244,10 +244,10 @@ async def verify_connection( **({"Authorization": f"Bearer {key}"} if key else {}), **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS and user else {} @@ -464,10 +464,10 @@ async def get_ollama_tags( **({"Authorization": f"Bearer {key}"} if key else {}), **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS and user else {} @@ -834,10 +834,10 @@ async def copy_model( **({"Authorization": f"Bearer {key}"} if key else {}), **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS and user else {} @@ -905,10 +905,10 @@ async def delete_model( **({"Authorization": f"Bearer {key}"} if key else {}), **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS and user else {} @@ -969,10 +969,10 @@ async def show_model_info( **({"Authorization": f"Bearer {key}"} if key else {}), **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS and user else {} @@ -1056,10 +1056,10 @@ async def embed( **({"Authorization": f"Bearer {key}"} if key else {}), **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS and user else {} @@ -1143,10 +1143,10 @@ async def embeddings( **({"Authorization": f"Bearer {key}"} if key else {}), **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS and user else {} diff --git a/backend/open_webui/routers/openai.py b/backend/open_webui/routers/openai.py index a769c9a0c9..a759ec7eee 100644 --- a/backend/open_webui/routers/openai.py +++ b/backend/open_webui/routers/openai.py @@ -67,10 +67,10 @@ async def send_get_request(url, key=None, user: UserModel = None): **({"Authorization": f"Bearer {key}"} if key else {}), **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS and user else {} @@ -226,10 +226,10 @@ async def speech(request: Request, user=Depends(get_verified_user)): ), **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS else {} @@ -479,10 +479,10 @@ async def get_models( "Content-Type": "application/json", **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS else {} @@ -574,10 +574,10 @@ async def verify_connection( "Content-Type": "application/json", **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS else {} @@ -818,10 +818,10 @@ async def generate_chat_completion( ), **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS else {} @@ -936,10 +936,10 @@ async def embeddings(request: Request, form_data: dict, user): "Content-Type": "application/json", **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS and user else {} @@ -1008,10 +1008,10 @@ async def proxy(path: str, request: Request, user=Depends(get_verified_user)): "Content-Type": "application/json", **( { - "X-OpenWebUI-User-Name": quote(user.name), - "X-OpenWebUI-User-Id": quote(user.id), - "X-OpenWebUI-User-Email": quote(user.email), - "X-OpenWebUI-User-Role": quote(user.role), + "X-OpenWebUI-User-Name": quote(user.name, safe=" "), + "X-OpenWebUI-User-Id": user.id, + "X-OpenWebUI-User-Email": user.email, + "X-OpenWebUI-User-Role": user.role, } if ENABLE_FORWARD_USER_INFO_HEADERS else {}