Spaces:
Running
Running
| import os, socket, threading, webbrowser, time | |
| import gradio as gr | |
| from fastapi import FastAPI, Request | |
| from fastapi.responses import RedirectResponse, PlainTextResponse | |
| import uvicorn | |
| 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() | |
| HOST = "0.0.0.0" | |
| PORT = int(os.getenv("PORT", 7860)) | |
| ADMIN_USER = os.getenv("ADMIN_USER", "admin") | |
| ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD", "admin") | |
| # ── RATE LIMITER ────────────────────────────────────────────────────── | |
| limiter = Limiter(key_func=get_remote_address, default_limits=["60/minute"]) | |
| # ── ДОДАТКИ ─────────────────────────────────────────────────────────── | |
| app_showcase = build_showcase_app() | |
| app_admin = build_admin_app() | |
| # ── FASTAPI ─────────────────────────────────────────────────────────── | |
| 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", "/queue/", "/upload", | |
| "/.git", "/static/../", | |
| ) | |
| async def security_middleware(request: Request, call_next): | |
| path = request.url.path.lower() | |
| for blocked in BLOCKED_PATHS: | |
| if path.startswith(blocked): | |
| return PlainTextResponse("404 Not Found", status_code=404) | |
| if ".." in path or "%2e" in path or "%2f" in path: | |
| return PlainTextResponse("400 Bad Request", status_code=400) | |
| ua = request.headers.get("user-agent", "").lower() | |
| bad_agents = ("sqlmap", "nikto", "nmap", "masscan", "zgrab") | |
| if any(b in ua for b in bad_agents): | |
| return PlainTextResponse("403 Forbidden", status_code=403) | |
| response = await call_next(request) | |
| response.headers["X-Content-Type-Options"] = "nosniff" | |
| response.headers["X-Frame-Options"] = "SAMEORIGIN" | |
| response.headers["X-XSS-Protection"] = "1; mode=block" | |
| response.headers["Referrer-Policy"] = "no-referrer" | |
| 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="/") | |
| # ── ЛОКАЛЬНИЙ ЗАПУСК ────────────────────────────────────────────────── | |
| def wait_and_open(): | |
| for _ in range(40): | |
| try: | |
| with socket.create_connection(("localhost", PORT), timeout=1): | |
| webbrowser.open(f"http://localhost:{PORT}") | |
| return | |
| except OSError: | |
| time.sleep(0.5) | |
| if __name__ == "__main__": | |
| threading.Thread(target=wait_and_open, daemon=True).start() | |
| uvicorn.run(app, host=HOST, port=PORT, log_level="warning") | |