Spaces:
Running
Running
| import os | |
| import re | |
| import traceback | |
| import gradio as gr | |
| from fastapi import FastAPI, Request | |
| from fastapi.responses import RedirectResponse, PlainTextResponse | |
| from dotenv import load_dotenv | |
| from slowapi import Limiter, _rate_limit_exceeded_handler | |
| from slowapi.util import get_remote_address | |
| from slowapi.errors import RateLimitExceeded | |
| from showcase_ui import build_showcase_app | |
| from admin_ui import build_admin_app | |
| load_dotenv() | |
| ADMIN_USER = os.getenv("ADMIN_USER", "admin") | |
| ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD", "admin") | |
| # Патч: відключаємо get_api_info щоб уникнути 500 | |
| try: | |
| import gradio.blocks as _gb | |
| _gb.Blocks.get_api_info = lambda self, *a, **kw: {"named_endpoints": {}, "unnamed_endpoints": {}} | |
| print("[OK] get_api_info patched") | |
| except Exception: | |
| traceback.print_exc() | |
| limiter = Limiter(key_func=get_remote_address, default_limits=["60/minute"]) | |
| print("[..] building showcase...") | |
| app_showcase = build_showcase_app() | |
| print("[OK] showcase built") | |
| print("[..] building admin...") | |
| app_admin = build_admin_app() | |
| print("[OK] admin built") | |
| app = FastAPI() | |
| app.state.limiter = limiter | |
| app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler) | |
| BLOCKED_PATHS = ( | |
| "/config.json", "/.env", "/utils.py", "/main.py", | |
| "/admin_ui.py", "/showcase_ui.py", "/.git", | |
| ) | |
| async def security_middleware(request: Request, call_next): | |
| path = request.url.path | |
| # Нормалізуємо подвійні слеші: //figvam/ -> /figvam/ | |
| clean_path = re.sub(r'/{2,}', '/', path) | |
| if clean_path != path: | |
| return RedirectResponse(url=clean_path, status_code=301) | |
| path_lower = path.lower() | |
| for blocked in BLOCKED_PATHS: | |
| if path_lower.startswith(blocked): | |
| return PlainTextResponse("404 Not Found", status_code=404) | |
| if ".." in path or "%2e%2e" in path: | |
| return PlainTextResponse("400 Bad Request", status_code=400) | |
| try: | |
| response = await call_next(request) | |
| except Exception: | |
| traceback.print_exc() | |
| return PlainTextResponse("500 Internal Server Error", status_code=500) | |
| response.headers["X-Content-Type-Options"] = "nosniff" | |
| response.headers["X-Frame-Options"] = "SAMEORIGIN" | |
| return response | |
| def redirect_admin(): | |
| return RedirectResponse(url="/figvam/") | |
| app = gr.mount_gradio_app(app, app_admin, path="/figvam", | |
| auth=(ADMIN_USER, ADMIN_PASSWORD), | |
| auth_message="Unstop Admin") | |
| app = gr.mount_gradio_app(app, app_showcase, path="/") | |