diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9ade708b91..00660228c6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
## v1.34.3
+### Bugfixes
+
+- [Core] Oops, `HttpClient` actually sucks (#3960 by: HebaruSan)
+
### Internal
- [Netkan] Re-sort module properties after merging (#3957 by: HebaruSan)
diff --git a/Cmdline/CKAN-cmdline.csproj b/Cmdline/CKAN-cmdline.csproj
index 43245ee6e5..12819a8ecd 100644
--- a/Cmdline/CKAN-cmdline.csproj
+++ b/Cmdline/CKAN-cmdline.csproj
@@ -24,7 +24,7 @@
512
prompt
4
- IDE1006
+ IDE1006,NU1701
PrepareResources;$(CompileDependsOn)
diff --git a/Core/Games/KerbalSpaceProgram.cs b/Core/Games/KerbalSpaceProgram.cs
index 969e11ae1c..b767fd556a 100644
--- a/Core/Games/KerbalSpaceProgram.cs
+++ b/Core/Games/KerbalSpaceProgram.cs
@@ -266,34 +266,34 @@ public GameVersion DetectVersion(DirectoryInfo where)
public Uri MetadataBugtrackerURL => new Uri("https://github.com/KSP-CKAN/NetKAN/issues/new/choose");
- private string Missions(GameInstance inst)
+ private static string Missions(GameInstance inst)
=> CKANPathUtils.NormalizePath(Path.Combine(inst.GameDir(), "Missions"));
- private string Ships(GameInstance inst)
+ private static string Ships(GameInstance inst)
=> CKANPathUtils.NormalizePath(Path.Combine(inst.GameDir(), "Ships"));
- private string ShipsVab(GameInstance inst)
+ private static string ShipsVab(GameInstance inst)
=> CKANPathUtils.NormalizePath(Path.Combine(Ships(inst), "VAB"));
- private string ShipsSph(GameInstance inst)
+ private static string ShipsSph(GameInstance inst)
=> CKANPathUtils.NormalizePath(Path.Combine(Ships(inst), "SPH"));
- private string ShipsThumbs(GameInstance inst)
+ private static string ShipsThumbs(GameInstance inst)
=> CKANPathUtils.NormalizePath(Path.Combine(Ships(inst), "@thumbs"));
- private string ShipsThumbsSPH(GameInstance inst)
+ private static string ShipsThumbsSPH(GameInstance inst)
=> CKANPathUtils.NormalizePath(Path.Combine(ShipsThumbs(inst), "SPH"));
- private string ShipsThumbsVAB(GameInstance inst)
+ private static string ShipsThumbsVAB(GameInstance inst)
=> CKANPathUtils.NormalizePath(Path.Combine(ShipsThumbs(inst), "VAB"));
- private string ShipsScript(GameInstance inst)
+ private static string ShipsScript(GameInstance inst)
=> CKANPathUtils.NormalizePath(Path.Combine(Ships(inst), "Script"));
- private string Tutorial(GameInstance inst)
+ private static string Tutorial(GameInstance inst)
=> CKANPathUtils.NormalizePath(Path.Combine(inst.GameDir(), "saves", "training"));
- private string Scenarios(GameInstance inst)
+ private static string Scenarios(GameInstance inst)
=> CKANPathUtils.NormalizePath(Path.Combine(inst.GameDir(), "saves", "scenarios"));
private readonly Dictionary allowedFolders = new Dictionary
@@ -343,7 +343,7 @@ private static string KSPDirectory(string steamPath)
///
/// args or args minus parameter
///
- private string[] filterCmdLineArgs(string[] args, GameVersion installedVersion, GameVersionRange crashyKspRange, string parameter)
+ private static string[] filterCmdLineArgs(string[] args, GameVersion installedVersion, GameVersionRange crashyKspRange, string parameter)
{
var installedRange = installedVersion.ToVersionRange();
if (crashyKspRange.IntersectWith(installedRange) != null
diff --git a/Core/Net/Net.cs b/Core/Net/Net.cs
index 8167c45208..4c0608f487 100644
--- a/Core/Net/Net.cs
+++ b/Core/Net/Net.cs
@@ -3,7 +3,6 @@
using System.IO;
using System.Linq;
using System.Net;
-using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading;
@@ -46,27 +45,17 @@ public static class Net
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
///
public static string CurrentETag(Uri url)
- => httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, url),
- HttpCompletionOption.ResponseHeadersRead)
- .Result
- .Headers.ETag.ToString()
- .Replace("\"", "");
-
- ///
- /// "HttpClient is intended to be instantiated once and reused
- /// throughout the life of an application. In .NET Core and .NET 5+,
- /// HttpClient pools connections inside the handler instance and
- /// reuses a connection across multiple requests. If you instantiate
- /// an HttpClient class for every request, the number of sockets
- /// available under heavy loads will be exhausted. This exhaustion
- /// will result in SocketException errors."
- ///
- public static readonly HttpClient httpClient = new HttpClient();
- public static readonly HttpClient nonRedirectingHttpClient = new HttpClient(
- new HttpClientHandler()
- {
- AllowAutoRedirect = false,
- });
+ {
+ // HttpClient apparently is worse than what it was supposed to replace
+ #pragma warning disable SYSLIB0014
+ WebRequest req = WebRequest.Create(url);
+ #pragma warning restore SYSLIB0014
+ req.Method = "HEAD";
+ HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
+ string val = resp.Headers["ETag"]?.Replace("\"", "");
+ resp.Close();
+ return val;
+ }
///
/// Downloads the specified url, and stores it in the filename given.
@@ -257,10 +246,6 @@ public static Uri ResolveRedirect(Uri url)
const int maxRedirects = 6;
for (int redirects = 0; redirects <= maxRedirects; ++redirects)
{
- #if NETFRAMEWORK
-
- // HttpClient doesn't handle redirects well on Mono, but net7.0 considers WebClient obsolete
-
var rwClient = new RedirectWebClient();
using (rwClient.OpenRead(url)) { }
var location = rwClient.ResponseHeaders["Location"];
@@ -281,37 +266,6 @@ public static Uri ResolveRedirect(Uri url)
{
throw new Kraken(string.Format(Properties.Resources.NetInvalidLocation, location));
}
-
- #else
-
- var req = new HttpRequestMessage(HttpMethod.Head, url);
- req.Headers.UserAgent.Clear();
- req.Headers.UserAgent.ParseAdd(UserAgentString);
- using (var response = nonRedirectingHttpClient.SendAsync(
- req, HttpCompletionOption.ResponseHeadersRead).Result)
- {
- if (response.Headers.Location == null)
- {
- return url;
- }
-
- var location = response.Headers.Location.ToString();
- if (Uri.IsWellFormedUriString(location, UriKind.Absolute))
- {
- url = response.Headers.Location;
- }
- else if (Uri.IsWellFormedUriString(location, UriKind.Relative))
- {
- url = new Uri(url, response.Headers.Location);
- log.DebugFormat("Relative URL {0} is absolute URL {1}", location, url);
- }
- else
- {
- throw new Kraken(string.Format(Properties.Resources.NetInvalidLocation, location));
- }
- }
-
- #endif
}
return null;
}
diff --git a/Core/Net/RedirectWebClient.cs b/Core/Net/RedirectWebClient.cs
index 661252fc10..3c279ce8e9 100644
--- a/Core/Net/RedirectWebClient.cs
+++ b/Core/Net/RedirectWebClient.cs
@@ -1,8 +1,8 @@
-#if NETFRAMEWORK
-
using System;
using System.Net;
+#pragma warning disable SYSLIB0014
+
namespace CKAN
{
// HttpClient doesn't handle redirects well on Mono, but net7.0 considers WebClient obsolete
@@ -23,5 +23,3 @@ protected override WebRequest GetWebRequest(Uri address)
}
}
}
-
-#endif
diff --git a/GUI/Main/MainRepo.cs b/GUI/Main/MainRepo.cs
index 0b7f26a849..1bc1cf473f 100644
--- a/GUI/Main/MainRepo.cs
+++ b/GUI/Main/MainRepo.cs
@@ -202,7 +202,22 @@ private void PostUpdateRepo(object sender, RunWorkerCompletedEventArgs e)
EnableMainWindow();
break;
+ case AggregateException exc:
+ foreach (var inner in exc.InnerExceptions
+ .SelectMany(inner =>
+ inner.TraverseNodes(ex => ex.InnerException)
+ .Reverse()))
+ {
+ log.Error(inner.Message, inner);
+ currentUser.RaiseMessage(inner.Message);
+ }
+ AddStatusMessage(Properties.Resources.MainRepoFailed);
+ Wait.Finish();
+ EnableMainWindow();
+ break;
+
case Exception exc:
+ log.Error(exc.Message, exc);
currentUser.RaiseMessage(exc.Message);
AddStatusMessage(Properties.Resources.MainRepoFailed);
Wait.Finish();
diff --git a/Netkan/CKAN-netkan.csproj b/Netkan/CKAN-netkan.csproj
index ea5bc06ffd..dcc9be7eca 100644
--- a/Netkan/CKAN-netkan.csproj
+++ b/Netkan/CKAN-netkan.csproj
@@ -23,7 +23,7 @@
512
prompt
4
- IDE1006
+ IDE1006,NU1701
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index ee48db95c3..0cedf0cc1c 100644
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -18,7 +18,7 @@
Debug;Release;NoGUI
false
7.3
- IDE1006
+ IDE1006,NU1701
net48;net7.0;net7.0-windows
$(TargetFramework.Replace("-windows", ""))
$(DefaultItemExcludes);AutoUpdate\**;GUI\**