FastAPI 0.109+集成Socket.IO出现WebSocket路由错误问题排查
FastAPI 0.109+ 集成Socket.IO WebSocket服务连接异常问题排查与修复
问题原因
FastAPI 0.109版本开始重构了路由系统,对ASGI子应用的请求转发逻辑做了关键调整:
- 原
app.mount方式挂载socketio.ASGIApp时,FastAPI的路由中间件会优先将Socket.IO的HTTP握手请求判定为普通HTTP请求,找不到匹配路由就返回404 - WebSocket连接阶段,新版本对ASGI消息的类型和顺序校验更严格,Socket.IO的响应消息不符合FastAPI的预期,触发
RuntimeError
修复方案
方案1:改用socketio.AsyncServer.attach集成
放弃mount方式,直接将Socket.IO服务附加到FastAPI应用,指定Socket.IO的路径后缀:
from fastapi import FastAPI import socketio app = FastAPI() # 初始化异步Socket.IO服务器,按需配置跨域 sio = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins="*") # 定义Socket.IO事件 @sio.event async def connect(sid, environ): print(f"客户端 {sid} 已连接") @sio.event async def disconnect(sid): print(f"客户端 {sid} 已断开") # 附加到FastAPI应用,指定socket路径 sio.attach(app, socket_path="/ws/socket.io/")
客户端连接路径需改为:ws://your-domain:port/ws/socket.io/
方案2:用Starlette的Mount显式挂载ASGI应用
如果想保留原挂载路径结构,可通过Starlette的Mount类显式定义路由,绕过FastAPI默认的路由匹配逻辑:
from fastapi import FastAPI from starlette.mount import Mount import socketio sio = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins="*") socket_app = socketio.ASGIApp(sio) # 定义Socket.IO事件 @sio.event async def connect(sid, environ): print(f"客户端 {sid} 已连接") # 通过routes参数显式挂载 app = FastAPI( routes=[ Mount("/ws", app=socket_app) ] )
客户端连接路径保持原结构:ws://your-domain:port/ws/socket.io/
方案3:临时降级到FastAPI 0.108.0
如果暂时无法修改代码,可执行以下命令降级版本:
pip install fastapi==0.108.0
注意:这只是临时方案,长期来看建议适配新版本以获取安全和功能更新。
验证方法
- 测试HTTP握手:执行
curl http://localhost:8000/ws/socket.io/?EIO=4&transport=polling,应返回正常的握手响应而非404 - 测试WebSocket连接:用前端或Postman连接
ws://localhost:8000/ws/socket.io/,应成功建立连接,无RuntimeError触发
内容的提问来源于stack exchange,提问作者Eugene Snopok
相关产品推荐
相关产品推荐

