mirror of
https://github.com/hansjone/dsh-search-mcp.git
synced 2026-10-11 04:30:45 +08:00
Fallback to env proxy when dsh-http-proxy cannot resolve on link installs.
Use process HTTP_PROXY/HTTPS_PROXY and undici global dispatcher when the policy module import fails, so symlinked desktop plugins still egress through the corporate proxy. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
26a8c2ecee
commit
4b4a1e4460
5 changed files with 197 additions and 35 deletions
|
|
@ -12,7 +12,7 @@ test('package exports resolve and peerDependencies stay open', async () => {
|
|||
assert.equal(pkg.exports['.'], './lib/index.js')
|
||||
assert.equal(pkg.exports['./client'], './lib/client.browser.js')
|
||||
assert.equal(pkg.engines.node, '>=20')
|
||||
assert.equal(pkg.version, '0.2.40')
|
||||
assert.equal(pkg.version, '0.2.41')
|
||||
assert.equal(pkg.dsh.client.immediately, false)
|
||||
assert.equal(pkg.dependencies['@modelcontextprotocol/client'], '2.0.0')
|
||||
assert.ok(!Object.hasOwn(pkg.dependencies, '@modelcontextprotocol/sdk'))
|
||||
|
|
@ -86,16 +86,18 @@ test('known providers are CDKey-only while custom keeps advanced fields', async
|
|||
assert.match(client, /已知提供商不需要填写端点链接/)
|
||||
})
|
||||
|
||||
test('HTTP transport inherits DSH proxy and pins DNS on the direct path', async () => {
|
||||
test('HTTP transport inherits DSH proxy with env fallback and pins DNS on direct path', async () => {
|
||||
const transport = await read('lib/client.js')
|
||||
const proxyEnv = await read('lib/proxy-env.js')
|
||||
assert.match(transport, /from '@modelcontextprotocol\/client'/)
|
||||
assert.match(transport, /from '@modelcontextprotocol\/client\/stdio'/)
|
||||
assert.doesNotMatch(transport, /from ['"]@modelcontextprotocol\/sdk/)
|
||||
assert.match(transport, /@deepseek-ai\/dsh-http-proxy/)
|
||||
assert.match(transport, /proxyRouteFor/)
|
||||
assert.match(transport, /resolveEgressRoute/)
|
||||
assert.match(proxyEnv, /proxyRouteFor/)
|
||||
assert.match(proxyEnv, /readProxyEnv/)
|
||||
assert.match(proxyEnv, /getGlobalDispatcher/)
|
||||
assert.match(transport, /parseHttpEndpoint/)
|
||||
assert.match(transport, /validateHttpEndpoint\(server\.url, \{ signal \}\)/)
|
||||
assert.match(transport, /dispatcher/)
|
||||
assert.match(transport, /redirect: 'error'/)
|
||||
assert.match(transport, /versionNegotiation:\s*\{\s*mode:\s*['"]auto['"]/)
|
||||
})
|
||||
|
|
|
|||
66
test/proxy-env.test.js
Normal file
66
test/proxy-env.test.js
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import {
|
||||
bypassesEnvNoProxy,
|
||||
readProxyEnv,
|
||||
shouldUseProcessProxy,
|
||||
} from '../lib/proxy-env.js';
|
||||
|
||||
const nonPublic = (host) => host === '127.0.0.1' || host === '10.0.0.1';
|
||||
|
||||
test('readProxyEnv picks HTTPS_PROXY over HTTP_PROXY', () => {
|
||||
const prev = {
|
||||
HTTPS_PROXY: process.env.HTTPS_PROXY,
|
||||
HTTP_PROXY: process.env.HTTP_PROXY,
|
||||
};
|
||||
process.env.HTTPS_PROXY = 'http://proxy.example:8080';
|
||||
process.env.HTTP_PROXY = 'http://other:8080';
|
||||
try {
|
||||
assert.equal(readProxyEnv(), 'http://proxy.example:8080');
|
||||
} finally {
|
||||
for (const [key, value] of Object.entries(prev)) {
|
||||
if (value === undefined) delete process.env[key];
|
||||
else process.env[key] = value;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('bypassesEnvNoProxy matches suffix entries', () => {
|
||||
const prev = process.env.NO_PROXY;
|
||||
process.env.NO_PROXY = 'localhost,.zte.com.cn';
|
||||
try {
|
||||
assert.equal(bypassesEnvNoProxy(new URL('https://api.zte.com.cn/v1')), true);
|
||||
assert.equal(bypassesEnvNoProxy(new URL('https://dashscope.aliyuncs.com/mcp')), false);
|
||||
} finally {
|
||||
if (prev === undefined) delete process.env.NO_PROXY;
|
||||
else process.env.NO_PROXY = prev;
|
||||
}
|
||||
});
|
||||
|
||||
test('shouldUseProcessProxy respects NO_PROXY bypass', () => {
|
||||
const prev = {
|
||||
HTTPS_PROXY: process.env.HTTPS_PROXY,
|
||||
NO_PROXY: process.env.NO_PROXY,
|
||||
};
|
||||
process.env.HTTPS_PROXY = 'http://proxy.zte.com.cn:80';
|
||||
process.env.NO_PROXY = '.zte.com.cn';
|
||||
try {
|
||||
assert.equal(
|
||||
shouldUseProcessProxy(new URL('https://dashscope.aliyuncs.com/mcp'), nonPublic),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
shouldUseProcessProxy(new URL('https://llm.zte.com.cn/v1'), nonPublic),
|
||||
false,
|
||||
);
|
||||
assert.equal(
|
||||
shouldUseProcessProxy(new URL('https://127.0.0.1/mcp'), nonPublic),
|
||||
false,
|
||||
);
|
||||
} finally {
|
||||
for (const [key, value] of Object.entries(prev)) {
|
||||
if (value === undefined) delete process.env[key];
|
||||
else process.env[key] = value;
|
||||
}
|
||||
}
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue