Files
H3ConuMS-v2/backend/app/api/v1/ws.py
T
v6ole fcfa5af614 feat: v0.10.0 生产环境优化 — HTTPS、前端生产构建、安全加固
- feat(deploy): 前端多阶段构建 (vite build + nginx:alpine),移除 Vite 开发模式
- feat(deploy): OpenResty HTTPS 配置 (SSL + HSTS + 安全头)
- fix(ws): WebSocket 路由添加 /api 前缀,修正前后端路径不匹配
- security: SSH AutoAddPolicy → WarningPolicy
- security: CORS 来源环境变量化 (CORS_ORIGINS)
- security: 限流器使用 X-Forwarded-For 真实客户端 IP
- perf(db): 数据库连接池配置 (pool_size=20, max_overflow=40)
- refactor: 移除硬编码 URL/IP (NTP、域名、微信代理),改为环境变量
- chore: 更新 .env.example 模板,补充新增配置项
- chore: 清理 .reasonix/、scripts/、guide.md 无用文件
- docs: 更新 CLAUDE.md 至 v0.10.0,补充生产架构文档

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 19:00:08 +08:00

47 lines
1.4 KiB
Python

"""WebSocket 实时推送"""
import asyncio
import json
import logging
import redis.asyncio as aioredis
from fastapi import APIRouter, WebSocket, WebSocketDisconnect
from app.core.config import settings
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api", tags=["WebSocket"])
REDIS_CHANNEL = "h3c_onu:status_updates"
_connected: set[WebSocket] = set()
async def _redis_listener():
"""监听 Redis pub/sub 并广播给所有 WebSocket 客户端"""
try:
r = aioredis.from_url(settings.REDIS_URL)
pubsub = r.pubsub()
await pubsub.subscribe(REDIS_CHANNEL)
logger.info("WebSocket Redis 监听已启动")
async for msg in pubsub.listen():
if msg["type"] == "message":
dead: set[WebSocket] = set()
for ws in _connected:
try:
await ws.send_text(msg["data"].decode())
except Exception:
dead.add(ws)
_connected -= dead
except Exception as e:
logger.error(f"Redis 监听异常: {e}")
@router.websocket("/ws/dashboard")
async def dashboard_ws(ws: WebSocket):
await ws.accept()
_connected.add(ws)
try:
while True:
await ws.receive_text() # keep-alive, 忽略客户端消息
except WebSocketDisconnect:
pass
finally:
_connected.discard(ws)