File size: 2,614 Bytes
f7b9253
c4fab07
 
f7b9253
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c4fab07
 
 
 
 
 
 
 
f7b9253
 
c4fab07
f7b9253
c4fab07
 
 
 
 
f7b9253
 
 
 
 
 
 
 
 
 
 
 
c4fab07
 
 
 
 
 
 
 
f7b9253
c4fab07
f7b9253
 
 
c4fab07
 
 
 
 
 
 
f7b9253
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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",
)

@app.middleware("http")
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

@app.get("/figvam")
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="/")