Switch speedtest IP fallback to Cloudflare trace first

This commit is contained in:
freekof 2026-03-02 23:41:44 +08:00
parent 5d76a3e26e
commit 0638be614d

View file

@ -5,8 +5,8 @@ public static class ConnectionHandler
private static readonly string _tag = "ConnectionHandler"; private static readonly string _tag = "ConnectionHandler";
private static readonly string[] _speedtestIpApiUrls = private static readonly string[] _speedtestIpApiUrls =
[ [
"https://api.ipapi.is", "https://www.cloudflare.com/cdn-cgi/trace",
"https://api.ip.sb/geoip" "https://api.ipapi.is"
]; ];
public static async Task<string> RunAvailabilityCheck() public static async Task<string> RunAvailabilityCheck()
@ -70,6 +70,11 @@ public static class ConnectionHandler
} }
var result = await response.Content.ReadAsStringAsync(cts.Token).ConfigureAwait(false); var result = await response.Content.ReadAsStringAsync(cts.Token).ConfigureAwait(false);
if (url.Contains("/cdn-cgi/trace", StringComparison.OrdinalIgnoreCase))
{
return ParseCloudflareTrace(result);
}
return JsonUtils.Deserialize<IPAPIInfo>(result); return JsonUtils.Deserialize<IPAPIInfo>(result);
} }
catch catch
@ -78,6 +83,47 @@ public static class ConnectionHandler
} }
} }
private static IPAPIInfo? ParseCloudflareTrace(string? traceContent)
{
if (traceContent.IsNullOrEmpty())
{
return null;
}
var tracePairs = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (var line in traceContent.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
{
var idx = line.IndexOf('=');
if (idx <= 0)
{
continue;
}
var key = line[..idx];
var value = line[(idx + 1)..];
tracePairs[key] = value;
}
tracePairs.TryGetValue("ip", out var ip);
if (ip.IsNullOrEmpty())
{
return null;
}
tracePairs.TryGetValue("loc", out var loc);
return new IPAPIInfo
{
ip = ip,
clientIp = ip,
ip_addr = ip,
query = ip,
country = loc,
country_code = loc,
countryCode = loc
};
}
private static string? FormatCountryAndIp(IPAPIInfo? ipInfo, bool compact) private static string? FormatCountryAndIp(IPAPIInfo? ipInfo, bool compact)
{ {
if (ipInfo == null) if (ipInfo == null)