Spaces:
Running
Running
fix: harden bucket file serving
Browse files- Dockerfile +2 -0
- app.py +24 -10
Dockerfile
CHANGED
|
@@ -1,5 +1,7 @@
|
|
| 1 |
FROM python:3.12-slim
|
| 2 |
|
|
|
|
|
|
|
| 3 |
WORKDIR /app
|
| 4 |
|
| 5 |
COPY requirements.txt .
|
|
|
|
| 1 |
FROM python:3.12-slim
|
| 2 |
|
| 3 |
+
ARG LEADERBOARD_BUILD_ID=20260620_leaderboard_slug
|
| 4 |
+
|
| 5 |
WORKDIR /app
|
| 6 |
|
| 7 |
COPY requirements.txt .
|
app.py
CHANGED
|
@@ -12,7 +12,7 @@ from pathlib import Path
|
|
| 12 |
from typing import Any
|
| 13 |
|
| 14 |
from fastapi import FastAPI, Header, HTTPException
|
| 15 |
-
from fastapi.responses import
|
| 16 |
|
| 17 |
from leaderboard_core import DEFAULT_MAX_AGE_DAYS, DEFAULT_MIN_DOWNLOADS, DEFAULT_TOP_N, refresh
|
| 18 |
|
|
@@ -65,7 +65,18 @@ def latest_json() -> Path:
|
|
| 65 |
def read_json(path: Path) -> dict[str, Any]:
|
| 66 |
if not path.exists():
|
| 67 |
return {}
|
| 68 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
|
| 71 |
def run_refresh() -> dict[str, Any]:
|
|
@@ -144,7 +155,7 @@ def loading_page() -> str:
|
|
| 144 |
def index():
|
| 145 |
path = latest_html()
|
| 146 |
if path.exists():
|
| 147 |
-
return
|
| 148 |
return HTMLResponse(loading_page(), status_code=202)
|
| 149 |
|
| 150 |
|
|
@@ -155,23 +166,26 @@ def healthz() -> dict[str, Any]:
|
|
| 155 |
"data_dir": str(data_dir()),
|
| 156 |
"has_html": latest_html().exists(),
|
| 157 |
"has_json": latest_json().exists(),
|
|
|
|
|
|
|
|
|
|
| 158 |
}
|
| 159 |
|
| 160 |
|
| 161 |
@app.get("/api/summary", response_model=None)
|
| 162 |
def api_summary():
|
| 163 |
-
|
| 164 |
-
if not
|
| 165 |
return JSONResponse({"status": "initializing"}, status_code=202)
|
| 166 |
-
return
|
| 167 |
|
| 168 |
|
| 169 |
@app.get("/api/leaderboard", response_model=None)
|
| 170 |
def api_leaderboard():
|
| 171 |
-
|
| 172 |
-
if not
|
| 173 |
return JSONResponse({"status": "initializing"}, status_code=202)
|
| 174 |
-
return
|
| 175 |
|
| 176 |
|
| 177 |
@app.get("/latest/{filename}", response_model=None)
|
|
@@ -185,7 +199,7 @@ def latest_file(filename: str):
|
|
| 185 |
media_type = "application/json" if filename.endswith(".json") else "text/plain"
|
| 186 |
if filename.endswith(".csv"):
|
| 187 |
media_type = "text/csv"
|
| 188 |
-
return
|
| 189 |
|
| 190 |
|
| 191 |
@app.post("/api/refresh", response_model=None)
|
|
|
|
| 12 |
from typing import Any
|
| 13 |
|
| 14 |
from fastapi import FastAPI, Header, HTTPException
|
| 15 |
+
from fastapi.responses import HTMLResponse, JSONResponse, Response
|
| 16 |
|
| 17 |
from leaderboard_core import DEFAULT_MAX_AGE_DAYS, DEFAULT_MIN_DOWNLOADS, DEFAULT_TOP_N, refresh
|
| 18 |
|
|
|
|
| 65 |
def read_json(path: Path) -> dict[str, Any]:
|
| 66 |
if not path.exists():
|
| 67 |
return {}
|
| 68 |
+
try:
|
| 69 |
+
return json.loads(path.read_text(encoding="utf-8"))
|
| 70 |
+
except Exception as err: # noqa: BLE001
|
| 71 |
+
print(f"failed to read json {path}: {err}", flush=True)
|
| 72 |
+
return {}
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def file_size(path: Path) -> int | None:
|
| 76 |
+
try:
|
| 77 |
+
return path.stat().st_size
|
| 78 |
+
except OSError:
|
| 79 |
+
return None
|
| 80 |
|
| 81 |
|
| 82 |
def run_refresh() -> dict[str, Any]:
|
|
|
|
| 155 |
def index():
|
| 156 |
path = latest_html()
|
| 157 |
if path.exists():
|
| 158 |
+
return HTMLResponse(path.read_text(encoding="utf-8"))
|
| 159 |
return HTMLResponse(loading_page(), status_code=202)
|
| 160 |
|
| 161 |
|
|
|
|
| 166 |
"data_dir": str(data_dir()),
|
| 167 |
"has_html": latest_html().exists(),
|
| 168 |
"has_json": latest_json().exists(),
|
| 169 |
+
"html_size": file_size(latest_html()),
|
| 170 |
+
"json_size": file_size(latest_json()),
|
| 171 |
+
"summary_size": file_size(latest_dir() / "summary.json"),
|
| 172 |
}
|
| 173 |
|
| 174 |
|
| 175 |
@app.get("/api/summary", response_model=None)
|
| 176 |
def api_summary():
|
| 177 |
+
path = latest_dir() / "summary.json"
|
| 178 |
+
if not path.exists():
|
| 179 |
return JSONResponse({"status": "initializing"}, status_code=202)
|
| 180 |
+
return Response(path.read_bytes(), media_type="application/json")
|
| 181 |
|
| 182 |
|
| 183 |
@app.get("/api/leaderboard", response_model=None)
|
| 184 |
def api_leaderboard():
|
| 185 |
+
path = latest_json()
|
| 186 |
+
if not path.exists():
|
| 187 |
return JSONResponse({"status": "initializing"}, status_code=202)
|
| 188 |
+
return Response(path.read_bytes(), media_type="application/json")
|
| 189 |
|
| 190 |
|
| 191 |
@app.get("/latest/{filename}", response_model=None)
|
|
|
|
| 199 |
media_type = "application/json" if filename.endswith(".json") else "text/plain"
|
| 200 |
if filename.endswith(".csv"):
|
| 201 |
media_type = "text/csv"
|
| 202 |
+
return Response(path.read_bytes(), media_type=media_type)
|
| 203 |
|
| 204 |
|
| 205 |
@app.post("/api/refresh", response_model=None)
|