larksuite / larksuite/oapi-sdk-python

[Feature Request] Expose public WebSocket proxy/connect options on ws.Client

Open
#143 0 comments 1 reaction 0 assignees View on GitHub

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():

https://github.com/larksuite/oapi-sdk-python/blob/dcec8e409b46a7830d33584e3690e7719e7a992a/lark_oapi/ws/client.py#L73-L80

The result is passed to websockets.connect() here:

https://github.com/larksuite/oapi-sdk-python/blob/dcec8e409b46a7830d33584e3690e7719e7a992a/lark_oapi/ws/client.py#L193-L205

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 直连:

https://github.com/larksuite/oapi-sdk-python/blob/dcec8e409b46a7830d33584e3690e7719e7a992a/lark_oapi/ws/client.py#L73-L80

返回值随后在这里传给 websockets.connect()

https://github.com/larksuite/oapi-sdk-python/blob/dcec8e409b46a7830d33584e3690e7719e7a992a/lark_oapi/ws/client.py#L193-L205

这一行为保留了 SDK 历史上的默认直连语义,但如果应用的出站网络必须经过 HTTP、HTTPS 或 SOCKS 代理,目前没有公开且受支持的方式,让事件 WebSocket 遵从 HTTP_PROXYHTTPS_PROXYALL_PROXYNO_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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.