Bug:- websocket_base_url derivation corrupts URLs containing http:// in query params

当你在 OpenAI Python SDK 中没有显式指定 websocket_base_url ,且 base_url 的查询参数或路径中本身就含有 http:// 字符串时,SDK 生成 WebSocket 地址会把内嵌的 http:// 一并改写成 ws:// ,导致 URL 被破坏。优先检查

快速结论:当你在 OpenAI Python SDK 中没有显式指定 websocket_base_url,且 base_url 的查询参数或路径中本身就含有 http:// 字符串时,SDK 生成 WebSocket 地址会把内嵌的 http:// 一并改写成 ws://,导致 URL 被破坏。优先检查 base_url 里是否带有 target=http://... 之类的参数,并升级到已修复的主分支版本。

适用环境:OpenAI Python SDK(Issue 提交时为 main 分支),Python 3.x。Issue 中未确认具体的小版本号、操作系统、CUDA、显卡或依赖版本。

最快修复方案:升级到已合并修复的主分支版本。Issue 关闭说明中提到,#3971 与 #3999 已修复 base-URL 的 query/path 保留问题(含 Realtime),并已合并进 main;当前 WebSocket URL 处理已不再使用 str.replace()。

注意事项:Issue 中提到的 startswith() 改写只是报告者给出的建议方案,并非最终的已验证修复方式;最终修复采用 httpx 的 URL 操作(copy_with(scheme=ws_scheme))。另外,src/openai/_client.py 的部分 docstring 在 Issue 讨论时仍描述旧的字符串替换行为,文档与实际实现可能不一致,不影响运行时正确性。

问题场景

使用 OpenAI Python SDK 的 WebSocket 相关功能(如 Realtime 等)时,如果只传入 base_url 而不传 websocket_base_url,SDK 会从 base_url 推导出 WebSocket 地址。当 base_url 通过代理转发,并且其查询参数中携带了另一个后端地址(例如 ?target=http://backend.internal/v1)时,推导过程会误改写入参中的 URL。

报错原文

Bug:- websocket_base_url derivation corrupts URLs containing http:// in query params

base_url.replace("https://", "wss://").replace("http://", "ws://")

Expected result
wss://proxy.com/forward?target=http://backend.internal/v1

Actual result
wss://proxy.com/forward?target=ws://backend.internal/v1

原因分析

根本原因是推导 websocket_base_url 时使用了 Python 的 str.replace(),它会替换字符串中所有匹配项,而不仅仅是开头的协议前缀。因此当 http:// 出现在查询参数、路径片段等其他位置时,也会被错误地替换为 ws://,破坏了原始 URL。根据后续代码审查,当前 main 分支的相关 WebSocket 端点已改用 httpx 的 URL 操作,不再存在该替换逻辑,属于已修复的历史实现问题。

环境排查

  • 确认 OpenAI Python SDK 版本:是否为包含该 str.replace() 推导逻辑的旧版本。
  • 确认 base_url 是否包含查询参数或路径片段中内嵌的 http:// / https://,例如代理转发场景。
  • 确认是否显式设置了 websocket_base_url(显式设置可绕过自动推导)。
  • 确认 Python 版本为 3.x。
  • Issue 未提供 CUDA、显卡、PyTorch 或操作系统环境信息,这些项目与本问题无直接关系,无需作为排查重点。

解决步骤

  1. 先打印 client.websocket_base_url,确认推导结果中内嵌的 http:// 是否被错误改写成了 ws://,复现报告中的现象。
  2. 在代码中显式传入 websocket_base_url,绕过 SDK 的自动推导,作为临时规避手段(可优先尝试,能直接避免误替换)。
  3. 升级到已修复的版本:Issue 关闭说明指出 #3971 与 #3999 已修复 base-URL 的 query/path 保留问题(含 Realtime),并已合并进 main。升级后相关 WebSocket 端点使用 copy_with(scheme=ws_scheme) 进行 URL 转换。
  4. 不要仅依赖报告者建议的 startswith() 方案作为最终修复,因为实际合并的修复方式是基于 httpx URL 操作,二者实现不同。

验证方法

再次运行最小复现脚本,使用带查询参数的 base_url(如 https://proxy.com/forward?target=http://backend.internal/v1),检查 client.websocket_base_url 的输出:应保留参数中的 http://backend.internal/v1 不变,仅协议前缀被正确转换为 wss://。若输出与预期一致,说明问题已解决。

参考来源

openai/openai-python #3294

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 26893

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注