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

FastAPI WebSocket握手失败:UnicodeEncodeError问题排查与解决

FastAPI WebSocket握手失败:UnicodeEncodeError 问题排查与解决

问题场景

使用FastAPI 0.89.1搭配websockets 12.0实现WebSocket功能,路由代码如下:

@router.websocket("/ws/{room_id}")
async def websocket_endpoint(ws: WebSocket, room_id: str, token: str):
    """
    Handles WebSocket communication for a specific room.
    """
    # 业务逻辑代码

运行时触发UnicodeEncodeError: 'ascii' codec can't encode characters in position 5-6: ordinal not in range(128)错误,WebSocket握手直接失败,提示opening handshake failed,回溯信息:

Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/websockets/legacy/server.py", line 167, in handler
    await self.handshake(
  File "/usr/local/lib/python3.11/site-packages/websockets/legacy/server.py", line 587, in handshake
    early_response = await early_response_awaitable

问题原因

核心是ASCII编码无法处理非ASCII字符,触发时机在握手阶段,常见诱因:

  • 路由参数room_id或请求参数token包含中文、emoji等非ASCII字符,websockets库在处理握手请求时默认使用ASCII编码解析URL相关内容,导致编码失败。
  • 运行环境的系统默认编码被设置为ASCII,强制websockets库用ASCII处理字符串。
  • websockets 12.0版本存在非ASCII字符处理的兼容性bug。

解决方法

1. 规范参数编码,服务端主动解码

要求客户端对非ASCII参数做URL编码(如中文转%E4%B8%AD%E6%96%87),服务端接收后解码:

from urllib.parse import unquote

@router.websocket("/ws/{room_id}")
async def websocket_endpoint(ws: WebSocket, room_id: str, token: str):
    # 解码URL编码的参数
    room_id = unquote(room_id)
    token = unquote(token)
    # 后续业务逻辑

2. 强制设置系统默认编码为UTF-8

在项目启动文件开头添加编码配置:

import locale

locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')

或启动服务时通过环境变量指定:

export PYTHONIOENCODING=utf-8
export LC_ALL=en_US.UTF-8
uvicorn main:app --host 0.0.0.0 --port 8000

3. 升级websockets版本

websockets 12.0的非ASCII字符处理存在缺陷,升级到更高稳定版本可修复:

pip install --upgrade websockets

4. 检查自定义握手逻辑

如果在握手前添加了自定义验证(如token解析),确保所有字符串操作使用UTF-8编码,避免显式调用ASCII编码转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 08:13:11