diff --git a/src/main/services/ProxyManager.ts b/src/main/services/ProxyManager.ts index 620a6a5fef..860324bc62 100644 --- a/src/main/services/ProxyManager.ts +++ b/src/main/services/ProxyManager.ts @@ -11,14 +11,42 @@ import { Dispatcher, EnvHttpProxyAgent, getGlobalDispatcher, setGlobalDispatcher const logger = loggerService.withContext('ProxyManager') let byPassRules: string[] = [] -const isByPass = (hostname: string) => { +const isByPass = (url: string) => { if (byPassRules.length === 0) { return false } - return byPassRules.includes(hostname) -} + try { + const subjectUrlTokens = new URL(url) + for (const rule of byPassRules) { + const ruleMatch = rule.replace(/^(?\.)/, '*').match(/^(?.+?)(?::(?\d+))?$/) + if (!ruleMatch || !ruleMatch.groups) { + logger.warn('Failed to parse bypass rule:', { rule }) + continue + } + + if (!ruleMatch.groups.hostname) { + continue + } + + const hostnameIsMatch = subjectUrlTokens.hostname === ruleMatch.groups.hostname + + if ( + hostnameIsMatch && + (!ruleMatch.groups || + !ruleMatch.groups.port || + (subjectUrlTokens.port && subjectUrlTokens.port === ruleMatch.groups.port)) + ) { + return true + } + } + return false + } catch (error) { + logger.error('Failed to check bypass:', error as Error) + return false + } +} class SelectiveDispatcher extends Dispatcher { private proxyDispatcher: Dispatcher private directDispatcher: Dispatcher @@ -31,9 +59,7 @@ class SelectiveDispatcher extends Dispatcher { dispatch(opts: Dispatcher.DispatchOptions, handler: Dispatcher.DispatchHandlers) { if (opts.origin) { - const url = new URL(opts.origin) - // 检查是否为 localhost 或本地地址 - if (isByPass(url.hostname)) { + if (isByPass(opts.origin.toString())) { return this.directDispatcher.dispatch(opts, handler) } } @@ -93,15 +119,20 @@ export class ProxyManager { // Set new interval this.systemProxyInterval = setInterval(async () => { const currentProxy = await getSystemProxy() - if (currentProxy?.proxyUrl.toLowerCase() === this.config?.proxyRules) { + if ( + currentProxy?.proxyUrl.toLowerCase() === this.config?.proxyRules && + currentProxy?.noProxy.join(',').toLowerCase() === this.config?.proxyBypassRules?.toLowerCase() + ) { return } - logger.info(`system proxy changed: ${currentProxy?.proxyUrl}, this.config.proxyRules: ${this.config.proxyRules}`) + logger.info( + `system proxy changed: ${currentProxy?.proxyUrl}, this.config.proxyRules: ${this.config.proxyRules}, this.config.proxyBypassRules: ${this.config.proxyBypassRules}` + ) await this.configureProxy({ mode: 'system', proxyRules: currentProxy?.proxyUrl.toLowerCase(), - proxyBypassRules: undefined + proxyBypassRules: currentProxy?.noProxy.join(',') }) }, 1000 * 60) } @@ -151,6 +182,7 @@ export class ProxyManager { delete process.env.grpc_proxy delete process.env.http_proxy delete process.env.https_proxy + delete process.env.no_proxy delete process.env.SOCKS_PROXY delete process.env.ALL_PROXY @@ -162,6 +194,7 @@ export class ProxyManager { process.env.HTTPS_PROXY = url process.env.http_proxy = url process.env.https_proxy = url + process.env.no_proxy = byPassRules.join(',') if (url.startsWith('socks')) { process.env.SOCKS_PROXY = url @@ -229,8 +262,7 @@ export class ProxyManager { // filter localhost if (url) { - const hostname = typeof url === 'string' ? new URL(url).hostname : url.hostname - if (isByPass(hostname)) { + if (isByPass(url.toString())) { return originalMethod(url, options, callback) } }