#!/usr/bin/env python3 """ 支持 SPA 路由的静态文件服务器 将所有 404 请求重定向到 index.html """ import http.server import socketserver import os import sys from pathlib import Path PORT = 10000 DIRECTORY = Path(__file__).parent / "frontend" / "dist" class SPAHandler(http.server.SimpleHTTPRequestHandler): def __init__(self, *args, **kwargs): super().__init__(*args, directory=str(DIRECTORY), **kwargs) def log_message(self, format, *args): # 简化日志输出 sys.stderr.write(f"[{self.log_date_time_string()}] {args[0]}\n") def do_GET(self): # 检查请求的文件是否存在 file_path = DIRECTORY / self.path.lstrip('/').split('?')[0] # 如果文件不存在且不是静态资源,返回 index.html if not file_path.exists() and not self.path.startswith('/assets/'): self.path = '/index.html' return super().do_GET() def end_headers(self): self.send_header('Access-Control-Allow-Origin', '*') super().end_headers() class ReusableTCPServer(socketserver.TCPServer): allow_reuse_address = True daemon_threads = True if __name__ == "__main__": os.chdir(DIRECTORY) sys.stdout.write(f"🚀 SPA Server starting at http://0.0.0.0:{PORT}\n") sys.stdout.write(f"📁 Serving: {DIRECTORY}\n") sys.stdout.write("✓ SPA routing enabled (404s -> index.html)\n") sys.stdout.flush() try: with ReusableTCPServer(("0.0.0.0", PORT), SPAHandler) as httpd: httpd.serve_forever() except KeyboardInterrupt: sys.stdout.write("\n👋 Server stopped\n")