Files
firegex-traffic-viewer/backend/utils/loader.py
2023-09-22 20:46:50 +02:00

99 lines
3.6 KiB
Python

import os, httpx
from typing import Callable
from fastapi import APIRouter, WebSocket
import asyncio
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
from fastapi.middleware.cors import CORSMiddleware
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):
if DEBUG:
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@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: None|APIRouter
reset: None|Callable
startup: None|Callable
shutdown: None|Callable
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():
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
))
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])
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):
for func in resets: await run_func(func, reset_option)
async def startup():
for func in startups: await run_func(func)
async def shutdown():
for func in shutdowns: await run_func(func)
return reset, startup, shutdown