FastAPI/Starlette中websocket.close()方法不支持reason参数问题求助
解决WebSocket.close() 报"unexpected keyword argument 'reason'"的问题
这个报错的根源很直接:Starlette(以及FastAPI基于它实现的WebSocket接口)的WebSocket.close()方法根本不支持reason这个关键字参数——你可能是把它和其他WebSocket库(比如原生的websockets库)的API搞混了,Starlette的封装做了简化,没有暴露这个参数。
要让客户端知道连接被拒绝的具体原因,你可以用下面两种更可靠的方式:
方案一:先发送原因消息再关闭(推荐)
这是兼容性最好的做法,先给客户端主动发送一条文本消息说明拒绝原因,再调用关闭方法:
# 先给客户端发送拒绝原因 await websocket.send_text("Connection refused as session already exists for user") # 选择更贴合场景的关闭码:1008 代表"Policy Violation"(违反策略),比1000(正常关闭)更合适 await websocket.close(code=1008)
客户端可以在监听消息的回调里收到这条文本,然后处理关闭逻辑,体验更友好。
方案二:手动构造ASGI关闭帧(兼容性差,不推荐)
如果一定要通过WebSocket关闭帧的reason字段传递信息,你需要绕开Starlette的封装,直接构造ASGI的关闭消息。但要注意,很多客户端框架可能不会主动解析这个reason字段,所以这种方式的兼容性不如方案一:
await websocket.send({ "type": "websocket.close", "code": 1008, "reason": b"Connection refused as session already exists for user" # 注意必须是字节串 })
另外补充一句:选择合适的关闭码很重要,比如你的场景是因为用户已有活跃连接而拒绝,用1008(策略违反)比默认的1000(正常关闭)更符合WebSocket协议的语义,客户端也能通过关闭码快速判断关闭类型。
内容的提问来源于stack exchange,提问作者heaVenShaker




