Improved http timeout handling

Co-authored-by: Qstick <qstick@gmail.com>
pull/1889/head
Bogdan 1 year ago
parent e602862102
commit 32db2af0ea

@ -128,6 +128,17 @@ namespace NzbDrone.Common.Test.Http
response.Content.Should().NotBeNullOrWhiteSpace(); 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.Throws<WebException>(() => Subject.Execute(request));
ExceptionVerification.ExpectedErrors(1);
}
[Test] [Test]
public void should_execute_https_get() public void should_execute_https_get()
{ {

@ -107,52 +107,59 @@ namespace NzbDrone.Common.Http.Dispatchers
sw.Start(); sw.Start();
using var responseMessage = await httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, cts.Token); try
{ {
byte[] data = null; using var responseMessage = await httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, cts.Token);
try
{ {
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 = await responseMessage.Content.ReadAsByteArrayAsync(cts.Token);
}
} }
else catch (Exception ex)
{ {
data = await responseMessage.Content.ReadAsByteArrayAsync(cts.Token); 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());
var responseCookies = new CookieContainer(); var responseCookies = new CookieContainer();
if (responseMessage.Headers.TryGetValues("Set-Cookie", out var cookieHeaders)) if (responseMessage.Headers.TryGetValues("Set-Cookie", out var cookieHeaders))
{
foreach (var responseCookieHeader in cookieHeaders)
{ {
try foreach (var responseCookieHeader in cookieHeaders)
{
cookies.SetCookies(responseMessage.RequestMessage.RequestUri, responseCookieHeader);
}
catch
{ {
// Ignore invalid cookies try
{
cookies.SetCookies(responseMessage.RequestMessage.RequestUri, responseCookieHeader);
}
catch
{
// Ignore invalid cookies
}
} }
} }
}
var cookieCollection = cookies.GetCookies(responseMessage.RequestMessage.RequestUri); var cookieCollection = cookies.GetCookies(responseMessage.RequestMessage.RequestUri);
sw.Stop(); sw.Stop();
return new HttpResponse(request, new HttpHeader(headers), cookieCollection, data, sw.ElapsedMilliseconds, responseMessage.StatusCode, responseMessage.Version); return new HttpResponse(request, new HttpHeader(headers), cookieCollection, data, sw.ElapsedMilliseconds, responseMessage.StatusCode, responseMessage.Version);
}
}
catch (OperationCanceledException ex) when (cts.IsCancellationRequested)
{
throw new WebException("Http request timed out", ex.InnerException, WebExceptionStatus.Timeout, null);
} }
} }

Loading…
Cancel
Save