You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI Socketio WebSocket连接失败问题排查与解决

FastAPI + Socket.io WebSocket连接失败问题排查与解决

问题场景

使用FastAPI与Socket.io构建WebSocket服务时,出现前端连接失败的情况,相关代码如下:

ws.py

from loguru import logger
import socketio
from typing import List

def handle_connect(sid, environ):
    logger.info(f"Socket connected with sid {sid}")

class SocketManager:
    def __init__(self, origins: List[str]):
        self.server = socketio.AsyncServer(
            cors_allowed_origins=origins,
            async_mode="asgi",
            logger=True,
            engineio_logger=True,
        )
        self.app = socketio.ASGIApp(self.server)

    @property
    def on(self):
        return self.server.on

    @property
    def send(self):
        return self.server.send

    def mount_to(self, path: str, app: socketio.ASGIApp):
        app.mount(path, self.app)


socket_manager = SocketManager(origins=["*"])
socket_manager.on("connect", handler=handle_connect)

main.py

from ws import socket_manager

app = FastAPI(
    title="MyBackend",
    docs_url="/docs",
    openapi_url="/openapi.json"
)

app.include_router(router, prefix="/api/v1")
socket_manager.mount_to("/ws", app)

错误信息

前端控制台报错

WebSocket connection to 'ws://localhost:80/ws/' failed

后端日志报错

RuntimeError: Expected ASGI message 'websocket.accept' or 'websocket.close', but got 'http.response.start'.
DEBUG:    > HTTP/1.1 101 Switching Protocols
DEBUG:    > Upgrade: websocket
DEBUG:    > Connection: Upgrade
DEBUG:    > Sec-WebSocket-Accept: TDJXRnQoVA7XR0L7D7yn+va91Q4=
DEBUG:    > Sec-WebSocket-Extensions: permessage-deflate
DEBUG:    > date: Sun, 26 Feb 2023 21:04:11 GMT
DEBUG:    > server: uvicorn
INFO:     connection open
DEBUG:    = connection is OPEN
DEBUG:    = connection is CLOSED
DEBUG:    ! failing connection with code 1006
DEBUG:    x half-closing TCP connection
INFO:     connection closed

问题原因

  1. 参数类型错误:SocketManager的mount_to方法参数标注为socketio.ASGIApp,但实际传入的是FastAPI实例,类型不匹配导致挂载逻辑异常。
  2. 连接路径错误:前端直接访问挂载路径/ws/,但Socket.io要求客户端通过/socket.io子路径建立连接,直接访问根路径会被FastAPI当作普通HTTP请求处理,引发协议不匹配错误。

解决方法

1. 修复mount_to方法类型标注

修改ws.py中的mount_to方法,修正参数类型并导入FastAPI类型:

from fastapi import FastAPI  # 新增导入

# ... 其他代码不变

def mount_to(self, path: str, app: FastAPI):  # 将参数类型改为FastAPI
    app.mount(path, self.app)

2. 调整前端连接路径

Socket.io客户端需要通过/socket.io子路径连接,正确的WebSocket地址应为:

ws://localhost:80/ws/socket.io/?EIO=4&transport=websocket

若使用Socket.io官方客户端,初始化代码应改为:

const socket = io('http://localhost:80', { path: '/ws/socket.io' });

3. 验证修复后的完整代码

修正后的ws.py

from loguru import logger
import socketio
from typing import List
from fastapi import FastAPI

def handle_connect(sid, environ):
    logger.info(f"Socket connected with sid {sid}")

class SocketManager:
    def __init__(self, origins: List[str]):
        self.server = socketio.AsyncServer(
            cors_allowed_origins=origins,
            async_mode="asgi",
            logger=True,
            engineio_logger=True,
        )
        self.app = socketio.ASGIApp(self.server)

    @property
    def on(self):
        return self.server.on

    @property
    def send(self):
        return self.server.send

    def mount_to(self, path: str, app: FastAPI):
        app.mount(path, self.app)


socket_manager = SocketManager(origins=["*"])
socket_manager.on("connect", handler=handle_connect)

修正后的main.py

from fastapi import FastAPI
from ws import socket_manager

app = FastAPI(
    title="MyBackend",
    docs_url="/docs",
    openapi_url="/openapi.json"
)

app.include_router(router, prefix="/api/v1")
socket_manager.mount_to("/ws", app)

额外说明

  • 错误码1006属于Socket.io的异常关闭码,多数由协议不匹配、路径错误或CORS配置问题导致。
  • Socket.io的ASGI应用挂载后,必须通过/socket.io子路径建立连接,不能直接访问挂载的根路径。

内容的提问来源于stack exchange,提问作者haku

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 06:12:26