删除旧的main.py文件,将FastAPI应用创建逻辑集中在router/main.py中 添加直接运行router/main.py的支持 更新README.md以反映新的项目结构和使用方式 添加websocket连接测试脚本test_websocket.py
92 lines
2.3 KiB
Python
92 lines
2.3 KiB
Python
"""Router main module - FastAPI app factory.
|
|
|
|
Creates the FastAPI application with:
|
|
- Feishu WebSocket client
|
|
- Node WebSocket endpoint
|
|
- Health check endpoints
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import Optional
|
|
|
|
from fastapi import FastAPI, WebSocket
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
from bot.handler import start_websocket_client
|
|
from router.nodes import NodeRegistry, get_node_registry
|
|
from router.ws import ws_node_endpoint
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def create_app(router_secret: Optional[str] = None) -> FastAPI:
|
|
"""Create the FastAPI application.
|
|
|
|
Args:
|
|
router_secret: Secret for authenticating host client connections
|
|
"""
|
|
app = FastAPI(title="PhoneWork Router", version="3.0.0")
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
registry = get_node_registry()
|
|
if router_secret:
|
|
registry._secret = router_secret
|
|
|
|
@app.get("/health")
|
|
async def health():
|
|
from router.rpc import get_pending_count
|
|
nodes = registry.list_nodes()
|
|
online_nodes = [n for n in nodes if n["status"] == "online"]
|
|
return {
|
|
"status": "ok",
|
|
"nodes": nodes,
|
|
"online_nodes": len(online_nodes),
|
|
"total_nodes": len(nodes),
|
|
"pending_requests": get_pending_count(),
|
|
}
|
|
|
|
@app.get("/nodes")
|
|
async def list_nodes():
|
|
return registry.list_nodes()
|
|
|
|
@app.websocket("/ws/node")
|
|
async def ws_node(websocket: WebSocket):
|
|
await ws_node_endpoint(websocket)
|
|
|
|
@app.on_event("startup")
|
|
async def startup():
|
|
import asyncio
|
|
loop = asyncio.get_running_loop()
|
|
start_websocket_client(loop)
|
|
logger.info("Router started")
|
|
|
|
@app.on_event("shutdown")
|
|
async def shutdown():
|
|
logger.info("Router shut down")
|
|
|
|
return app
|
|
|
|
|
|
if __name__ == "__main__":
|
|
from config import PORT, ROUTER_SECRET
|
|
import uvicorn
|
|
app = create_app(router_secret=ROUTER_SECRET)
|
|
uvicorn.run(
|
|
"router.main:app",
|
|
host="0.0.0.0",
|
|
port=PORT,
|
|
reload=False,
|
|
log_level="info",
|
|
ws_ping_interval=20,
|
|
ws_ping_timeout=60,
|
|
)
|