diff --git a/backend/open_webui/retrieval/models/external.py b/backend/open_webui/retrieval/models/external.py index a9be526b6d..822cb3e3dd 100644 --- a/backend/open_webui/retrieval/models/external.py +++ b/backend/open_webui/retrieval/models/external.py @@ -6,6 +6,7 @@ from urllib.parse import quote from open_webui.env import ENABLE_FORWARD_USER_INFO_HEADERS, SRC_LOG_LEVELS from open_webui.retrieval.models.base_reranker import BaseReranker +from open_webui.utils.headers import include_user_info_headers log = logging.getLogger(__name__) @@ -40,22 +41,17 @@ class ExternalReranker(BaseReranker): log.info(f"ExternalReranker:predict:model {self.model}") log.info(f"ExternalReranker:predict:query {query}") + headers = { + "Content-Type": "application/json", + "Authorization": f"Bearer {self.api_key}", + } + + if ENABLE_FORWARD_USER_INFO_HEADERS and user: + headers = include_user_info_headers(headers, user) + r = requests.post( f"{self.url}", - headers={ - "Content-Type": "application/json", - "Authorization": f"Bearer {self.api_key}", - **( - { - "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 {} - ), - }, + headers=headers, json=payload, ) diff --git a/backend/open_webui/routers/audio.py b/backend/open_webui/routers/audio.py index 1edf31fa9c..db7861d333 100644 --- a/backend/open_webui/routers/audio.py +++ b/backend/open_webui/routers/audio.py @@ -16,7 +16,6 @@ import aiohttp import aiofiles import requests import mimetypes -from urllib.parse import urljoin, quote from fastapi import ( Depends, diff --git a/backend/open_webui/routers/ollama.py b/backend/open_webui/routers/ollama.py index 64b0687afa..85cfee6ff4 100644 --- a/backend/open_webui/routers/ollama.py +++ b/backend/open_webui/routers/ollama.py @@ -16,8 +16,8 @@ from urllib.parse import urlparse import aiohttp from aiocache import cached import requests -from urllib.parse import quote +from open_webui.utils.headers import include_user_info_headers from open_webui.models.chats import Chats from open_webui.models.users import UserModel @@ -53,6 +53,7 @@ from open_webui.utils.auth import get_admin_user, get_verified_user from open_webui.utils.access_control import has_access + from open_webui.config import ( UPLOAD_DIR, ) @@ -82,22 +83,17 @@ async def send_get_request(url, key=None, user: UserModel = None): timeout = aiohttp.ClientTimeout(total=AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST) try: async with aiohttp.ClientSession(timeout=timeout, trust_env=True) as session: + headers = { + "Content-Type": "application/json", + **({"Authorization": f"Bearer {key}"} if key else {}), + } + + if ENABLE_FORWARD_USER_INFO_HEADERS and user: + headers = include_user_info_headers(headers, user) + async with session.get( url, - headers={ - "Content-Type": "application/json", - **({"Authorization": f"Bearer {key}"} if key else {}), - **( - { - "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 {} - ), - }, + headers=headers, ssl=AIOHTTP_CLIENT_SESSION_SSL, ) as response: return await response.json() @@ -133,28 +129,20 @@ async def send_post_request( trust_env=True, timeout=aiohttp.ClientTimeout(total=AIOHTTP_CLIENT_TIMEOUT) ) + headers = { + "Content-Type": "application/json", + **({"Authorization": f"Bearer {key}"} if key else {}), + } + + if ENABLE_FORWARD_USER_INFO_HEADERS and user: + headers = include_user_info_headers(headers, user) + if metadata and metadata.get("chat_id"): + headers["X-OpenWebUI-Chat-Id"] = metadata.get("chat_id") + r = await session.post( url, data=payload, - headers={ - "Content-Type": "application/json", - **({"Authorization": f"Bearer {key}"} if key else {}), - **( - { - "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, - **( - {"X-OpenWebUI-Chat-Id": metadata.get("chat_id")} - if metadata and metadata.get("chat_id") - else {} - ), - } - if ENABLE_FORWARD_USER_INFO_HEADERS and user - else {} - ), - }, + headers=headers, ssl=AIOHTTP_CLIENT_SESSION_SSL, ) @@ -246,21 +234,16 @@ async def verify_connection( timeout=aiohttp.ClientTimeout(total=AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST), ) as session: try: + headers = { + **({"Authorization": f"Bearer {key}"} if key else {}), + } + + if ENABLE_FORWARD_USER_INFO_HEADERS and user: + headers = include_user_info_headers(headers, user) + async with session.get( f"{url}/api/version", - headers={ - **({"Authorization": f"Bearer {key}"} if key else {}), - **( - { - "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 {} - ), - }, + headers=headers, ssl=AIOHTTP_CLIENT_SESSION_SSL, ) as r: if r.status != 200: @@ -469,22 +452,17 @@ async def get_ollama_tags( r = None try: + headers = { + **({"Authorization": f"Bearer {key}"} if key else {}), + } + + if ENABLE_FORWARD_USER_INFO_HEADERS and user: + headers = include_user_info_headers(headers, user) + r = requests.request( method="GET", url=f"{url}/api/tags", - headers={ - **({"Authorization": f"Bearer {key}"} if key else {}), - **( - { - "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 {} - ), - }, + headers=headers, ) r.raise_for_status() @@ -838,23 +816,18 @@ async def copy_model( key = get_api_key(url_idx, url, request.app.state.config.OLLAMA_API_CONFIGS) try: + headers = { + "Content-Type": "application/json", + **({"Authorization": f"Bearer {key}"} if key else {}), + } + + if ENABLE_FORWARD_USER_INFO_HEADERS and user: + headers = include_user_info_headers(headers, user) + r = requests.request( method="POST", url=f"{url}/api/copy", - headers={ - "Content-Type": "application/json", - **({"Authorization": f"Bearer {key}"} if key else {}), - **( - { - "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 {} - ), - }, + headers=headers, data=form_data.model_dump_json(exclude_none=True).encode(), ) r.raise_for_status() @@ -908,24 +881,19 @@ async def delete_model( key = get_api_key(url_idx, url, request.app.state.config.OLLAMA_API_CONFIGS) try: + headers = { + "Content-Type": "application/json", + **({"Authorization": f"Bearer {key}"} if key else {}), + } + + if ENABLE_FORWARD_USER_INFO_HEADERS and user: + headers = include_user_info_headers(headers, user) + r = requests.request( method="DELETE", url=f"{url}/api/delete", - data=json.dumps(form_data).encode(), - headers={ - "Content-Type": "application/json", - **({"Authorization": f"Bearer {key}"} if key else {}), - **( - { - "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 {} - ), - }, + headers=headers, + data=form_data.model_dump_json(exclude_none=True).encode(), ) r.raise_for_status() @@ -973,24 +941,19 @@ async def show_model_info( key = get_api_key(url_idx, url, request.app.state.config.OLLAMA_API_CONFIGS) try: + headers = { + "Content-Type": "application/json", + **({"Authorization": f"Bearer {key}"} if key else {}), + } + + if ENABLE_FORWARD_USER_INFO_HEADERS and user: + headers = include_user_info_headers(headers, user) + r = requests.request( method="POST", url=f"{url}/api/show", - headers={ - "Content-Type": "application/json", - **({"Authorization": f"Bearer {key}"} if key else {}), - **( - { - "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 {} - ), - }, - data=json.dumps(form_data).encode(), + headers=headers, + data=form_data.model_dump_json(exclude_none=True).encode(), ) r.raise_for_status() @@ -1064,23 +1027,18 @@ async def embed( form_data.model = form_data.model.replace(f"{prefix_id}.", "") try: + headers = { + "Content-Type": "application/json", + **({"Authorization": f"Bearer {key}"} if key else {}), + } + + if ENABLE_FORWARD_USER_INFO_HEADERS and user: + headers = include_user_info_headers(headers, user) + r = requests.request( method="POST", url=f"{url}/api/embed", - headers={ - "Content-Type": "application/json", - **({"Authorization": f"Bearer {key}"} if key else {}), - **( - { - "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 {} - ), - }, + headers=headers, data=form_data.model_dump_json(exclude_none=True).encode(), ) r.raise_for_status() @@ -1151,23 +1109,18 @@ async def embeddings( form_data.model = form_data.model.replace(f"{prefix_id}.", "") try: + headers = { + "Content-Type": "application/json", + **({"Authorization": f"Bearer {key}"} if key else {}), + } + + if ENABLE_FORWARD_USER_INFO_HEADERS and user: + headers = include_user_info_headers(headers, user) + r = requests.request( method="POST", url=f"{url}/api/embeddings", - headers={ - "Content-Type": "application/json", - **({"Authorization": f"Bearer {key}"} if key else {}), - **( - { - "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 {} - ), - }, + headers=headers, data=form_data.model_dump_json(exclude_none=True).encode(), ) r.raise_for_status() diff --git a/backend/open_webui/routers/openai.py b/backend/open_webui/routers/openai.py index cf75bc425a..a74a59ca1f 100644 --- a/backend/open_webui/routers/openai.py +++ b/backend/open_webui/routers/openai.py @@ -7,7 +7,6 @@ from typing import Optional import aiohttp from aiocache import cached import requests -from urllib.parse import quote from azure.identity import DefaultAzureCredential, get_bearer_token_provider @@ -50,6 +49,7 @@ from open_webui.utils.misc import ( from open_webui.utils.auth import get_admin_user, get_verified_user from open_webui.utils.access_control import has_access +from open_webui.utils.headers import include_user_info_headers log = logging.getLogger(__name__) @@ -67,21 +67,16 @@ async def send_get_request(url, key=None, user: UserModel = None): timeout = aiohttp.ClientTimeout(total=AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST) try: async with aiohttp.ClientSession(timeout=timeout, trust_env=True) as session: + headers = { + **({"Authorization": f"Bearer {key}"} if key else {}), + } + + if ENABLE_FORWARD_USER_INFO_HEADERS and user: + headers = include_user_info_headers(headers, user) + async with session.get( url, - headers={ - **({"Authorization": f"Bearer {key}"} if key else {}), - **( - { - "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 {} - ), - }, + headers=headers, ssl=AIOHTTP_CLIENT_SESSION_SSL, ) as response: return await response.json() @@ -141,23 +136,13 @@ async def get_headers_and_cookies( if "openrouter.ai" in url else {} ), - **( - { - "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, - **( - {"X-OpenWebUI-Chat-Id": metadata.get("chat_id")} - if metadata and metadata.get("chat_id") - else {} - ), - } - if ENABLE_FORWARD_USER_INFO_HEADERS - else {} - ), } + if ENABLE_FORWARD_USER_INFO_HEADERS and user: + headers = include_user_info_headers(headers, user) + if metadata and metadata.get("chat_id"): + headers["X-OpenWebUI-Chat-Id"] = metadata.get("chat_id") + token = None auth_type = config.get("auth_type")