perf: optional orjson JSON codec behind ENABLE_ORJSON (#27583)

Swap the JSON encoder/decoder used across the backend from stdlib json to
orjson when ENABLE_ORJSON is set — HTTP request bodies, JSONResponse
bodies, upstream provider responses, SSE chunks, and socket.io/Redis
payloads.

The flag defaults to off, in which case the app uses stdlib json and
engineio's codec verbatim, so default behaviour is unchanged.

- json_codec exports JSONCodec (stdlib json or the orjson codec) and
  SOCKETIO_JSON (engineio's codec or the orjson codec); call sites import
  JSONCodec and stay implementation-agnostic
- apply_orjson_http_json() is a no-op when the flag is off, leaving
  starlette's Request.json / JSONResponse.render untouched
- the orjson codec falls back to the stdlib for inputs orjson rejects
  (non-str dict keys, ints beyond 64 bits, NaN literals)
- orjson is imported only when the flag is on
- FastAPI(default_response_class=...) is deliberately not used: an
  explicit default disables the Pydantic direct-to-bytes fast path for
  response_model routes
This commit is contained in:
Classic298 authored and GitHub committed 2026-07-27 03:45:37 -04:00
1 parent 602004dd5f
commit 72fdf238a8
13 files changed
+176 -51

No files matched your search

+6 -5
View File
@@ -42,6 +42,7 @@ from open_webui.utils.access_control import check_model_access
from open_webui.utils.auth import get_admin_user, get_verified_user
from open_webui.utils.headers import get_custom_headers, include_user_info_headers
from open_webui.utils.model_ids import strip_provider_model_prefix
from open_webui.utils.json_codec import JSONCodec
from open_webui.utils.misc import calculate_sha256
from open_webui.utils.payload import (
apply_model_params_to_body_ollama,
@@ -86,7 +87,7 @@ async def send_get_request(
ssl=AIOHTTP_CLIENT_SESSION_SSL,
timeout=aiohttp.ClientTimeout(total=AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST),
) as r:
return await r.json()
return await r.json(loads=JSONCodec.loads)
except Exception as exc:
log.error(f'Connection error: {exc}')
return None
@@ -137,7 +138,7 @@ async def send_request(
if not r.ok:
try:
res = await r.json()
res = await r.json(loads=JSONCodec.loads)
await publish_model_provider_request_failed(
request,
actor=user,
@@ -179,7 +180,7 @@ async def send_request(
)
else:
try:
return await r.json()
return await r.json(loads=JSONCodec.loads)
except Exception:
return None
@@ -270,12 +271,12 @@ async def verify_connection(
) as r:
if r.status != 200:
detail = f'HTTP Error: {r.status}'
res = await r.json()
res = await r.json(loads=JSONCodec.loads)
if 'error' in res:
detail = f'External Error: {res["error"]}'
raise Exception(detail)
return await r.json()
return await r.json(loads=JSONCodec.loads)
except aiohttp.ClientError as exc:
log.exception(f'Client error: {exc}')
raise HTTPException(status_code=500, detail=ERROR_MESSAGES.SERVER_CONNECTION_ERROR)
+12 -11
View File
@@ -44,6 +44,7 @@ from open_webui.utils.access_control import check_model_access, has_connection_a
from open_webui.utils.anthropic import get_anthropic_models, is_anthropic_url
from open_webui.utils.auth import get_admin_user, get_verified_user
from open_webui.utils.headers import get_custom_headers, include_user_info_headers
from open_webui.utils.json_codec import JSONCodec
from open_webui.utils.model_ids import strip_provider_model_prefix
from open_webui.utils.misc import (
convert_logit_bias_input_to_json,
@@ -112,7 +113,7 @@ async def send_get_request(
cookies=cookies,
ssl=AIOHTTP_CLIENT_SESSION_SSL,
) as response:
return await response.json()
return await response.json(loads=JSONCodec.loads)
except Exception as e:
# Handle connection error here
log.error(f'Connection error: {e}')
@@ -357,7 +358,7 @@ async def count_anthropic_tokens(request: Request, form_data: dict, user: UserMo
)
try:
response_data = await response.json()
response_data = await response.json(loads=JSONCodec.loads)
except Exception:
response_data = await response.text()
@@ -509,7 +510,7 @@ async def speech(request: Request, user=Depends(get_verified_user)):
detail = None
if r is not None:
try:
res = await r.json()
res = await r.json(loads=JSONCodec.loads)
if 'error' in res:
detail = f'External: {res["error"]}'
except Exception:
@@ -763,14 +764,14 @@ async def get_models(request: Request, url_idx: int | None = None, user=Depends(
if r.status != 200:
error_detail = f'HTTP Error: {r.status}'
try:
res = await r.json()
res = await r.json(loads=JSONCodec.loads)
if 'error' in res:
error_detail = f'External Error: {res["error"]}'
except Exception:
pass
raise Exception(error_detail)
response_data = await r.json()
response_data = await r.json(loads=JSONCodec.loads)
if 'api.openai.com' in url:
response_data['data'] = [
@@ -853,7 +854,7 @@ async def verify_connection(
ssl=AIOHTTP_CLIENT_SESSION_SSL,
) as r:
try:
response_data = await r.json()
response_data = await r.json(loads=JSONCodec.loads)
except Exception:
response_data = await r.text()
@@ -879,7 +880,7 @@ async def verify_connection(
ssl=AIOHTTP_CLIENT_SESSION_SSL,
) as r:
try:
response_data = await r.json()
response_data = await r.json(loads=JSONCodec.loads)
except Exception:
response_data = await r.text()
@@ -1417,7 +1418,7 @@ async def generate_chat_completion(
)
else:
try:
response = await r.json()
response = await r.json(loads=JSONCodec.loads)
except Exception as e:
log.error(e)
response = await r.text()
@@ -1529,7 +1530,7 @@ async def embeddings(request: Request, form_data: dict, user):
)
else:
try:
response_data = await r.json()
response_data = await r.json(loads=JSONCodec.loads)
except Exception:
response_data = await r.text()
@@ -1656,7 +1657,7 @@ async def responses(
)
else:
try:
response_data = await r.json()
response_data = await r.json(loads=JSONCodec.loads)
except Exception:
response_data = await r.text()
@@ -1778,7 +1779,7 @@ async def proxy(path: str, request: Request, user=Depends(get_verified_user)):
)
else:
try:
response_data = await r.json()
response_data = await r.json(loads=JSONCodec.loads)
except Exception:
response_data = await r.text()