parent
e13c89521d
commit
fe76d0f98f
@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
|
||||
namespace NzbDrone.Common.Http.Dispatchers
|
||||
{
|
||||
public class FallbackHttpDispatcher : IHttpDispatcher
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
private readonly ICached<bool> _curlTLSFallbackCache;
|
||||
private readonly ManagedHttpDispatcher _managedDispatcher;
|
||||
private readonly CurlHttpDispatcher _curlDispatcher;
|
||||
|
||||
public FallbackHttpDispatcher(ICached<bool> curlTLSFallbackCache, Logger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
_curlTLSFallbackCache = curlTLSFallbackCache;
|
||||
_managedDispatcher = new ManagedHttpDispatcher();
|
||||
_curlDispatcher = new CurlHttpDispatcher();
|
||||
}
|
||||
|
||||
public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
|
||||
{
|
||||
if (OsInfo.IsMonoRuntime && request.Url.Scheme == "https")
|
||||
{
|
||||
if (!_curlTLSFallbackCache.Find(request.Url.Host))
|
||||
{
|
||||
try
|
||||
{
|
||||
return _managedDispatcher.GetResponse(request, cookies);
|
||||
}
|
||||
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.", request.Url.Host);
|
||||
|
||||
_curlTLSFallbackCache.Set(request.Url.Host, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CurlHttpDispatcher.CheckAvailability())
|
||||
{
|
||||
return _curlDispatcher.GetResponse(request, cookies);
|
||||
}
|
||||
|
||||
_logger.Trace("Curl not available, using default WebClient.");
|
||||
}
|
||||
|
||||
return _managedDispatcher.GetResponse(request, cookies);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.TPL;
|
||||
|
||||
namespace NzbDrone.Common.Http.Dispatchers
|
||||
{
|
||||
public interface IHttpDispatcher
|
||||
{
|
||||
HttpResponse GetResponse(HttpRequest request, CookieContainer cookies);
|
||||
}
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using NzbDrone.Common.Extensions;
|
||||
|
||||
namespace NzbDrone.Common.Http.Dispatchers
|
||||
{
|
||||
public class ManagedHttpDispatcher : IHttpDispatcher
|
||||
{
|
||||
public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
|
||||
{
|
||||
var webRequest = (HttpWebRequest)WebRequest.Create(request.Url);
|
||||
|
||||
// Deflate is not a standard and could break depending on implementation.
|
||||
// we should just stick with the more compatible Gzip
|
||||
//http://stackoverflow.com/questions/8490718/how-to-decompress-stream-deflated-with-java-util-zip-deflater-in-net
|
||||
webRequest.AutomaticDecompression = DecompressionMethods.GZip;
|
||||
|
||||
webRequest.Credentials = request.NetworkCredential;
|
||||
webRequest.Method = request.Method.ToString();
|
||||
webRequest.UserAgent = UserAgentBuilder.UserAgent;
|
||||
webRequest.KeepAlive = false;
|
||||
webRequest.AllowAutoRedirect = request.AllowAutoRedirect;
|
||||
webRequest.ContentLength = 0;
|
||||
webRequest.CookieContainer = cookies;
|
||||
|
||||
if (request.Headers != null)
|
||||
{
|
||||
AddRequestHeaders(webRequest, request.Headers);
|
||||
}
|
||||
|
||||
if (!request.Body.IsNullOrWhiteSpace())
|
||||
{
|
||||
var bytes = request.Headers.GetEncodingFromContentType().GetBytes(request.Body.ToCharArray());
|
||||
|
||||
webRequest.ContentLength = bytes.Length;
|
||||
using (var writeStream = webRequest.GetRequestStream())
|
||||
{
|
||||
writeStream.Write(bytes, 0, bytes.Length);
|
||||
}
|
||||
}
|
||||
|
||||
HttpWebResponse httpWebResponse;
|
||||
|
||||
try
|
||||
{
|
||||
httpWebResponse = (HttpWebResponse)webRequest.GetResponse();
|
||||
}
|
||||
catch (WebException e)
|
||||
{
|
||||
httpWebResponse = (HttpWebResponse)e.Response;
|
||||
|
||||
if (httpWebResponse == null)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
byte[] data = null;
|
||||
|
||||
using (var responseStream = httpWebResponse.GetResponseStream())
|
||||
{
|
||||
if (responseStream != null)
|
||||
{
|
||||
data = responseStream.ToBytes();
|
||||
}
|
||||
}
|
||||
|
||||
return new HttpResponse(request, new HttpHeader(httpWebResponse.Headers), data, httpWebResponse.StatusCode);
|
||||
}
|
||||
|
||||
protected virtual void AddRequestHeaders(HttpWebRequest webRequest, HttpHeader headers)
|
||||
{
|
||||
foreach (var header in headers)
|
||||
{
|
||||
switch (header.Key)
|
||||
{
|
||||
case "Accept":
|
||||
webRequest.Accept = header.Value.ToString();
|
||||
break;
|
||||
case "Connection":
|
||||
webRequest.Connection = header.Value.ToString();
|
||||
break;
|
||||
case "Content-Length":
|
||||
webRequest.ContentLength = Convert.ToInt64(header.Value);
|
||||
break;
|
||||
case "Content-Type":
|
||||
webRequest.ContentType = header.Value.ToString();
|
||||
break;
|
||||
case "Date":
|
||||
webRequest.Date = (DateTime)header.Value;
|
||||
break;
|
||||
case "Expect":
|
||||
webRequest.Expect = header.Value.ToString();
|
||||
break;
|
||||
case "Host":
|
||||
webRequest.Host = header.Value.ToString();
|
||||
break;
|
||||
case "If-Modified-Since":
|
||||
webRequest.IfModifiedSince = (DateTime)header.Value;
|
||||
break;
|
||||
case "Range":
|
||||
throw new NotImplementedException();
|
||||
break;
|
||||
case "Referer":
|
||||
webRequest.Referer = header.Value.ToString();
|
||||
break;
|
||||
case "Transfer-Encoding":
|
||||
webRequest.TransferEncoding = header.Value.ToString();
|
||||
break;
|
||||
case "User-Agent":
|
||||
throw new NotSupportedException("User-Agent other than Sonarr not allowed.");
|
||||
case "Proxy-Connection":
|
||||
throw new NotImplementedException();
|
||||
break;
|
||||
default:
|
||||
webRequest.Headers.Add(header.Key, header.Value.ToString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue