Spaces:
Running
Running
Upload 26 files
Browse files- Dockerfile +1 -1
- app.py +32 -4
Dockerfile
CHANGED
|
@@ -9,4 +9,4 @@ COPY . .
|
|
| 9 |
|
| 10 |
EXPOSE 7860
|
| 11 |
|
| 12 |
-
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860", "--log-level", "
|
|
|
|
| 9 |
|
| 10 |
EXPOSE 7860
|
| 11 |
|
| 12 |
+
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860", "--log-level", "trace"]
|
app.py
CHANGED
|
@@ -1,4 +1,6 @@
|
|
| 1 |
import os
|
|
|
|
|
|
|
| 2 |
import gradio as gr
|
| 3 |
from fastapi import FastAPI, Request
|
| 4 |
from fastapi.responses import RedirectResponse, PlainTextResponse
|
|
@@ -14,10 +16,23 @@ load_dotenv()
|
|
| 14 |
ADMIN_USER = os.getenv("ADMIN_USER", "admin")
|
| 15 |
ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD", "admin")
|
| 16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
limiter = Limiter(key_func=get_remote_address, default_limits=["60/minute"])
|
| 18 |
|
|
|
|
| 19 |
app_showcase = build_showcase_app()
|
| 20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
|
| 22 |
app = FastAPI()
|
| 23 |
app.state.limiter = limiter
|
|
@@ -30,13 +45,26 @@ BLOCKED_PATHS = (
|
|
| 30 |
|
| 31 |
@app.middleware("http")
|
| 32 |
async def security_middleware(request: Request, call_next):
|
| 33 |
-
path = request.url.path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
for blocked in BLOCKED_PATHS:
|
| 35 |
-
if
|
| 36 |
return PlainTextResponse("404 Not Found", status_code=404)
|
| 37 |
if ".." in path or "%2e%2e" in path:
|
| 38 |
return PlainTextResponse("400 Bad Request", status_code=400)
|
| 39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
response.headers["X-Content-Type-Options"] = "nosniff"
|
| 41 |
response.headers["X-Frame-Options"] = "SAMEORIGIN"
|
| 42 |
return response
|
|
|
|
| 1 |
import os
|
| 2 |
+
import re
|
| 3 |
+
import traceback
|
| 4 |
import gradio as gr
|
| 5 |
from fastapi import FastAPI, Request
|
| 6 |
from fastapi.responses import RedirectResponse, PlainTextResponse
|
|
|
|
| 16 |
ADMIN_USER = os.getenv("ADMIN_USER", "admin")
|
| 17 |
ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD", "admin")
|
| 18 |
|
| 19 |
+
# Патч: відключаємо get_api_info щоб уникнути 500
|
| 20 |
+
try:
|
| 21 |
+
import gradio.blocks as _gb
|
| 22 |
+
_gb.Blocks.get_api_info = lambda self, *a, **kw: {"named_endpoints": {}, "unnamed_endpoints": {}}
|
| 23 |
+
print("[OK] get_api_info patched")
|
| 24 |
+
except Exception:
|
| 25 |
+
traceback.print_exc()
|
| 26 |
+
|
| 27 |
limiter = Limiter(key_func=get_remote_address, default_limits=["60/minute"])
|
| 28 |
|
| 29 |
+
print("[..] building showcase...")
|
| 30 |
app_showcase = build_showcase_app()
|
| 31 |
+
print("[OK] showcase built")
|
| 32 |
+
|
| 33 |
+
print("[..] building admin...")
|
| 34 |
+
app_admin = build_admin_app()
|
| 35 |
+
print("[OK] admin built")
|
| 36 |
|
| 37 |
app = FastAPI()
|
| 38 |
app.state.limiter = limiter
|
|
|
|
| 45 |
|
| 46 |
@app.middleware("http")
|
| 47 |
async def security_middleware(request: Request, call_next):
|
| 48 |
+
path = request.url.path
|
| 49 |
+
|
| 50 |
+
# Нормалізуємо подвійні слеші: //figvam/ -> /figvam/
|
| 51 |
+
clean_path = re.sub(r'/{2,}', '/', path)
|
| 52 |
+
if clean_path != path:
|
| 53 |
+
return RedirectResponse(url=clean_path, status_code=301)
|
| 54 |
+
|
| 55 |
+
path_lower = path.lower()
|
| 56 |
for blocked in BLOCKED_PATHS:
|
| 57 |
+
if path_lower.startswith(blocked):
|
| 58 |
return PlainTextResponse("404 Not Found", status_code=404)
|
| 59 |
if ".." in path or "%2e%2e" in path:
|
| 60 |
return PlainTextResponse("400 Bad Request", status_code=400)
|
| 61 |
+
|
| 62 |
+
try:
|
| 63 |
+
response = await call_next(request)
|
| 64 |
+
except Exception:
|
| 65 |
+
traceback.print_exc()
|
| 66 |
+
return PlainTextResponse("500 Internal Server Error", status_code=500)
|
| 67 |
+
|
| 68 |
response.headers["X-Content-Type-Options"] = "nosniff"
|
| 69 |
response.headers["X-Frame-Options"] = "SAMEORIGIN"
|
| 70 |
return response
|