diff --git a/src/lib-csharp/Sources/HttpClientFileDownloader.cs b/src/lib-csharp/Sources/HttpClientFileDownloader.cs
index d0a2e7d0..85e1488f 100644
--- a/src/lib-csharp/Sources/HttpClientFileDownloader.cs
+++ b/src/lib-csharp/Sources/HttpClientFileDownloader.cs
@@ -18,48 +18,54 @@ namespace Velopack.Sources
public static ProductInfoHeaderValue UserAgent => new("Velopack", VelopackRuntimeInfo.VelopackNugetVersion.ToFullString());
///
- public virtual async Task DownloadFile(string url, string targetFile, Action progress, IDictionary? headers, double timeout, CancellationToken cancelToken = default)
+ public virtual async Task DownloadFile(string url, string targetFile, Action progress, IDictionary? headers, double timeout,
+ CancellationToken cancelToken = default)
{
using var client = CreateHttpClient(headers, timeout);
+ await TryDownloadThenLowercase(
+ async (reqUrl) => {
+ using (var fs = File.Open(targetFile, FileMode.Create)) {
+ await DownloadToStreamInternal(client, reqUrl, fs, progress, cancelToken).ConfigureAwait(false);
+ }
- try {
- using (var fs = File.Open(targetFile, FileMode.Create)) {
- await DownloadToStreamInternal(client, url, fs, progress, cancelToken).ConfigureAwait(false);
- }
- } catch {
- // NB: Some super brain-dead services are case-sensitive yet
- // corrupt case on upload. I can't even.
- using (var fs = File.Open(targetFile, FileMode.Create)) {
- await DownloadToStreamInternal(client, url.ToLower(), fs, progress, cancelToken).ConfigureAwait(false);
- }
- }
+ return true;
+ },
+ url).ConfigureAwait(false);
}
///
public virtual async Task DownloadBytes(string url, IDictionary? headers, double timeout)
{
using var client = CreateHttpClient(headers, timeout);
-
- try {
- return await client.GetByteArrayAsync(url).ConfigureAwait(false);
- } catch {
- // NB: Some super brain-dead services are case-sensitive yet
- // corrupt case on upload. I can't even.
- return await client.GetByteArrayAsync(url.ToLower()).ConfigureAwait(false);
- }
+ return await TryDownloadThenLowercase(client.GetByteArrayAsync, url).ConfigureAwait(false);
}
///
public virtual async Task DownloadString(string url, IDictionary? headers, double timeout)
{
using var client = CreateHttpClient(headers, timeout);
+ return await TryDownloadThenLowercase(client.GetStringAsync, url).ConfigureAwait(false);
+ }
+ ///
+ /// Tries to download a string from the specified url. If it fails, it will attempt to
+ /// download the string again with the url lowercased. This is useful for services that
+ /// are case-sensitive yet corrupt the case on upload.
+ ///
+ protected virtual async Task TryDownloadThenLowercase(Func> downloadFunc, string url)
+ {
try {
- return await client.GetStringAsync(url).ConfigureAwait(false);
+ return await downloadFunc(url).ConfigureAwait(false);
} catch {
- // NB: Some super brain-dead services are case-sensitive yet
- // corrupt case on upload. I can't even.
- return await client.GetStringAsync(url.ToLower()).ConfigureAwait(false);
+ try {
+ // NB: Some super brain-dead services are case-sensitive yet
+ // corrupt case on upload. I can't even.
+ return await downloadFunc(url.ToLower()).ConfigureAwait(false);
+ } catch {
+ // we don't want to throw the "fallback" exception
+ }
+
+ throw; // rethrow the original exception
}
}
@@ -67,7 +73,8 @@ namespace Velopack.Sources
/// Asynchronously downloads a remote url to the specified destination stream while
/// providing progress updates.
///
- protected virtual async Task DownloadToStreamInternal(HttpClient client, string requestUri, Stream destination, Action? progress = null, CancellationToken cancelToken = default)
+ protected virtual async Task DownloadToStreamInternal(HttpClient client, string requestUri, Stream destination, Action? progress = null,
+ CancellationToken cancelToken = default)
{
// https://stackoverflow.com/a/46497896/184746
// Get the http headers first to examine the content length
@@ -128,8 +135,7 @@ namespace Velopack.Sources
var client = new HttpClient(CreateHttpClientHandler());
client.DefaultRequestHeaders.UserAgent.Add(UserAgent);
- foreach (var header in headers ?? new Dictionary())
- {
+ foreach (var header in headers ?? new Dictionary()) {
client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
@@ -137,4 +143,4 @@ namespace Velopack.Sources
return client;
}
}
-}
+}
\ No newline at end of file