mirror of https://github.com/razor-ai/soup.git
88 lines
2.4 KiB
Python
88 lines
2.4 KiB
Python
"""v0.44.0 Part C — Web UI environment-variable knobs.
|
|
|
|
`API_HOST` / `API_PORT` / `API_KEY` for the FastAPI server, plus
|
|
`GRADIO_HOST` / `GRADIO_PORT` for any Gradio sub-UI.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from dataclasses import dataclass
|
|
from typing import Optional
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class UiEnv:
|
|
"""Resolved Web UI environment overrides."""
|
|
|
|
api_host: Optional[str]
|
|
api_port: Optional[int]
|
|
api_key: Optional[str]
|
|
gradio_host: Optional[str]
|
|
gradio_port: Optional[int]
|
|
|
|
|
|
_VALID_HOST_CHARS = set(
|
|
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-:"
|
|
)
|
|
|
|
|
|
def _parse_host(raw: Optional[str]) -> Optional[str]:
|
|
if raw is None:
|
|
return None
|
|
if not isinstance(raw, str):
|
|
raise TypeError("host must be str")
|
|
cleaned = raw.strip()
|
|
if not cleaned:
|
|
return None
|
|
if "\x00" in cleaned or len(cleaned) > 253:
|
|
raise ValueError("invalid host string")
|
|
if any(char not in _VALID_HOST_CHARS for char in cleaned):
|
|
raise ValueError(
|
|
"host contains characters outside [a-zA-Z0-9.-:]"
|
|
)
|
|
return cleaned
|
|
|
|
|
|
def _parse_port(raw: Optional[str]) -> Optional[int]:
|
|
if raw is None:
|
|
return None
|
|
if not isinstance(raw, str):
|
|
raise TypeError("port must be str")
|
|
cleaned = raw.strip()
|
|
if not cleaned:
|
|
return None
|
|
try:
|
|
port = int(cleaned)
|
|
except ValueError as exc:
|
|
raise ValueError(f"port must be int; got {cleaned!r}") from exc
|
|
if not (1 <= port <= 65535):
|
|
raise ValueError("port must be in [1, 65535]")
|
|
return port
|
|
|
|
|
|
def _parse_key(raw: Optional[str]) -> Optional[str]:
|
|
if raw is None:
|
|
return None
|
|
if not isinstance(raw, str):
|
|
raise TypeError("key must be str")
|
|
cleaned = raw.strip()
|
|
if not cleaned:
|
|
return None
|
|
if "\x00" in cleaned or len(cleaned) > 256:
|
|
raise ValueError("invalid key string")
|
|
return cleaned
|
|
|
|
|
|
def resolve_ui_env(env: Optional[dict] = None) -> UiEnv:
|
|
"""Read the documented env knobs, applying validation. `env=None` reads
|
|
from `os.environ`."""
|
|
source = os.environ if env is None else env
|
|
return UiEnv(
|
|
api_host=_parse_host(source.get("API_HOST")),
|
|
api_port=_parse_port(source.get("API_PORT")),
|
|
api_key=_parse_key(source.get("API_KEY")),
|
|
gradio_host=_parse_host(source.get("GRADIO_HOST")),
|
|
gradio_port=_parse_port(source.get("GRADIO_PORT")),
|
|
)
|