mirror of
https://github.com/hansjone/dsh-im-ops.git
synced 2026-10-08 23:13:17 +08:00
Merge pull request #103 from evanfang0054/fix/feishu-ws-honor-no-proxy
fix(feishu): honor NO_PROXY before proxying the long connection
This commit is contained in:
commit
165def416a
3 changed files with 351 additions and 217 deletions
513
lib/index.js
513
lib/index.js
File diff suppressed because one or more lines are too long
|
|
@ -25,7 +25,34 @@ import {
|
|||
import { listAgentPresetCatalog } from '../../../../src/channels/shared/agent-preset.mjs';
|
||||
import { createDeliveryAdapter } from '../../delivery-adapter.mjs';
|
||||
|
||||
// The WebSocket agent built here is only used for the Feishu long connection,
|
||||
// whose endpoint is open.feishu.cn (Feishu) or open.larksuite.com (Lark).
|
||||
// Honor NO_PROXY/no_proxy for those hosts so users with blanket proxy
|
||||
// environments exported in their shell (Clash/V2Ray etc.) keep a direct
|
||||
// connection to Feishu instead of routing the WSS handshake through the proxy.
|
||||
const LONG_CONNECTION_HOSTS = ['open.feishu.cn', 'open.larksuite.com'];
|
||||
|
||||
function hostExcludedByNoProxyEntry(host, entry) {
|
||||
if (entry === '*') return true;
|
||||
const bare = entry.startsWith('.') ? entry.slice(1) : entry;
|
||||
if (!bare) return false;
|
||||
return host === bare || host.endsWith(`.${bare}`);
|
||||
}
|
||||
|
||||
function longConnectionExcludedByNoProxy(env) {
|
||||
for (const key of ['no_proxy', 'NO_PROXY']) {
|
||||
const value = env?.[key];
|
||||
if (typeof value !== 'string' || !value.trim()) continue;
|
||||
const entries = value.split(',').map((entry) => entry.trim().toLowerCase()).filter(Boolean);
|
||||
if (LONG_CONNECTION_HOSTS.some((host) => entries.some((entry) => hostExcludedByNoProxyEntry(host, entry)))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function webSocketProxyUrl(env) {
|
||||
if (longConnectionExcludedByNoProxy(env)) return undefined;
|
||||
for (const key of ['https_proxy', 'HTTPS_PROXY', 'http_proxy', 'HTTP_PROXY']) {
|
||||
const value = env?.[key];
|
||||
if (typeof value === 'string' && value.trim()) return value.trim();
|
||||
|
|
|
|||
|
|
@ -197,3 +197,31 @@ test('Feishu WebSocket agent sends an upgrade through an HTTPS_PROXY CONNECT tun
|
|||
test('Feishu WebSocket agent is absent when no proxy is configured', () => {
|
||||
assert.equal(createFeishuWebSocketAgent({}), undefined);
|
||||
});
|
||||
|
||||
test('Feishu WebSocket agent honors NO_PROXY for the long-connection endpoints', () => {
|
||||
const proxyUrl = 'http://127.0.0.1:8080';
|
||||
assert.equal(createFeishuWebSocketAgent({
|
||||
HTTPS_PROXY: proxyUrl,
|
||||
NO_PROXY: 'localhost,127.0.0.1,::1,*.local,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,.cn',
|
||||
}), undefined, 'a .cn NO_PROXY entry must exclude open.feishu.cn from proxying');
|
||||
assert.equal(createFeishuWebSocketAgent({
|
||||
https_proxy: proxyUrl,
|
||||
no_proxy: 'open.feishu.cn',
|
||||
}), undefined, 'an exact-host NO_PROXY entry must exclude the Feishu endpoint');
|
||||
assert.equal(createFeishuWebSocketAgent({
|
||||
HTTPS_PROXY: proxyUrl,
|
||||
NO_PROXY: 'feishu.cn',
|
||||
}), undefined, 'a bare parent domain in NO_PROXY must exclude subdomains');
|
||||
assert.equal(createFeishuWebSocketAgent({
|
||||
HTTPS_PROXY: proxyUrl,
|
||||
NO_PROXY: '*',
|
||||
}), undefined, 'a wildcard NO_PROXY must disable the WebSocket agent');
|
||||
assert.equal(createFeishuWebSocketAgent({
|
||||
HTTPS_PROXY: proxyUrl,
|
||||
NO_PROXY: 'larksuite.com',
|
||||
}), undefined, 'NO_PROXY must also cover the Lark endpoint');
|
||||
assert.notEqual(createFeishuWebSocketAgent({
|
||||
HTTPS_PROXY: proxyUrl,
|
||||
NO_PROXY: 'example.com,other.org',
|
||||
}), undefined, 'unrelated NO_PROXY entries must keep the WebSocket agent');
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue