Files
kvm-manager/frontend/serve.py
T
admin 8ccccf8f52 feat: 多主机纳管、用户认证、noVNC控制台、深色主题
主要功能:
- 多主机管理: 支持TCP/SSH方式纳管远程KVM主机
- 用户认证: JWT token认证, 默认admin/admin123
- noVNC控制台: 前端集成noVNC, WebSocket代理VNC连接
- 深色主题: 全局Element Plus深色主题覆盖
- 虚拟机操作: 克隆、迁移、XML编辑、快照管理
- 资源监控: CPU/内存/磁盘IO/网络流量实时监控

Bug修复:
- libvirt getInfo()内存单位修正(MiB非KiB)
- 远程主机VNC 0.0.0.0监听地址连接策略修复
- Dashboard定时器内存泄漏修复
- bcrypt版本兼容性修复
2026-05-07 12:41:10 +08:00

92 sor
3.0 KiB
Python

"""Simple static file server for the KVM frontend with API proxy"""
import http.server
import urllib.request
import urllib.error
import os
import json
PORT = 8006
DIST_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "dist")
API_BASE = "http://127.0.0.1:8004"
class KVMHandler(http.server.SimpleHTTPRequestHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, directory=DIST_DIR, **kwargs)
def do_GET(self):
if self.path.startswith("/api/"):
self._proxy("GET")
elif self.path == "/" or self.path == "":
self.path = "/index.html"
super().do_GET()
else:
# SPA fallback: if file doesn't exist, serve index.html
file_path = os.path.join(DIST_DIR, self.path.lstrip("/"))
if os.path.isfile(file_path):
super().do_GET()
else:
self.path = "/index.html"
super().do_GET()
def do_POST(self):
if self.path.startswith("/api/"):
self._proxy("POST")
else:
self.send_error(404)
def do_PUT(self):
if self.path.startswith("/api/"):
self._proxy("PUT")
else:
self.send_error(404)
def do_DELETE(self):
if self.path.startswith("/api/"):
self._proxy("DELETE")
else:
self.send_error(404)
def _proxy(self, method):
"""Proxy API requests to backend"""
content_length = int(self.headers.get("Content-Length", 0))
body = self.rfile.read(content_length) if content_length > 0 else None
url = f"{API_BASE}{self.path}"
req = urllib.request.Request(url, data=body, method=method)
# Forward headers
for key in ["Content-Type", "Authorization"]:
if key in self.headers:
req.add_header(key, self.headers[key])
try:
with urllib.request.urlopen(req, timeout=30) as resp:
resp_body = resp.read()
self.send_response(resp.status)
self.send_header("Content-Type", "application/json")
self.send_header("Access-Control-Allow-Origin", "*")
self.end_headers()
self.wfile.write(resp_body)
except urllib.error.HTTPError as e:
resp_body = e.read()
self.send_response(e.code)
self.send_header("Content-Type", "application/json")
self.send_header("Access-Control-Allow-Origin", "*")
self.end_headers()
self.wfile.write(resp_body)
except Exception as e:
self.send_response(502)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(json.dumps({"error": str(e)}).encode())
def log_message(self, format, *args):
pass # Suppress logs
if __name__ == "__main__":
server = http.server.HTTPServer(("0.0.0.0", PORT), KVMHandler)
print(f"KVM Frontend serving on http://0.0.0.0:{PORT}")
server.serve_forever()