New: Fallback to libcurl/libssl on mono for https connections.

This commit is contained in:
Taloth Saldono 2015-06-18 09:08:29 +02:00
parent c4430ab4de
commit 527122452c
9 changed files with 348 additions and 20 deletions

View file

@ -26,6 +26,7 @@ namespace NzbDrone.Common.Http
private readonly Logger _logger;
private readonly IRateLimitService _rateLimitService;
private readonly ICached<CookieContainer> _cookieContainerCache;
private readonly ICached<bool> _curlTLSFallbackCache;
public HttpClient(ICacheManager cacheManager, IRateLimitService rateLimitService, Logger logger)
{
@ -34,6 +35,7 @@ namespace NzbDrone.Common.Http
ServicePointManager.DefaultConnectionLimit = 12;
_cookieContainerCache = cacheManager.GetCache<CookieContainer>(typeof(HttpClient));
_curlTLSFallbackCache = cacheManager.GetCache<bool>(typeof(HttpClient), "curlTLSFallback");
}
public HttpResponse Execute(HttpRequest request)
@ -94,6 +96,74 @@ namespace NzbDrone.Common.Http
webRequest.CookieContainer.Add(cookieContainer.GetCookies(request.Url));
}
var response = ExecuteRequest(request, webRequest);
stopWatch.Stop();
_logger.Trace("{0} ({1:n0} ms)", response, stopWatch.ElapsedMilliseconds);
if (request.AllowAutoRedirect && !RuntimeInfoBase.IsProduction &&
(response.StatusCode == HttpStatusCode.Moved ||
response.StatusCode == HttpStatusCode.MovedPermanently ||
response.StatusCode == HttpStatusCode.Found))
{
_logger.Error("Server requested a redirect to [" + response.Headers["Location"] + "]. Update the request URL to avoid this redirect.");
}
if (!request.SuppressHttpError && response.HasHttpError)
{
_logger.Warn("HTTP Error - {0}", response);
throw new HttpException(request, response);
}
return response;
}
private HttpResponse ExecuteRequest(HttpRequest request, HttpWebRequest webRequest)
{
if (OsInfo.IsMonoRuntime && webRequest.RequestUri.Scheme == "https")
{
if (!_curlTLSFallbackCache.Find(webRequest.RequestUri.Host))
{
try
{
return ExecuteWebRequest(request, webRequest);
}
catch (Exception ex)
{
if (ex.ToString().Contains("The authentication or decryption has failed."))
{
_logger.Debug("https request failed in tls error for {0}, trying curl fallback.", webRequest.RequestUri.Host);
_curlTLSFallbackCache.Set(webRequest.RequestUri.Host, true);
}
else
{
throw;
}
}
}
if (CurlHttpClient.CheckAvailability())
{
return ExecuteCurlRequest(request, webRequest);
}
_logger.Trace("Curl not available, using default WebClient.");
}
return ExecuteWebRequest(request, webRequest);
}
private HttpResponse ExecuteCurlRequest(HttpRequest request, HttpWebRequest webRequest)
{
var curlClient = new CurlHttpClient();
return curlClient.GetResponse(request, webRequest);
}
private HttpResponse ExecuteWebRequest(HttpRequest request, HttpWebRequest webRequest)
{
if (!request.Body.IsNullOrWhiteSpace())
{
var bytes = request.Headers.GetEncodingFromContentType().GetBytes(request.Body.ToCharArray());
@ -131,26 +201,7 @@ namespace NzbDrone.Common.Http
}
}
stopWatch.Stop();
var response = new HttpResponse(request, new HttpHeader(httpWebResponse.Headers), data, httpWebResponse.StatusCode);
_logger.Trace("{0} ({1:n0} ms)", response, stopWatch.ElapsedMilliseconds);
if (request.AllowAutoRedirect && !RuntimeInfoBase.IsProduction &&
(response.StatusCode == HttpStatusCode.Moved ||
response.StatusCode == HttpStatusCode.MovedPermanently ||
response.StatusCode == HttpStatusCode.Found))
{
_logger.Error("Server requested a redirect to [" + response.Headers["Location"] + "]. Update the request URL to avoid this redirect.");
}
if (!request.SuppressHttpError && response.HasHttpError)
{
_logger.Warn("HTTP Error - {0}", response);
throw new HttpException(request, response);
}
return response;
return new HttpResponse(request, new HttpHeader(httpWebResponse.Headers), data, httpWebResponse.StatusCode);
}
public void DownloadFile(string url, string fileName)