LAN access: bind 0.0.0.0 + expose LAN URL (capabilities.lan, UI badge)

This commit is contained in:
2026-08-10 20:46:06 +07:00
parent a0d8725541
commit d31e226f00
5 changed files with 112 additions and 6 deletions
+41
View File
@@ -12,6 +12,7 @@ import os
import sys
import json
import shutil
import socket
import functools
from app.config import settings
@@ -326,6 +327,29 @@ def default_soundfont_dirs() -> list:
return ["/opt/daw_engine/soundfonts", os.path.expanduser("~/.sf2")]
def _lan_ips() -> list:
"""IPv4 của máy trên mạng LAN (bỏ loopback) — để client browser ở máy
khác mở app qua địa chỉ này. Stdlib only (không kéo thư viện ngoài)."""
ips = []
try:
# IP ra mạng theo default route — không gửi gói tin thật
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.connect(("8.8.8.8", 80))
ip = s.getsockname()[0]
if ip and not ip.startswith("127.") and ip not in ips:
ips.append(ip)
except Exception:
pass
# Enumerate thêm các interface khác (multi-NIC)
try:
for info in socket.getaddrinfo(socket.gethostname(), None, socket.AF_INET):
ip = info[4][0]
if ip and not ip.startswith("127.") and ip not in ips:
ips.append(ip)
except Exception:
pass
return ips
@functools.lru_cache(maxsize=1)
def detect() -> dict:
"""Detect 1 lần (cache toàn cục) — kết quả bất biến trong 1 tiến trình."""
@@ -359,6 +383,20 @@ def _vst_render_available() -> bool:
return False
def _lan_info() -> dict:
"""Địa chỉ + port để client LAN mở app. Port: SF_PORT (desktop engine chọn
trước, 8000-8010) hoặc 8000 mặc định."""
try:
port = int(os.environ.get("SF_PORT") or "8000")
except ValueError:
port = 8000
ips = _lan_ips()
return {
"ips": ips,
"port": port,
"urls": [f"http://{ip}:{port}" for ip in ips],
}
def capabilities() -> dict:
"""Capabilities API — frontend gọi 1 lần lúc boot để bật/tắt tính năng."""
d = detect()
@@ -378,6 +416,9 @@ def capabilities() -> dict:
"platform": d["platform"],
"docker": d["docker"],
"environment": d["environment"],
# LAN access (chỉ standalone): URL để client browser ở máy khác trên
# mạng mở app. Docker (container) → bỏ qua (IP container không dùng được).
**({"lan": _lan_info()} if not d["docker"] else {}),
"features": features,
"default_dirs": {
"vst": d["default_vst_dirs"],