From c4ebfb6432a70669fb4ba95d48179708cd1efbb8 Mon Sep 17 00:00:00 2001 From: "Gan, Jimmy" Date: Thu, 26 Feb 2026 03:11:13 +0800 Subject: [PATCH] feat: smart LAN detection for sidebar links via X-Forwarded-For and router probe --- dashboard/backend/main.py | 17 +++++++++++++++++ .../frontend/src/components/Sidebar.svelte | 8 ++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/dashboard/backend/main.py b/dashboard/backend/main.py index bc057fd..91afddb 100644 --- a/dashboard/backend/main.py +++ b/dashboard/backend/main.py @@ -114,6 +114,23 @@ async def startup_event(): async def health(): return {"status": "ok"} +@app.get("/api/client-ip") +async def client_ip(request: Request): + ip = request.headers.get("x-forwarded-for", "").split(",")[0].strip() or request.client.host + lan = ip.startswith("192.168.31.") or (ip.startswith("100.") and _router_reachable()) + return {"ip": ip, "lan": lan} + +def _router_reachable(): + import socket + try: + s = socket.socket() + s.settimeout(1) + s.connect(("192.168.31.1", 80)) + s.close() + return True + except Exception: + return False + # Public auth endpoints app.include_router(auth.router, prefix="/api/auth", tags=["auth"]) diff --git a/dashboard/frontend/src/components/Sidebar.svelte b/dashboard/frontend/src/components/Sidebar.svelte index cbd8bb4..8306a4a 100644 --- a/dashboard/frontend/src/components/Sidebar.svelte +++ b/dashboard/frontend/src/components/Sidebar.svelte @@ -12,10 +12,10 @@ const TS_IP = "100.78.131.124"; let lanReachable = $state(false); - if (typeof window !== "undefined" && location.hostname !== LAN_IP) { - fetch(`http://${LAN_IP}:4000/`, { mode: "no-cors", signal: AbortSignal.timeout(1500) }) - .then(() => { lanReachable = true; }) - .catch(() => {}); + if (typeof window !== "undefined") { + fetch("/api/client-ip").then(r => r.json()).then(d => { + if (d.lan) lanReachable = true; + }).catch(() => {}); } const media = [