Spaces:
Running
Running
| from __future__ import annotations | |
| import asyncio | |
| import json | |
| import threading | |
| from dataclasses import asdict | |
| from http import HTTPStatus | |
| from typing import Any, Callable | |
| from streamlit import config | |
| from streamlit.web.server.server_util import make_url_path_regex | |
| from tornado.routing import PathMatches, Rule | |
| from tornado.web import Application, RequestHandler | |
| from src.api.session_bootstrap import ( | |
| build_bootstrap_error_payload, | |
| build_session_bootstrap_payload, | |
| ) | |
| from src.core.logger import logger | |
| SESSION_BOOTSTRAP_ENDPOINT = "session/bootstrap" | |
| _patch_lock = threading.Lock() | |
| _patch_installed = False | |
| _original_create_app: Callable[..., Application] | None = None | |
| def build_session_bootstrap_path() -> str: | |
| base_path = (config.get_option("server.baseUrlPath") or "").strip("/") | |
| if not base_path: | |
| return "/session/bootstrap" | |
| return f"/{base_path}/session/bootstrap" | |
| class SessionBootstrapRequestHandler(RequestHandler): | |
| def set_default_headers(self) -> None: | |
| self.set_header("Access-Control-Allow-Origin", "*") | |
| self.set_header("Access-Control-Allow-Methods", "GET, OPTIONS") | |
| self.set_header("Access-Control-Allow-Headers", "Content-Type") | |
| self.set_header("Cache-Control", "no-store") | |
| def options(self) -> None: | |
| self.set_status(HTTPStatus.NO_CONTENT) | |
| self.finish() | |
| async def get(self) -> None: | |
| try: | |
| payload = await asyncio.to_thread(build_session_bootstrap_payload) | |
| except Exception as exc: # pragma: no cover - integration behavior | |
| logger.exception("Failed to create session bootstrap payload: %s", exc) | |
| self._write_json( | |
| build_bootstrap_error_payload(exc), | |
| status=HTTPStatus.INTERNAL_SERVER_ERROR, | |
| ) | |
| return | |
| self._write_json(asdict(payload), status=HTTPStatus.OK) | |
| def _write_json(self, payload: dict[str, Any], *, status: HTTPStatus) -> None: | |
| self.set_status(status) | |
| self.set_header("Content-Type", "application/json; charset=utf-8") | |
| self.finish(json.dumps(payload)) | |
| def install_streamlit_bootstrap_route() -> None: | |
| global _patch_installed, _original_create_app | |
| if _patch_installed: | |
| return | |
| with _patch_lock: | |
| if _patch_installed: | |
| return | |
| from streamlit.web.server import server as server_module | |
| _original_create_app = server_module.Server._create_app | |
| def _patched_create_app(self: Any) -> Application: | |
| app = _original_create_app(self) | |
| _install_route_on_app(app) | |
| return app | |
| server_module.Server._create_app = _patched_create_app | |
| _patch_installed = True | |
| logger.info( | |
| "Installed Streamlit bootstrap route at %s", | |
| build_session_bootstrap_path(), | |
| ) | |
| def _install_route_on_app(app: Application) -> None: | |
| if getattr(app, "_open_voice_bootstrap_route_installed", False): | |
| return | |
| base = config.get_option("server.baseUrlPath") | |
| pattern = make_url_path_regex(base, SESSION_BOOTSTRAP_ENDPOINT) | |
| # Ensure this route is checked before Streamlit's static catch-all route. | |
| app.wildcard_router.rules.insert( | |
| 0, | |
| Rule(PathMatches(pattern), SessionBootstrapRequestHandler), | |
| ) | |
| setattr(app, "_open_voice_bootstrap_route_installed", True) | |