"""管理后台API路由 - 对应Go的api/admin_router.go""" from fastapi import APIRouter, Depends, HTTPException, Header, Query from typing import Optional from app.models import ( Response, ConfigListRequest, ConfigUpdateRequest, ReloadRequest, AdapterToggleRequest, AdapterConfigUpdateRequest, APITestRequest, WSTestRequest, TestHistoryRequest ) from app.services import ConfigService, AdapterService, TestService from app.core.config import get_config admin_router = APIRouter() # 服务实例 config_service = ConfigService() adapter_service = AdapterService() test_service = TestService() def verify_admin_token(x_admin_token: Optional[str] = Header(None)): """验证Admin Token""" # TODO: 实现Token验证 return x_admin_token # ============================================ # 系统管理接口 # ============================================ @admin_router.get("/admin/system/status", response_model=Response) def get_system_status( token: str = Depends(verify_admin_token) ): """获取系统状态""" try: data = config_service.get_system_status() return Response(code=0, message="success", data=data) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @admin_router.post("/admin/system/reload", response_model=Response) def reload_config( req: Optional[ReloadRequest] = None, token: str = Depends(verify_admin_token) ): """热加载配置""" try: if req is None: req = ReloadRequest() data = config_service.reload_config(req) return Response(code=0, message="success", data=data) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @admin_router.post("/admin/system/restart", response_model=Response) def restart_service( token: str = Depends(verify_admin_token) ): """重启服务 注意: 此方法通过创建子进程实现服务重启,适用于开发环境。 生产环境建议使用Docker或systemd管理服务生命周期。 """ import os import sys import subprocess import threading import time def delayed_restart(): """延迟重启函数""" time.sleep(2) # 等待当前响应返回 # 获取当前Python解释器和启动参数 python = sys.executable args = sys.argv[:] # 在Windows上使用start命令,在Linux上使用nohup if os.name == 'nt': # Windows subprocess.Popen( ['start', 'python'] + args, shell=True, creationflags=subprocess.CREATE_NEW_CONSOLE ) else: # Linux/Mac subprocess.Popen( [python] + args, stdout=open('/dev/null', 'w'), stderr=open('/dev/null', 'w'), start_new_session=True ) # 退出当前进程 os._exit(0) # 在后台线程中执行重启 restart_thread = threading.Thread(target=delayed_restart, daemon=True) restart_thread.start() return Response( code=0, message="服务将在2秒后重启", data={"status": "restarting", "delay_seconds": 2} ) # ============================================ # 配置管理接口 # ============================================ @admin_router.get("/admin/config", response_model=Response) def get_config_list( type: Optional[str] = Query(None, description="配置类型筛选"), token: str = Depends(verify_admin_token) ): """获取配置列表""" try: from app.models import ConfigType req = ConfigListRequest() if type: req.type = ConfigType(type) data = config_service.get_config_list(req) return Response(code=0, message="success", data=data) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @admin_router.put("/admin/config", response_model=Response) def update_config( req: ConfigUpdateRequest, token: str = Depends(verify_admin_token) ): """更新配置""" try: data = config_service.update_config(req) return Response(code=0, message="success", data=data) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @admin_router.post("/admin/config/reload", response_model=Response) def reload_config_endpoint( req: Optional[ReloadRequest] = None, token: str = Depends(verify_admin_token) ): """热加载配置""" return reload_config(req, token) # ============================================ # 适配器管理接口 # ============================================ @admin_router.get("/admin/adapters", response_model=Response) def get_adapter_list( token: str = Depends(verify_admin_token) ): """获取适配器列表""" try: data = adapter_service.get_adapter_list() return Response(code=0, message="success", data=data) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @admin_router.post("/admin/adapters/toggle", response_model=Response) def toggle_adapter( req: AdapterToggleRequest, token: str = Depends(verify_admin_token) ): """切换适配器状态""" try: adapter_service.toggle_adapter(req) return Response(code=0, message="success") except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @admin_router.put("/admin/adapters/config", response_model=Response) def update_adapter_config( req: AdapterConfigUpdateRequest, token: str = Depends(verify_admin_token) ): """更新适配器配置""" try: adapter_service.update_adapter_config(req) return Response(code=0, message="success") except Exception as e: raise HTTPException(status_code=500, detail=str(e)) # ============================================ # 测试管理接口 # ============================================ @admin_router.get("/admin/tests/api", response_model=Response) def get_api_test_list( token: str = Depends(verify_admin_token) ): """获取API测试列表""" try: data = test_service.get_api_test_list() # 设置基础URL config = get_config() data.base_url = f"http://localhost:{config.server.port}" return Response(code=0, message="success", data=data) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @admin_router.post("/admin/tests/api/run", response_model=Response) async def run_api_test( req: APITestRequest, token: str = Depends(verify_admin_token) ): """执行API测试""" try: config = get_config() base_url = f"http://localhost:{config.server.port}" data = await test_service.run_api_test(base_url, req) return Response(code=0, message="success", data=data) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @admin_router.get("/admin/tests/ws", response_model=Response) def get_ws_test_list( token: str = Depends(verify_admin_token) ): """获取WebSocket测试列表""" try: data = test_service.get_ws_test_list() config = get_config() data.ws_url = f"ws://localhost:{config.server.port}/v1/stream" return Response(code=0, message="success", data=data) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @admin_router.post("/admin/tests/ws/run", response_model=Response) async def run_ws_test( req: WSTestRequest, token: str = Depends(verify_admin_token) ): """执行WebSocket测试""" try: config = get_config() ws_url = f"ws://localhost:{config.server.port}/v1/stream" data = await test_service.run_ws_test(ws_url, req) return Response(code=0, message="success", data=data) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @admin_router.get("/admin/tests/history", response_model=Response) def get_test_history( type: Optional[str] = Query(None, description="测试类型"), limit: int = Query(default=20, ge=1, le=100, description="数量限制"), token: str = Depends(verify_admin_token) ): """获取测试历史""" try: req = TestHistoryRequest(type=type, limit=limit) data = test_service.get_test_history(req) return Response(code=0, message="success", data=data) except Exception as e: raise HTTPException(status_code=500, detail=str(e))