larksuite / larksuite/oapi-sdk-python
[Feature Request] Expose public WebSocket proxy/connect options on ws.Client
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 559
- Forks
- 102
- PR merge metrics
- No merged PRs in 30d
Description
English
Problem
lark.ws.Client currently forces a direct WebSocket connection on websockets 15 by returning {"proxy": None} from the private module-level helper _ws_connect_kwargs():
The result is passed to websockets.connect() here:
This preserves the SDK's historical direct-connect behavior, but applications whose outbound traffic must use an HTTP/HTTPS/SOCKS proxy have no supported way to let the event WebSocket honor HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, and NO_PROXY.
This is specifically about the long-lived event WebSocket. It is separate from HTTP API proxy support discussed in #82.
Current workaround
Applications must monkeypatch the private global helper:
import lark_oapi.ws.client as ws_client
# Let websockets 15 use its normal environment proxy discovery.
ws_client._ws_connect_kwargs = lambda: {}
One real-world adapter is here:
https://github.com/ZichaoLong/focus/blob/main/bot/feishu_ws_proxy.py
This workaround is fragile across SDK updates and process-global, so it cannot safely configure different Client instances independently.
Requested public API
Please expose a supported, per-Client way to configure the arguments or proxy policy used by websockets.connect().
Possible API shapes include:
lark.ws.Client(..., ws_proxy="env") # honor proxy environment variables
lark.ws.Client(..., ws_proxy="disabled") # force a direct connection
or:
lark.ws.Client(..., ws_connect_kwargs={"proxy": True})
The exact API shape is up to the maintainers. The important properties are:
- The existing default remains unchanged for backward compatibility.
- Configuration is per client instance, not a module-level global.
- The same policy is used for initial connection and reconnects.
- Environment proxy discovery, explicit proxy disabling, and ideally an explicit proxy URL can be represented.
- Callers no longer need to depend on
_ws_connect_kwargs.
Environment
- Latest PyPI release observed:
lark-oapi 1.7.1 - Also reproduced with:
lark-oapi 1.6.4 websockets 15.x
中文
问题
lark.ws.Client 当前会通过私有的模块级函数 _ws_connect_kwargs() 返回 {"proxy": None},从而在 websockets 15 下强制 WebSocket 直连:
返回值随后在这里传给 websockets.connect():
这一行为保留了 SDK 历史上的默认直连语义,但如果应用的出站网络必须经过 HTTP、HTTPS 或 SOCKS 代理,目前没有公开且受支持的方式,让事件 WebSocket 遵从 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY 和 NO_PROXY。
本 issue 只讨论长连接事件 WebSocket,与 #82 中的 HTTP API 代理支持是两个不同问题。
当前 workaround
应用目前只能 monkeypatch 私有的全局函数:
import lark_oapi.ws.client as ws_client
# 让 websockets 15 使用正常的环境变量代理发现行为。
ws_client._ws_connect_kwargs = lambda: {}
一个实际使用中的适配实现见:
https://github.com/ZichaoLong/focus/blob/main/bot/feishu_ws_proxy.py
这种方式依赖 SDK 私有实现,升级时容易失效;而且修改的是进程级全局状态,无法安全地为不同 Client 实例设置不同代理策略。
希望提供的公开接口
希望 Client 提供一个受支持、按实例生效的公开接口,用于配置传给 websockets.connect() 的参数或代理策略。
可能的接口形式例如:
lark.ws.Client(..., ws_proxy="env") # 遵从代理环境变量
lark.ws.Client(..., ws_proxy="disabled") # 强制直连
或者:
lark.ws.Client(..., ws_connect_kwargs={"proxy": True})
具体 API 形式由维护者决定。希望它至少满足:
- 默认行为保持不变,避免破坏现有调用方。
- 配置属于单个
Client实例,而不是模块级全局状态。 - 首次连接和后续重连使用相同策略。
- 能表达环境变量代理发现、显式禁用代理,最好也支持显式代理 URL。
- 调用方不再需要依赖私有的
_ws_connect_kwargs。
环境
- 当前观察到的 PyPI 最新版本:
lark-oapi 1.7.1 - 同样复现于:
lark-oapi 1.6.4 websockets 15.x
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read lark_oapi/ws/client.py around _ws_connect_kwargs() and the websockets.connect() call, then trace how initial connections and reconnects obtain their arguments. Define the public per-Client proxy configuration against the requested default, environment, disabled, and explicit-proxy behaviors, and verify that both connection paths use the same policy without relying on the module-level helper.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- networking
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100