GET /api/cdn: probe status endpoint (public, read-only)

Latest state + kbps + ~1h history (20 samples). curl it to check the
CDN without digging through server.log.
This commit is contained in:
jozamudi committed 2026-08-31 15:23:36 +00:00
1 parent eea538ab17
commit a61e7dd0e7
1 file changed
+13 -1
+13 -1
View File
@@ -25,6 +25,9 @@ from . import db, upstream, users
ROOT = Path(__file__).parent.parent ROOT = Path(__file__).parent.parent
app = FastAPI(title="ani-web") app = FastAPI(title="ani-web")
# latest probe result + last 20 samples (~1h at 3-min spacing), for GET /api/cdn
_CDN = {"state": "unknown", "kbps": 0.0, "ts": 0.0, "hist": []}
def _cdn_probe(): def _cdn_probe():
"""Background probe: pull 64KB from the CDN every 3 min and log state """Background probe: pull 64KB from the CDN every 3 min and log state
@@ -56,18 +59,27 @@ def _cdn_probe():
if now != state: if now != state:
print(f"[probe] CDN {now} ({kbps:.0f} KB/s)", flush=True) print(f"[probe] CDN {now} ({kbps:.0f} KB/s)", flush=True)
state = now state = now
_CDN.update(state=now, kbps=round(kbps), ts=time.time())
_CDN["hist"].append({"t": time.time(), "kbps": round(kbps)})
del _CDN["hist"][:-20]
time.sleep(180) time.sleep(180)
threading.Thread(target=_cdn_probe, daemon=True).start() threading.Thread(target=_cdn_probe, daemon=True).start()
@app.get("/api/cdn")
async def cdn_status():
"""CDN health (read-only, public): latest probe + ~1h of history."""
return _CDN
# ---------- auth: multi-user, signed cookies ---------- # ---------- auth: multi-user, signed cookies ----------
users.migrate_legacy() # file-based legacy import; db.init() absorbs its output users.migrate_legacy() # file-based legacy import; db.init() absorbs its output
db.init() db.init()
_SIGNER = TimestampSigner(users.get_secret()) _SIGNER = TimestampSigner(users.get_secret())
_SESSION = "aniweb_session" _SESSION = "aniweb_session"
_SESSION_AGE = 30 * 86400 _SESSION_AGE = 30 * 86400
_PUBLIC = {("/login", "GET"), ("/login", "POST")} _PUBLIC = {("/login", "GET"), ("/login", "POST"), ("/api/cdn", "GET")}
_SECURE = os.environ.get("ANIWEB_SECURE") == "1" # set when served over HTTPS _SECURE = os.environ.get("ANIWEB_SECURE") == "1" # set when served over HTTPS
# ponytail: in-memory lockout per username, single process — 5 fails -> 15 min # ponytail: in-memory lockout per username, single process — 5 fails -> 15 min