From b2b5088ac5967b375b45d91637a6c4b532e0e52b Mon Sep 17 00:00:00 2001 From: tangge233 Date: Tue, 4 Aug 2026 08:20:09 +0800 Subject: [PATCH] =?UTF-8?q?fix(proxy):=20=E4=BB=A3=E7=90=86=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E8=A7=A3=E6=9E=90=E9=81=97=E6=BC=8F=E4=B8=80=E7=A7=8D?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PCL.Core/IO/Net/Http/HttpProxyManager.cs | 80 ++++++++++++------------ 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/PCL.Core/IO/Net/Http/HttpProxyManager.cs b/PCL.Core/IO/Net/Http/HttpProxyManager.cs index 88bad70402..0c35f87337 100644 --- a/PCL.Core/IO/Net/Http/HttpProxyManager.cs +++ b/PCL.Core/IO/Net/Http/HttpProxyManager.cs @@ -45,53 +45,56 @@ private enum ProxyProtocol Socks } - private record ProxyItem - { - public ProxyProtocol Protocol; - public required string Address; - } + private sealed record ProxyItem(ProxyProtocol Protocol, string Address); private static ProxyItem[] _GetProxyFromString(string? proxyString) { if (proxyString.IsNullOrWhiteSpace()) return []; - var ret = new List(); - - // 形式:http=192.168.1.100:8080;socks=192.168.1.100:1080 + // 含 '=' 的形式:http=192.168.1.100:8080;socks=192.168.1.100:1080;ftp=127.0.0.1:124 + // 也可以是 http=http://127.0.0.1:10808 if (proxyString.Contains('=')) { - foreach (var segment in proxyString.Split(';', StringSplitOptions.RemoveEmptyEntries)) + var items = new List(); + foreach (var segment in proxyString.Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)) { - var eqIndex = segment.IndexOf('='); - if (eqIndex <= 0 || eqIndex >= segment.Length - 1) - continue; + if (_ParseKeyValueSegment(segment) is { } item) + items.Add(item); + } + return [.. items]; + } - var protocolStr = segment[..eqIndex].Trim(); - var address = segment[(eqIndex + 1)..].Trim(); + // 形式:http://127.0.0.1:1145/ 或者单纯 127.0.0.1:1145 + var proxy = _ParseAddress(proxyString.Trim()); + return proxy is null ? [] : [proxy]; + } - if (string.IsNullOrWhiteSpace(address)) - continue; + /// 解析 protocol=address 形式的段;格式非法时返回 null 以便忽略该段 + private static ProxyItem? _ParseKeyValueSegment(string segment) + { + var eqIndex = segment.IndexOf('='); + // 缺少 '='、协议名或地址的段视为非法,直接忽略 + if (eqIndex <= 0 || eqIndex >= segment.Length - 1) return null; - ret.Add(new ProxyItem { Protocol = _ParseProtocol(protocolStr), Address = address }); - } + return _ParseAddress( + segment[(eqIndex + 1)..].Trim(), + _ParseProtocol(segment[..eqIndex].Trim())); + } - return ret.Count > 0 ? [.. ret] : []; - } + /// 解析单个代理地址:支持带 scheme 的地址(如 http://127.0.0.1:10808)与纯 host:port 地址(如 127.0.0.1:1145) + private static ProxyItem? _ParseAddress(string address, ProxyProtocol? protocol = null) + { + if (address.IsNullOrWhiteSpace()) return null; - // 形式:http://127.0.0.1:1145/ 或者单纯 127.0.0.1:1145 - if (Uri.TryCreate(proxyString, new UriCreationOptions(), out var proxyAddr)) - { - var address = proxyAddr.Port > 0 - ? $"{proxyAddr.Host}:{proxyAddr.Port}" - : proxyAddr.Host; - ret.Add(new ProxyItem { Protocol = _ParseProtocol(proxyAddr.Scheme), Address = address }); - } - else + // 能解析出主机名的地址,规范化为 host:port + if (Uri.TryCreate(address, new UriCreationOptions(), out var uri) && !uri.Host.IsNullOrEmpty()) { - ret.Add(new ProxyItem { Protocol = ProxyProtocol.Http, Address = proxyString.Trim() }); + var hostPort = uri.Port > 0 ? $"{uri.Host}:{uri.Port}" : uri.Host; + return new ProxyItem(protocol ?? _ParseProtocol(uri.Scheme), hostPort); } - return [.. ret]; + // 纯 host:port 地址(无法作为 URI 解析),按指定协议(默认 Http)原样使用 + return new ProxyItem(protocol ?? ProxyProtocol.Http, address); } private static ProxyProtocol _ParseProtocol(string scheme) @@ -117,14 +120,13 @@ public void RefreshSystemProxy() // parse var proxies = _GetProxyFromString(systemProxyString); - // filter - if (proxies.Length == 0 || !proxies.Any(static x => x.Protocol.Equals(ProxyProtocol.Http))) isSystemProxyEnabled = 0; - var selectedProxy = proxies.FirstOrDefault(static x => x.Protocol.Equals(ProxyProtocol.Http)); - - // apply - _systemWebProxy.Address = (isSystemProxyEnabled == 0 || selectedProxy!.Address.IsNullOrEmpty()) - ? null - : new Uri($"http://{selectedProxy.Address}"); + // 仅当系统代理已启用且存在有效的 HTTP 代理时才应用 + var selectedProxy = proxies.FirstOrDefault(static x => x.Protocol == ProxyProtocol.Http); + _systemWebProxy.Address = selectedProxy is null + || selectedProxy.Address.IsNullOrEmpty() + || isSystemProxyEnabled == 0 + ? null + : new Uri($"http://{selectedProxy.Address}"); LogWrapper.Info("Proxy", $"已从操作系统更新代理设置,系统代理状态:{isSystemProxyEnabled}|{systemProxyString}");