mirror of
https://github.com/BerriAI/litellm.git
synced 2026-08-28 05:25:59 +00:00
67 lines
2.4 KiB
Python
67 lines
2.4 KiB
Python
"""Gateway entrypoint.
|
|
|
|
Reuses the existing FastAPI app from `litellm.proxy.proxy_server` and trims its
|
|
route table to just the LLM data-plane surface. The trim is purely additive —
|
|
no existing module is modified, the full app continues to work via the legacy
|
|
entrypoint (`litellm.proxy.proxy_server:app`).
|
|
|
|
Run with:
|
|
uvicorn gateway.main:app --host 0.0.0.0 --port 4000
|
|
"""
|
|
|
|
from contextlib import asynccontextmanager
|
|
|
|
from fastapi.routing import Mount
|
|
|
|
# Assemble DATABASE_URL (+ DATABASE_URL_READ_REPLICA) from the discrete
|
|
# DATABASE_* env vars before proxy_server imports spin up Prisma. Handles
|
|
# both IAM (mint a token) and password auth, writer and reader. The standard
|
|
# CLI flow does this in proxy_cli.py; we bypass proxy_cli by uvicorn'ing the
|
|
# app directly, so without this Prisma initializes with the placeholder URL
|
|
# and every DB-needing endpoint returns "Database not connected".
|
|
from litellm.proxy.db.db_url_settings import DatabaseURLSettings
|
|
|
|
DatabaseURLSettings.from_env().apply_to_env()
|
|
|
|
from litellm.proxy.proxy_server import app
|
|
|
|
from gateway.routes.allowlist import (
|
|
GATEWAY_EXACT_PATHS,
|
|
GATEWAY_MOUNT_PATHS,
|
|
GATEWAY_PATH_PREFIXES,
|
|
)
|
|
|
|
|
|
def _is_gateway_route(route) -> bool:
|
|
"""Keep the route on the gateway if its path is in the LLM data-plane surface.
|
|
|
|
Prometheus registers /metrics as a Mount (``app.mount("/metrics", make_asgi_app())``),
|
|
so Mounts are matched against GATEWAY_MOUNT_PATHS instead of being dropped with
|
|
the UI static mounts.
|
|
"""
|
|
path = getattr(route, "path", None)
|
|
if path is None:
|
|
return False
|
|
if isinstance(route, Mount):
|
|
return path in GATEWAY_MOUNT_PATHS
|
|
if path in GATEWAY_EXACT_PATHS:
|
|
return True
|
|
return any(path.startswith(prefix) for prefix in GATEWAY_PATH_PREFIXES)
|
|
|
|
|
|
# Wrap proxy_server's existing lifespan so the route trim runs *after* its
|
|
# startup hooks (and any plugin code those hooks load) have had a chance to
|
|
# register routes. A module-load filter would miss routes added during
|
|
# startup; running inside the lifespan, after the inner __aenter__, catches
|
|
# them while still completing before uvicorn opens the listener.
|
|
_proxy_lifespan = app.router.lifespan_context
|
|
|
|
|
|
@asynccontextmanager
|
|
async def _gateway_lifespan(app_):
|
|
async with _proxy_lifespan(app_):
|
|
app_.router.routes = [r for r in app_.router.routes if _is_gateway_route(r)]
|
|
yield
|
|
|
|
|
|
app.router.lifespan_context = _gateway_lifespan
|