Spaces:
Sleeping
Sleeping
| """Space entrypoint: physix.server.app:app + static UI mount. | |
| Imported at runtime by the Dockerfile's CMD via ``uvicorn _space_app:app``. | |
| What this wrapper adds on top of ``physix.server.app:app``: | |
| 1. ``GET /`` -> 302 to ``/web/`` (so the bare Space URL | |
| doesn't 404 — OpenEnv's ``create_fastapi_app`` | |
| does NOT add a root redirect; that's only in | |
| the higher-level wrapper which mounts Gradio | |
| at ``/web`` and would clobber our React SPA). | |
| 2. ``GET /web`` -> 302 to ``/web/`` (same reason; users hit the | |
| no-trailing-slash variant from outside links). | |
| 3. ``StaticFiles`` mount at ``/web/`` serving the built Vite SPA. The | |
| vite build was run with ``--base=/web/`` so all asset URLs in the | |
| emitted ``index.html`` already include the prefix. | |
| Kept as a real .py file (not a heredoc inside the Dockerfile) so any | |
| syntax error is caught by the build's static analysis rather than at | |
| runtime — saved several deploy-fail loops in earlier iterations. | |
| """ | |
| from __future__ import annotations | |
| from pathlib import Path | |
| from fastapi.responses import RedirectResponse | |
| from fastapi.staticfiles import StaticFiles | |
| from physix.server.app import app | |
| _STATIC_DIR = Path("/app/static") | |
| async def _root_redirect() -> RedirectResponse: | |
| return RedirectResponse(url="/web/") | |
| async def _web_no_slash_redirect() -> RedirectResponse: | |
| return RedirectResponse(url="/web/") | |
| if _STATIC_DIR.is_dir(): | |
| # html=True makes StaticFiles serve index.html for directory hits and | |
| # fall back to it for unknown sub-paths (so client-side React routing | |
| # works). Mounted last so registered API routes (/web/metadata, | |
| # /web/reset, /web/step from OpenEnv; /interactive/* from physix) | |
| # always win over the static handler. | |
| app.mount( | |
| "/web", | |
| StaticFiles(directory=str(_STATIC_DIR), html=True), | |
| name="ui", | |
| ) | |