Merge pull request #15035 from decent-engineer-decent-datascientist/dev

fix: Resolve UnicodeEncodeError for non-ASCII usernames in forwarded headers
This commit is contained in:
Tim Jaeryang Baek 2025-06-17 12:22:02 +04:00 committed by GitHub
commit d50449ea71
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 89 additions and 85 deletions

View File

@ -7,6 +7,7 @@ import hashlib
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
import time import time
from urllib.parse import quote
from huggingface_hub import snapshot_download from huggingface_hub import snapshot_download
from langchain.retrievers import ContextualCompressionRetriever, EnsembleRetriever from langchain.retrievers import ContextualCompressionRetriever, EnsembleRetriever
from langchain_community.retrievers import BM25Retriever from langchain_community.retrievers import BM25Retriever
@ -678,10 +679,10 @@ def generate_openai_batch_embeddings(
"Authorization": f"Bearer {key}", "Authorization": f"Bearer {key}",
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS and user if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {} else {}
@ -727,10 +728,10 @@ def generate_azure_openai_batch_embeddings(
"api-key": key, "api-key": key,
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS and user if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {} else {}
@ -777,10 +778,10 @@ def generate_ollama_batch_embeddings(
"Authorization": f"Bearer {key}", "Authorization": f"Bearer {key}",
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS if ENABLE_FORWARD_USER_INFO_HEADERS
else {} else {}

View File

@ -15,6 +15,7 @@ import aiohttp
import aiofiles import aiofiles
import requests import requests
import mimetypes import mimetypes
from urllib.parse import quote
from fastapi import ( from fastapi import (
Depends, Depends,
@ -343,10 +344,10 @@ async def speech(request: Request, user=Depends(get_verified_user)):
"Authorization": f"Bearer {request.app.state.config.TTS_OPENAI_API_KEY}", "Authorization": f"Bearer {request.app.state.config.TTS_OPENAI_API_KEY}",
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS if ENABLE_FORWARD_USER_INFO_HEADERS
else {} else {}

View File

@ -8,6 +8,7 @@ import re
from pathlib import Path from pathlib import Path
from typing import Optional from typing import Optional
from urllib.parse import quote
import requests import requests
from fastapi import APIRouter, Depends, HTTPException, Request, UploadFile from fastapi import APIRouter, Depends, HTTPException, Request, UploadFile
from open_webui.config import CACHE_DIR from open_webui.config import CACHE_DIR
@ -483,10 +484,10 @@ async def image_generations(
headers["Content-Type"] = "application/json" headers["Content-Type"] = "application/json"
if ENABLE_FORWARD_USER_INFO_HEADERS: if ENABLE_FORWARD_USER_INFO_HEADERS:
headers["X-OpenWebUI-User-Name"] = user.name headers["X-OpenWebUI-User-Name"] = quote(user.name)
headers["X-OpenWebUI-User-Id"] = user.id headers["X-OpenWebUI-User-Id"] = quote(user.id)
headers["X-OpenWebUI-User-Email"] = user.email headers["X-OpenWebUI-User-Email"] = quote(user.email)
headers["X-OpenWebUI-User-Role"] = user.role headers["X-OpenWebUI-User-Role"] = quote(user.role)
data = { data = {
"model": ( "model": (

View File

@ -16,6 +16,7 @@ from urllib.parse import urlparse
import aiohttp import aiohttp
from aiocache import cached from aiocache import cached
import requests import requests
from urllib.parse import quote
from open_webui.models.chats import Chats from open_webui.models.chats import Chats
from open_webui.models.users import UserModel from open_webui.models.users import UserModel
@ -87,10 +88,10 @@ async def send_get_request(url, key=None, user: UserModel = None):
**({"Authorization": f"Bearer {key}"} if key else {}), **({"Authorization": f"Bearer {key}"} if key else {}),
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS and user if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {} else {}
@ -138,10 +139,10 @@ async def send_post_request(
**({"Authorization": f"Bearer {key}"} if key else {}), **({"Authorization": f"Bearer {key}"} if key else {}),
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS and user if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {} else {}
@ -242,10 +243,10 @@ async def verify_connection(
**({"Authorization": f"Bearer {key}"} if key else {}), **({"Authorization": f"Bearer {key}"} if key else {}),
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS and user if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {} else {}
@ -462,10 +463,10 @@ async def get_ollama_tags(
**({"Authorization": f"Bearer {key}"} if key else {}), **({"Authorization": f"Bearer {key}"} if key else {}),
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS and user if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {} else {}
@ -824,10 +825,10 @@ async def copy_model(
**({"Authorization": f"Bearer {key}"} if key else {}), **({"Authorization": f"Bearer {key}"} if key else {}),
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS and user if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {} else {}
@ -890,10 +891,10 @@ async def delete_model(
**({"Authorization": f"Bearer {key}"} if key else {}), **({"Authorization": f"Bearer {key}"} if key else {}),
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS and user if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {} else {}
@ -949,10 +950,10 @@ async def show_model_info(
**({"Authorization": f"Bearer {key}"} if key else {}), **({"Authorization": f"Bearer {key}"} if key else {}),
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS and user if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {} else {}
@ -1036,10 +1037,10 @@ async def embed(
**({"Authorization": f"Bearer {key}"} if key else {}), **({"Authorization": f"Bearer {key}"} if key else {}),
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS and user if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {} else {}
@ -1123,10 +1124,10 @@ async def embeddings(
**({"Authorization": f"Bearer {key}"} if key else {}), **({"Authorization": f"Bearer {key}"} if key else {}),
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS and user if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {} else {}

View File

@ -8,7 +8,7 @@ from typing import Literal, Optional, overload
import aiohttp import aiohttp
from aiocache import cached from aiocache import cached
import requests import requests
from urllib.parse import quote
from fastapi import Depends, FastAPI, HTTPException, Request, APIRouter from fastapi import Depends, FastAPI, HTTPException, Request, APIRouter
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
@ -66,10 +66,10 @@ async def send_get_request(url, key=None, user: UserModel = None):
**({"Authorization": f"Bearer {key}"} if key else {}), **({"Authorization": f"Bearer {key}"} if key else {}),
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS and user if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {} else {}
@ -225,10 +225,10 @@ async def speech(request: Request, user=Depends(get_verified_user)):
), ),
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS if ENABLE_FORWARD_USER_INFO_HEADERS
else {} else {}
@ -478,10 +478,10 @@ async def get_models(
"Content-Type": "application/json", "Content-Type": "application/json",
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS if ENABLE_FORWARD_USER_INFO_HEADERS
else {} else {}
@ -573,10 +573,10 @@ async def verify_connection(
"Content-Type": "application/json", "Content-Type": "application/json",
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS if ENABLE_FORWARD_USER_INFO_HEADERS
else {} else {}
@ -806,10 +806,10 @@ async def generate_chat_completion(
), ),
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS if ENABLE_FORWARD_USER_INFO_HEADERS
else {} else {}
@ -924,10 +924,10 @@ async def embeddings(request: Request, form_data: dict, user):
"Content-Type": "application/json", "Content-Type": "application/json",
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS and user if ENABLE_FORWARD_USER_INFO_HEADERS and user
else {} else {}
@ -996,10 +996,10 @@ async def proxy(path: str, request: Request, user=Depends(get_verified_user)):
"Content-Type": "application/json", "Content-Type": "application/json",
**( **(
{ {
"X-OpenWebUI-User-Name": user.name, "X-OpenWebUI-User-Name": quote(user.name),
"X-OpenWebUI-User-Id": user.id, "X-OpenWebUI-User-Id": quote(user.id),
"X-OpenWebUI-User-Email": user.email, "X-OpenWebUI-User-Email": quote(user.email),
"X-OpenWebUI-User-Role": user.role, "X-OpenWebUI-User-Role": quote(user.role),
} }
if ENABLE_FORWARD_USER_INFO_HEADERS if ENABLE_FORWARD_USER_INFO_HEADERS
else {} else {}