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

View File

@ -15,6 +15,7 @@ import aiohttp
import aiofiles
import requests
import mimetypes
from urllib.parse import quote
from fastapi import (
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}",
**(
{
"X-OpenWebUI-User-Name": user.name,
"X-OpenWebUI-User-Id": user.id,
"X-OpenWebUI-User-Email": user.email,
"X-OpenWebUI-User-Role": user.role,
"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),
}
if ENABLE_FORWARD_USER_INFO_HEADERS
else {}

View File

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

View File

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

View File

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