"""프록시 상태 및 통계.""" from __future__ import annotations import sqlite3 import time from fastapi import APIRouter from config_io import LOG_DB, load_config, touch_restart_signal router = APIRouter() @router.get("/status") def status() -> dict: cfg = load_config() total = allowed = blocked = errored = 0 last_ts: float | None = None if LOG_DB.exists(): con = sqlite3.connect(LOG_DB) try: total = con.execute("SELECT COUNT(*) FROM connections").fetchone()[0] allowed = con.execute( "SELECT COUNT(*) FROM connections WHERE action='allowed'" ).fetchone()[0] blocked = con.execute( "SELECT COUNT(*) FROM connections WHERE action='blocked'" ).fetchone()[0] errored = con.execute( "SELECT COUNT(*) FROM connections WHERE action='error'" ).fetchone()[0] row = con.execute( "SELECT ts FROM connections ORDER BY id DESC LIMIT 1" ).fetchone() last_ts = row[0] if row else None finally: con.close() return { "proxy_enabled": cfg.get("proxy", {}).get("enabled", True), "listen_port": cfg.get("proxy", {}).get("listen_port"), "backend": cfg.get("backend"), "domain_count": len(cfg.get("allowed_domains", [])), "stats": { "total": total, "allowed": allowed, "blocked": blocked, "error": errored, "last_event_ts": last_ts, }, "server_time": time.time(), } @router.post("/proxy/restart") def restart_proxy() -> dict: """프록시 listener 를 강제로 stop → start 시킨다. config 가 바뀌지 않았어도 listener 자체를 재시작하기 때문에 단순 config reload 와는 다르다. (proxy watcher 가 별도 신호 파일을 폴링) """ ts = touch_restart_signal() return {"ok": True, "restart_signal_ts": ts}