From c4a15dcdcb17bb8e6bce48b8446edf59d7ce1eda Mon Sep 17 00:00:00 2001 From: Krrish Dholakia Date: Mon, 2 Jun 2025 14:21:41 -0700 Subject: [PATCH] feat(ui_discovery_endpoints.py): add new public .well-known/ route for litellm ui config returns the server root path and proxy base url for constructing api calls --- litellm/proxy/discovery_endpoints/README.md | 12 +++++++++++ litellm/proxy/discovery_endpoints/__init__.py | 3 +++ .../ui_discovery_endpoints.py | 20 +++++++++++++++++++ litellm/proxy/proxy_server.py | 2 ++ litellm/proxy/utils.py | 7 +++++++ .../ui_discovery_endpoints.py | 8 ++++++++ 6 files changed, 52 insertions(+) create mode 100644 litellm/proxy/discovery_endpoints/README.md create mode 100644 litellm/proxy/discovery_endpoints/__init__.py create mode 100644 litellm/proxy/discovery_endpoints/ui_discovery_endpoints.py create mode 100644 litellm/types/proxy/discovery_endpoints/ui_discovery_endpoints.py diff --git a/litellm/proxy/discovery_endpoints/README.md b/litellm/proxy/discovery_endpoints/README.md new file mode 100644 index 00000000000..aebaa520c20 --- /dev/null +++ b/litellm/proxy/discovery_endpoints/README.md @@ -0,0 +1,12 @@ +Return the proxy base url and server root path, so UI can construct the correct url to access the proxy. + +This is useful when the proxy is deployed at a different path than the root of the domain. + +## How to use + +**Action** Route the `/litellm` path to the proxy. + +**Result** The UI will call `/litellm/.well-known/litellm-ui-config` to get the proxy base url and server root path. + + + diff --git a/litellm/proxy/discovery_endpoints/__init__.py b/litellm/proxy/discovery_endpoints/__init__.py new file mode 100644 index 00000000000..a6401c2f1b4 --- /dev/null +++ b/litellm/proxy/discovery_endpoints/__init__.py @@ -0,0 +1,3 @@ +from .ui_discovery_endpoints import router as ui_discovery_endpoints_router + +__all__ = ["ui_discovery_endpoints_router"] diff --git a/litellm/proxy/discovery_endpoints/ui_discovery_endpoints.py b/litellm/proxy/discovery_endpoints/ui_discovery_endpoints.py new file mode 100644 index 00000000000..91a3c045676 --- /dev/null +++ b/litellm/proxy/discovery_endpoints/ui_discovery_endpoints.py @@ -0,0 +1,20 @@ +#### Analytics Endpoints ##### +from fastapi import APIRouter + +from litellm.types.proxy.discovery_endpoints.ui_discovery_endpoints import ( + UiDiscoveryEndpoints, +) + +router = APIRouter() + + +@router.get(".well-known/litellm-ui-config", response_model=UiDiscoveryEndpoints) +@router.get( + "/litellm/.well-known/litellm-ui-config", response_model=UiDiscoveryEndpoints +) # if mounted at root path +async def get_ui_config(): + from litellm.proxy.utils import get_proxy_base_url, get_server_root_path + + return UiDiscoveryEndpoints( + server_root_path=get_server_root_path(), proxy_base_url=get_proxy_base_url() + ) diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index ce67b1d1d6f..4e7048f632c 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -203,6 +203,7 @@ from litellm.proxy.common_utils.swagger_utils import ERROR_RESPONSES from litellm.proxy.credential_endpoints.endpoints import router as credential_router from litellm.proxy.db.db_transaction_queue.spend_log_cleanup import SpendLogCleanup from litellm.proxy.db.exception_handler import PrismaDBExceptionHandler +from litellm.proxy.discovery_endpoints import ui_discovery_endpoints_router from litellm.proxy.fine_tuning_endpoints.endpoints import router as fine_tuning_router from litellm.proxy.fine_tuning_endpoints.endpoints import set_fine_tuning_config from litellm.proxy.guardrails.guardrail_endpoints import router as guardrails_router @@ -8150,3 +8151,4 @@ app.include_router(budget_management_router) app.include_router(model_management_router) app.include_router(tag_management_router) app.include_router(enterprise_router) +app.include_router(ui_discovery_endpoints_router) diff --git a/litellm/proxy/utils.py b/litellm/proxy/utils.py index 8349aafda58..c9ed40696dc 100644 --- a/litellm/proxy/utils.py +++ b/litellm/proxy/utils.py @@ -2865,6 +2865,13 @@ def get_custom_url(request_base_url: str) -> str: return ui_link +def get_proxy_base_url() -> Optional[str]: + """ + Get the proxy base url from the environment variables. + """ + return os.getenv("PROXY_BASE_URL") + + def get_server_root_path() -> str: """ Get the server root path from the environment variables. diff --git a/litellm/types/proxy/discovery_endpoints/ui_discovery_endpoints.py b/litellm/types/proxy/discovery_endpoints/ui_discovery_endpoints.py new file mode 100644 index 00000000000..7132077b5fa --- /dev/null +++ b/litellm/types/proxy/discovery_endpoints/ui_discovery_endpoints.py @@ -0,0 +1,8 @@ +from typing import Optional + +from pydantic import BaseModel + + +class UiDiscoveryEndpoints(BaseModel): + server_root_path: str + proxy_base_url: Optional[str]