|
|
@ -1,5 +1,4 @@
|
|
|
|
using System;
|
|
|
|
using System;
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
|
|
using System.IO;
|
|
|
|
using System.IO;
|
|
|
|
using System.Net;
|
|
|
|
using System.Net;
|
|
|
|
using System.Net.Http;
|
|
|
|
using System.Net.Http;
|
|
|
@ -8,7 +7,6 @@ using System.Net.Sockets;
|
|
|
|
using System.Text;
|
|
|
|
using System.Text;
|
|
|
|
using System.Threading;
|
|
|
|
using System.Threading;
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
using NLog;
|
|
|
|
|
|
|
|
using NzbDrone.Common.Cache;
|
|
|
|
using NzbDrone.Common.Cache;
|
|
|
|
using NzbDrone.Common.Extensions;
|
|
|
|
using NzbDrone.Common.Extensions;
|
|
|
|
using NzbDrone.Common.Http.Proxy;
|
|
|
|
using NzbDrone.Common.Http.Proxy;
|
|
|
@ -28,21 +26,18 @@ namespace NzbDrone.Common.Http.Dispatchers
|
|
|
|
private readonly ICertificateValidationService _certificateValidationService;
|
|
|
|
private readonly ICertificateValidationService _certificateValidationService;
|
|
|
|
private readonly IUserAgentBuilder _userAgentBuilder;
|
|
|
|
private readonly IUserAgentBuilder _userAgentBuilder;
|
|
|
|
private readonly ICached<System.Net.Http.HttpClient> _httpClientCache;
|
|
|
|
private readonly ICached<System.Net.Http.HttpClient> _httpClientCache;
|
|
|
|
private readonly Logger _logger;
|
|
|
|
|
|
|
|
private readonly ICached<CredentialCache> _credentialCache;
|
|
|
|
private readonly ICached<CredentialCache> _credentialCache;
|
|
|
|
|
|
|
|
|
|
|
|
public ManagedHttpDispatcher(IHttpProxySettingsProvider proxySettingsProvider,
|
|
|
|
public ManagedHttpDispatcher(IHttpProxySettingsProvider proxySettingsProvider,
|
|
|
|
ICreateManagedWebProxy createManagedWebProxy,
|
|
|
|
ICreateManagedWebProxy createManagedWebProxy,
|
|
|
|
ICertificateValidationService certificateValidationService,
|
|
|
|
ICertificateValidationService certificateValidationService,
|
|
|
|
IUserAgentBuilder userAgentBuilder,
|
|
|
|
IUserAgentBuilder userAgentBuilder,
|
|
|
|
ICacheManager cacheManager,
|
|
|
|
ICacheManager cacheManager)
|
|
|
|
Logger logger)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
_proxySettingsProvider = proxySettingsProvider;
|
|
|
|
_proxySettingsProvider = proxySettingsProvider;
|
|
|
|
_createManagedWebProxy = createManagedWebProxy;
|
|
|
|
_createManagedWebProxy = createManagedWebProxy;
|
|
|
|
_certificateValidationService = certificateValidationService;
|
|
|
|
_certificateValidationService = certificateValidationService;
|
|
|
|
_userAgentBuilder = userAgentBuilder;
|
|
|
|
_userAgentBuilder = userAgentBuilder;
|
|
|
|
_logger = logger;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_httpClientCache = cacheManager.GetCache<System.Net.Http.HttpClient>(typeof(ManagedHttpDispatcher));
|
|
|
|
_httpClientCache = cacheManager.GetCache<System.Net.Http.HttpClient>(typeof(ManagedHttpDispatcher));
|
|
|
|
_credentialCache = cacheManager.GetCache<CredentialCache>(typeof(ManagedHttpDispatcher), "credentialcache");
|
|
|
|
_credentialCache = cacheManager.GetCache<CredentialCache>(typeof(ManagedHttpDispatcher), "credentialcache");
|
|
|
@ -103,43 +98,25 @@ namespace NzbDrone.Common.Http.Dispatchers
|
|
|
|
|
|
|
|
|
|
|
|
var httpClient = GetClient(request.Url);
|
|
|
|
var httpClient = GetClient(request.Url);
|
|
|
|
|
|
|
|
|
|
|
|
HttpResponseMessage responseMessage;
|
|
|
|
using var responseMessage = httpClient.Send(requestMessage, HttpCompletionOption.ResponseHeadersRead, cts.Token);
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
responseMessage = httpClient.Send(requestMessage, cts.Token);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (HttpRequestException e)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
_logger.Error(e, "HttpClient error");
|
|
|
|
|
|
|
|
throw;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
byte[] data = null;
|
|
|
|
byte[] data = null;
|
|
|
|
|
|
|
|
|
|
|
|
using (var responseStream = responseMessage.Content.ReadAsStream())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (responseStream != null && responseStream != Stream.Null)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
try
|
|
|
|
try
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (request.ResponseStream != null && responseMessage.StatusCode == HttpStatusCode.OK)
|
|
|
|
if (request.ResponseStream != null && responseMessage.StatusCode == HttpStatusCode.OK)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// A target ResponseStream was specified, write to that instead.
|
|
|
|
responseMessage.Content.CopyTo(request.ResponseStream, null, cts.Token);
|
|
|
|
// But only on the OK status code, since we don't want to write failures and redirects.
|
|
|
|
|
|
|
|
responseStream.CopyTo(request.ResponseStream);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
data = responseStream.ToBytes();
|
|
|
|
data = responseMessage.Content.ReadAsByteArrayAsync(cts.Token).GetAwaiter().GetResult();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
throw new WebException("Failed to read complete http response", ex, WebExceptionStatus.ReceiveFailure, null);
|
|
|
|
throw new WebException("Failed to read complete http response", ex, WebExceptionStatus.ReceiveFailure, null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var headers = responseMessage.Headers.ToNameValueCollection();
|
|
|
|
var headers = responseMessage.Headers.ToNameValueCollection();
|
|
|
|
|
|
|
|
|
|
|
@ -147,6 +124,7 @@ namespace NzbDrone.Common.Http.Dispatchers
|
|
|
|
|
|
|
|
|
|
|
|
return new HttpResponse(request, new HttpHeader(headers), data, responseMessage.StatusCode);
|
|
|
|
return new HttpResponse(request, new HttpHeader(headers), data, responseMessage.StatusCode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected virtual System.Net.Http.HttpClient GetClient(HttpUri uri)
|
|
|
|
protected virtual System.Net.Http.HttpClient GetClient(HttpUri uri)
|
|
|
|
{
|
|
|
|
{
|
|
|
|