diff --git a/src/NzbDrone.Common.Test/Http/HttpClientFixture.cs b/src/NzbDrone.Common.Test/Http/HttpClientFixture.cs index fa02134fd..756d4ce58 100644 --- a/src/NzbDrone.Common.Test/Http/HttpClientFixture.cs +++ b/src/NzbDrone.Common.Test/Http/HttpClientFixture.cs @@ -131,6 +131,18 @@ namespace NzbDrone.Common.Test.Http response.Content.Should().NotBeNullOrWhiteSpace(); } + [Test] + public void should_throw_timeout_request() + { + var request = new HttpRequest($"https://{_httpBinHost}/delay/10"); + + request.RequestTimeout = new TimeSpan(0, 0, 5); + + Assert.ThrowsAsync(async () => await Subject.ExecuteAsync(request)); + + ExceptionVerification.ExpectedErrors(0); + } + [Test] public async Task should_execute_https_get() { diff --git a/src/NzbDrone.Common/Http/Dispatchers/ManagedHttpDispatcher.cs b/src/NzbDrone.Common/Http/Dispatchers/ManagedHttpDispatcher.cs index 732c4fbe4..1d47c57a2 100644 --- a/src/NzbDrone.Common/Http/Dispatchers/ManagedHttpDispatcher.cs +++ b/src/NzbDrone.Common/Http/Dispatchers/ManagedHttpDispatcher.cs @@ -102,31 +102,38 @@ namespace NzbDrone.Common.Http.Dispatchers var httpClient = GetClient(request.Url); - using var responseMessage = await httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, cts.Token); + try { - byte[] data = null; - - try + using var responseMessage = await httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, cts.Token); { - if (request.ResponseStream != null && responseMessage.StatusCode == HttpStatusCode.OK) + byte[] data = null; + + try { - await responseMessage.Content.CopyToAsync(request.ResponseStream, null, cts.Token); + if (request.ResponseStream != null && responseMessage.StatusCode == HttpStatusCode.OK) + { + await responseMessage.Content.CopyToAsync(request.ResponseStream, null, cts.Token); + } + else + { + data = responseMessage.Content.ReadAsByteArrayAsync(cts.Token).GetAwaiter().GetResult(); + } } - else + catch (Exception ex) { - data = responseMessage.Content.ReadAsByteArrayAsync(cts.Token).GetAwaiter().GetResult(); + throw new WebException("Failed to read complete http response", ex, WebExceptionStatus.ReceiveFailure, null); } - } - catch (Exception ex) - { - throw new WebException("Failed to read complete http response", ex, WebExceptionStatus.ReceiveFailure, null); - } - var headers = responseMessage.Headers.ToNameValueCollection(); + var headers = responseMessage.Headers.ToNameValueCollection(); - headers.Add(responseMessage.Content.Headers.ToNameValueCollection()); + headers.Add(responseMessage.Content.Headers.ToNameValueCollection()); - return new HttpResponse(request, new HttpHeader(headers), data, responseMessage.StatusCode, responseMessage.Version); + return new HttpResponse(request, new HttpHeader(headers), data, responseMessage.StatusCode, responseMessage.Version); + } + } + catch (OperationCanceledException ex) when (cts.IsCancellationRequested) + { + throw new WebException("Http request timed out", ex.InnerException, WebExceptionStatus.Timeout, null); } }