Files
Domingo Dirutigliano 8ae533e8f7 push: code changes x2
2025-02-28 21:14:09 +01:00

99 lines
3.7 KiB
Python

import os
import httpx
from typing import Callable
from fastapi import APIRouter
from starlette.responses import StreamingResponse
from fastapi.responses import FileResponse
from utils import DEBUG, ON_DOCKER, ROUTERS_DIR, list_files, run_func
from utils.models import ResetRequest
import asyncio
import traceback
REACT_BUILD_DIR: str = "../frontend/build/" if not ON_DOCKER else "frontend/"
REACT_HTML_PATH: str = os.path.join(REACT_BUILD_DIR,"index.html")
async def frontend_debug_proxy(path):
httpc = httpx.AsyncClient()
req = httpc.build_request("GET",f"http://127.0.0.1:{os.getenv('F_PORT','5173')}/"+path)
resp = await httpc.send(req, stream=True)
return StreamingResponse(resp.aiter_bytes(),status_code=resp.status_code, headers=resp.headers)
async def react_deploy(path):
file_request = os.path.join(REACT_BUILD_DIR, path)
if not os.path.isfile(file_request):
return FileResponse(REACT_HTML_PATH, media_type='text/html')
else:
return FileResponse(file_request)
def frontend_deploy(app):
@app.get("/{full_path:path}", include_in_schema=False)
async def catch_all(full_path:str):
if DEBUG:
try:
return await frontend_debug_proxy(full_path)
except Exception:
return {"details":"Frontend not started at "+f"http://127.0.0.1:{os.getenv('F_PORT','5173')}"}
else:
return await react_deploy(full_path)
def list_routers():
return [ele[:-3] for ele in list_files(ROUTERS_DIR) if ele != "__init__.py" and " " not in ele and ele.endswith(".py")]
class RouterModule():
router: APIRouter|None = None
reset: Callable|None = None
startup: Callable|None = None
shutdown: Callable|None = None
name: str
def __init__(self, router: APIRouter, reset: Callable, startup: Callable, shutdown: Callable, name:str):
self.router = router
self.reset = reset
self.startup = startup
self.shutdown = shutdown
self.name = name
def __repr__(self):
return f"RouterModule(router={self.router}, reset={self.reset}, startup={self.startup}, shutdown={self.shutdown})"
def get_router_modules():
res: list[RouterModule] = []
for route in list_routers():
try:
module = getattr(__import__(f"routers.{route}"), route, None)
if module:
res.append(RouterModule(
router=getattr(module, "app", None),
reset=getattr(module, "reset", None),
startup=getattr(module, "startup", None),
shutdown=getattr(module, "shutdown", None),
name=route
))
except Exception as e:
traceback.print_exc()
print(f"Router {route} failed to load: {e}")
return res
def load_routers(app):
resets, startups, shutdowns = [], [], []
for router in get_router_modules():
if router.router:
app.include_router(router.router, prefix=f"/{router.name}", tags=[router.name])
else:
print(f"Router {router.name} is not loaded")
continue
if router.reset:
resets.append(router.reset)
if router.startup:
startups.append(router.startup)
if router.shutdown:
shutdowns.append(router.shutdown)
async def reset(reset_option:ResetRequest):
await asyncio.gather(*[run_func(func, reset_option) for func in resets])
async def startup():
await asyncio.gather(*[run_func(func) for func in startups])
async def shutdown():
await asyncio.gather(*[run_func(func) for func in shutdowns])
return reset, startup, shutdown