import os, secrets, hmac, hashlib, httpx, re import gradio as gr import spaces from fastapi import Request, Form from fastapi.responses import HTMLResponse, RedirectResponse ADMIN_TOKEN = os.environ.get("ADMIN_TOKEN", "") HF_TOKEN = os.environ.get("HF_TOKEN", "") PRIVATE_URL = os.environ.get("PRIVATE_URL", "") AUTH_HEADERS = {"Authorization": f"Bearer {HF_TOKEN}"} if HF_TOKEN else {} @spaces.GPU(duration=30) def _gpu(): return "" def make_token() -> str: raw = secrets.token_hex(16) key = ADMIN_TOKEN.encode() or b"" return raw + "." + hmac.new(key, raw.encode(), hashlib.sha256).hexdigest() def check_token(t: str) -> bool: if not t or "." not in t: return False p = t.split(".") k = ADMIN_TOKEN.encode() or b"" return hmac.compare_digest(p[1], hmac.new(k, p[0].encode(), hashlib.sha256).hexdigest()) def rewrite(html: str) -> str: for q in ['"', "'"]: for a in ["href", "src", "action"]: html = html.replace(f'{a}={q}/', f'{a}={q}/px/') return html LOGIN = 'VESTA
VESTA
Acceso al ecosistema
' with gr.Blocks(title="VESTA") as demo: gr.Markdown("") app = demo.app def cookie(req: Request) -> str: return req.cookies.get("vesta_session", "") @app.get("/login") async def login_get(req: Request): t = cookie(req) if check_token(t): return RedirectResponse(url="/px/") return HTMLResponse(LOGIN) @app.post("/login") async def do_login(user: str = Form(...), passw: str = Form(...)): if user.lower() != "admin" or passw != ADMIN_TOKEN: return RedirectResponse(url="/login?error=1", status_code=303) token = make_token() r = RedirectResponse(url="/px/", status_code=303) r.set_cookie("vesta_session", token, max_age=86400, path="/", httponly=True) return r @app.get("/logout") async def logout(): r = RedirectResponse(url="/login") r.delete_cookie("vesta_session", path="/") return r @app.get("/px/{rest:path}") async def proxy(req: Request, rest: str = ""): t = cookie(req) if not check_token(t): return RedirectResponse(url="/login") path = "/" + rest try: async with httpx.AsyncClient(timeout=30) as c: r = await c.get(f"{PRIVATE_URL}{path}", headers=AUTH_HEADERS) content = r.text if "text/html" in r.headers.get("content-type", ""): content = rewrite(content) return HTMLResponse(content) except Exception as e: return HTMLResponse(f"Error: {e}", 502) @app.post("/px/proxy/predict") async def predict(req: Request): if not check_token(cookie(req)): return HTMLResponse("NO_AUTH", 401) body = await req.json() async with httpx.AsyncClient(timeout=120) as c: r = await c.post(f"{PRIVATE_URL}/proxy/predict", json=body, headers=AUTH_HEADERS) return HTMLResponse(r.text, r.status_code) demo.launch(server_name="0.0.0.0", server_port=7860, ssr_mode=False, head="")