diff --git a/Duplicati/Library/Backend/OAuthHelper/OAuthHttpClient.cs b/Duplicati/Library/Backend/OAuthHelper/OAuthHttpClient.cs index 4a57111368..8937f4a7de 100644 --- a/Duplicati/Library/Backend/OAuthHelper/OAuthHttpClient.cs +++ b/Duplicati/Library/Backend/OAuthHelper/OAuthHttpClient.cs @@ -64,6 +64,26 @@ private OAuthHttpClient(OAuthHttpMessageHandler authenticator) this.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("Duplicati", USER_AGENT_VERSION)); } + /// + /// Hide the base GetAsync method to throw a TimeoutException when an HTTP timeout occurs. + /// + public new async Task GetAsync(string requestUri) + { + // The HttpClient.GetAsync method throws an OperationCanceledException when the timeout is exceeded. + // In order to provide a more informative exception, we will detect this case and throw a TimeoutException + // instead. + try + { + return await base.GetAsync(requestUri).ConfigureAwait(false); + } + catch (OperationCanceledException) + { + // Since there is no CancellationToken, we will assume that the OperationCanceledException + // is due to an HTTP timeout. + throw new TimeoutException($"HTTP timeout {this.Timeout} exceeded."); + } + } + /// /// Sends an async request with optional authentication. ///