feat: implement native subdomain routing (*.hub.yesminedor.tn) for seamless absolute assets resolution across all universes
This commit is contained in:
+50
-1
@@ -3,13 +3,46 @@ from fastapi.responses import HTMLResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from pathlib import Path
|
||||
from typing import Optional, Tuple
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from app.config import settings, UNIVERSES, BASE_DIR
|
||||
from app.routers import api, proxy
|
||||
from app.proxy import close_http_client
|
||||
from app.proxy import close_http_client, proxy_request
|
||||
from app.personas import ensure_dirs
|
||||
|
||||
def get_subdomain_target(host: str) -> Optional[Tuple[str, str]]:
|
||||
"""
|
||||
Inspects Host header and returns (target_backend_url, universe_id) if it matches a subdomain.
|
||||
Examples:
|
||||
tt.hub.yesminedor.tn -> (HERMES_TT_URL, 'tt')
|
||||
nyora.hub.yesminedor.tn -> (HERMES_NYORA_URL, 'nyora')
|
||||
perso.hub.yesminedor.tn -> (HERMES_PERSO_URL, 'perso')
|
||||
nabil.hub.yesminedor.tn -> (HERMES_NABIL_URL, 'nabil')
|
||||
dsh.hub.yesminedor.tn -> (DSH_FILEBROWSER_URL, 'nabil')
|
||||
"""
|
||||
if not host:
|
||||
return None
|
||||
|
||||
hostname = host.split(":")[0].lower()
|
||||
|
||||
sub = None
|
||||
if hostname.endswith(".hub.yesminedor.tn"):
|
||||
sub = hostname.rsplit(".hub.yesminedor.tn", 1)[0]
|
||||
elif hostname.endswith(".localhost"):
|
||||
sub = hostname.rsplit(".localhost", 1)[0]
|
||||
|
||||
if not sub or sub in ("hub", "www"):
|
||||
return None
|
||||
|
||||
if sub in ("dsh", "files", "dsh-files"):
|
||||
return (settings.dsh_filebrowser_url, "nabil")
|
||||
|
||||
if sub in UNIVERSES:
|
||||
return (UNIVERSES[sub].backend_url, sub)
|
||||
|
||||
return None
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
ensure_dirs()
|
||||
@@ -22,6 +55,22 @@ app = FastAPI(
|
||||
lifespan=lifespan
|
||||
)
|
||||
|
||||
# Subdomain Routing Middleware
|
||||
@app.middleware("http")
|
||||
async def subdomain_routing_middleware(request: Request, call_next):
|
||||
host = request.headers.get("host", "")
|
||||
target = get_subdomain_target(host)
|
||||
if target:
|
||||
backend_url, universe_id = target
|
||||
path = request.url.path
|
||||
return await proxy_request(
|
||||
request=request,
|
||||
backend_url=backend_url,
|
||||
path=path,
|
||||
universe_id=universe_id
|
||||
)
|
||||
return await call_next(request)
|
||||
|
||||
# Mount static files
|
||||
static_dir = BASE_DIR / "static"
|
||||
static_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
Reference in New Issue
Block a user