Create HttpProxySettingsProvider and fixed related issues.
This commit is contained in:
parent
f807e44a39
commit
9e7927acec
|
@ -20,7 +20,8 @@ namespace NzbDrone.Common.Http.Dispatchers
|
||||||
{
|
{
|
||||||
private static readonly Regex ExpiryDate = new Regex(@"(expires=)([^;]+)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
private static readonly Regex ExpiryDate = new Regex(@"(expires=)([^;]+)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
|
||||||
private static readonly Logger _logger = NzbDroneLogger.GetLogger(typeof(CurlHttpDispatcher));
|
private readonly IHttpProxySettingsProvider _proxySettingsProvider;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
private const string _caBundleFileName = "curl-ca-bundle.crt";
|
private const string _caBundleFileName = "curl-ca-bundle.crt";
|
||||||
private static readonly string _caBundleFilePath;
|
private static readonly string _caBundleFilePath;
|
||||||
|
@ -36,8 +37,14 @@ namespace NzbDrone.Common.Http.Dispatchers
|
||||||
_caBundleFilePath = _caBundleFileName;
|
_caBundleFilePath = _caBundleFileName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CurlHttpDispatcher(IHttpProxySettingsProvider proxySettingsProvider, Logger logger)
|
||||||
|
{
|
||||||
|
_proxySettingsProvider = proxySettingsProvider;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool CheckAvailability()
|
public bool CheckAvailability()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -76,32 +83,10 @@ namespace NzbDrone.Common.Http.Dispatchers
|
||||||
return s * n;
|
return s * n;
|
||||||
};
|
};
|
||||||
|
|
||||||
if(request.Proxy != null && !request.Proxy.ShouldProxyBeBypassed(new Uri(request.Url.FullUri)))
|
AddProxy(curlEasy, request);
|
||||||
|
|
||||||
{
|
|
||||||
switch (request.Proxy.Type)
|
|
||||||
{
|
|
||||||
case ProxyType.Http:
|
|
||||||
curlEasy.SetOpt(CurlOption.ProxyType, CurlProxyType.Http);
|
|
||||||
curlEasy.SetOpt(CurlOption.ProxyAuth, CurlHttpAuth.Basic);
|
|
||||||
curlEasy.SetOpt(CurlOption.ProxyUserPwd, request.Proxy.Username + ":" + request.Proxy.Password.ToString());
|
|
||||||
break;
|
|
||||||
case ProxyType.Socks4:
|
|
||||||
curlEasy.SetOpt(CurlOption.ProxyType, CurlProxyType.Socks4);
|
|
||||||
curlEasy.SetOpt(CurlOption.ProxyUsername, request.Proxy.Username);
|
|
||||||
curlEasy.SetOpt(CurlOption.ProxyPassword, request.Proxy.Password);
|
|
||||||
break;
|
|
||||||
case ProxyType.Socks5:
|
|
||||||
curlEasy.SetOpt(CurlOption.ProxyType, CurlProxyType.Socks5);
|
|
||||||
curlEasy.SetOpt(CurlOption.ProxyUsername, request.Proxy.Username);
|
|
||||||
curlEasy.SetOpt(CurlOption.ProxyPassword, request.Proxy.Password);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
curlEasy.SetOpt(CurlOption.Proxy, request.Proxy.Host + ":" + request.Proxy.Port.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
curlEasy.Url = request.Url.FullUri;
|
curlEasy.Url = request.Url.FullUri;
|
||||||
|
|
||||||
switch (request.Method)
|
switch (request.Method)
|
||||||
{
|
{
|
||||||
case HttpMethod.GET:
|
case HttpMethod.GET:
|
||||||
|
@ -174,6 +159,34 @@ namespace NzbDrone.Common.Http.Dispatchers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AddProxy(CurlEasy curlEasy, HttpRequest request)
|
||||||
|
{
|
||||||
|
var proxySettings = _proxySettingsProvider.GetProxySettings(request);
|
||||||
|
if (proxySettings != null)
|
||||||
|
|
||||||
|
{
|
||||||
|
switch (proxySettings.Type)
|
||||||
|
{
|
||||||
|
case ProxyType.Http:
|
||||||
|
curlEasy.SetOpt(CurlOption.ProxyType, CurlProxyType.Http);
|
||||||
|
curlEasy.SetOpt(CurlOption.ProxyAuth, CurlHttpAuth.Basic);
|
||||||
|
curlEasy.SetOpt(CurlOption.ProxyUserPwd, proxySettings.Username + ":" + proxySettings.Password.ToString());
|
||||||
|
break;
|
||||||
|
case ProxyType.Socks4:
|
||||||
|
curlEasy.SetOpt(CurlOption.ProxyType, CurlProxyType.Socks4);
|
||||||
|
curlEasy.SetOpt(CurlOption.ProxyUsername, proxySettings.Username);
|
||||||
|
curlEasy.SetOpt(CurlOption.ProxyPassword, proxySettings.Password);
|
||||||
|
break;
|
||||||
|
case ProxyType.Socks5:
|
||||||
|
curlEasy.SetOpt(CurlOption.ProxyType, CurlProxyType.Socks5);
|
||||||
|
curlEasy.SetOpt(CurlOption.ProxyUsername, proxySettings.Username);
|
||||||
|
curlEasy.SetOpt(CurlOption.ProxyPassword, proxySettings.Password);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
curlEasy.SetOpt(CurlOption.Proxy, proxySettings.Host + ":" + proxySettings.Port.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private CurlSlist SerializeHeaders(HttpRequest request)
|
private CurlSlist SerializeHeaders(HttpRequest request)
|
||||||
{
|
{
|
||||||
if (!request.Headers.ContainsKey("Accept-Encoding"))
|
if (!request.Headers.ContainsKey("Accept-Encoding"))
|
||||||
|
|
|
@ -8,17 +8,18 @@ namespace NzbDrone.Common.Http.Dispatchers
|
||||||
{
|
{
|
||||||
public class FallbackHttpDispatcher : IHttpDispatcher
|
public class FallbackHttpDispatcher : IHttpDispatcher
|
||||||
{
|
{
|
||||||
private readonly Logger _logger;
|
|
||||||
private readonly ICached<bool> _curlTLSFallbackCache;
|
|
||||||
private readonly ManagedHttpDispatcher _managedDispatcher;
|
private readonly ManagedHttpDispatcher _managedDispatcher;
|
||||||
private readonly CurlHttpDispatcher _curlDispatcher;
|
private readonly CurlHttpDispatcher _curlDispatcher;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public FallbackHttpDispatcher(ICached<bool> curlTLSFallbackCache, Logger logger)
|
private readonly ICached<bool> _curlTLSFallbackCache;
|
||||||
|
|
||||||
|
public FallbackHttpDispatcher(ManagedHttpDispatcher managedDispatcher, CurlHttpDispatcher curlDispatcher, ICacheManager cacheManager, Logger logger)
|
||||||
{
|
{
|
||||||
|
_managedDispatcher = managedDispatcher;
|
||||||
|
_curlDispatcher = curlDispatcher;
|
||||||
|
_curlTLSFallbackCache = cacheManager.GetCache<bool>(GetType(), "curlTLSFallback");
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_curlTLSFallbackCache = curlTLSFallbackCache;
|
|
||||||
_managedDispatcher = new ManagedHttpDispatcher();
|
|
||||||
_curlDispatcher = new CurlHttpDispatcher();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
|
public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
|
||||||
|
@ -46,7 +47,7 @@ namespace NzbDrone.Common.Http.Dispatchers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CurlHttpDispatcher.CheckAvailability())
|
if (_curlDispatcher.CheckAvailability())
|
||||||
{
|
{
|
||||||
return _curlDispatcher.GetResponse(request, cookies);
|
return _curlDispatcher.GetResponse(request, cookies);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,22 @@ using NzbDrone.Common.Extensions;
|
||||||
using com.LandonKey.SocksWebProxy.Proxy;
|
using com.LandonKey.SocksWebProxy.Proxy;
|
||||||
using com.LandonKey.SocksWebProxy;
|
using com.LandonKey.SocksWebProxy;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace NzbDrone.Common.Http.Dispatchers
|
namespace NzbDrone.Common.Http.Dispatchers
|
||||||
{
|
{
|
||||||
public class ManagedHttpDispatcher : IHttpDispatcher
|
public class ManagedHttpDispatcher : IHttpDispatcher
|
||||||
{
|
{
|
||||||
|
private readonly IHttpProxySettingsProvider _proxySettingsProvider;
|
||||||
|
|
||||||
|
private readonly ICached<IWebProxy> _webProxyCache;
|
||||||
|
|
||||||
|
public ManagedHttpDispatcher(IHttpProxySettingsProvider proxySettingsProvider, ICacheManager cacheManager)
|
||||||
|
{
|
||||||
|
_proxySettingsProvider = proxySettingsProvider;
|
||||||
|
|
||||||
|
_webProxyCache = cacheManager.GetCache<IWebProxy>(GetType(), "webProxy");
|
||||||
|
}
|
||||||
|
|
||||||
public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
|
public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
|
||||||
{
|
{
|
||||||
var webRequest = (HttpWebRequest)WebRequest.Create((Uri)request.Url);
|
var webRequest = (HttpWebRequest)WebRequest.Create((Uri)request.Url);
|
||||||
|
@ -30,42 +40,7 @@ namespace NzbDrone.Common.Http.Dispatchers
|
||||||
webRequest.Timeout = (int)Math.Ceiling(request.RequestTimeout.TotalMilliseconds);
|
webRequest.Timeout = (int)Math.Ceiling(request.RequestTimeout.TotalMilliseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.Proxy != null && !request.Proxy.ShouldProxyBeBypassed(new Uri(request.Url.FullUri)))
|
AddProxy(webRequest, request);
|
||||||
{
|
|
||||||
var addresses = Dns.GetHostAddresses(request.Proxy.Host);
|
|
||||||
|
|
||||||
if(addresses.Length > 1)
|
|
||||||
{
|
|
||||||
var ipv4Only = addresses.Where(a => a.AddressFamily == AddressFamily.InterNetwork);
|
|
||||||
if (ipv4Only.Any())
|
|
||||||
{
|
|
||||||
addresses = ipv4Only.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var socksUsername = request.Proxy.Username == null ? string.Empty : request.Proxy.Username;
|
|
||||||
var socksPassword = request.Proxy.Password == null ? string.Empty : request.Proxy.Password;
|
|
||||||
|
|
||||||
switch (request.Proxy.Type)
|
|
||||||
{
|
|
||||||
case ProxyType.Http:
|
|
||||||
if(request.Proxy.Username.IsNotNullOrWhiteSpace() && request.Proxy.Password.IsNotNullOrWhiteSpace())
|
|
||||||
{
|
|
||||||
webRequest.Proxy = new WebProxy(request.Proxy.Host + ":" + request.Proxy.Port, request.Proxy.BypassLocalAddress, request.Proxy.SubnetFilterAsArray, new NetworkCredential(request.Proxy.Username, request.Proxy.Password));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
webRequest.Proxy = new WebProxy(request.Proxy.Host + ":" + request.Proxy.Port, request.Proxy.BypassLocalAddress, request.Proxy.SubnetFilterAsArray);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ProxyType.Socks4:
|
|
||||||
webRequest.Proxy = new SocksWebProxy(new ProxyConfig(IPAddress.Parse("127.0.0.1"), GetNextFreePort(), addresses[0], request.Proxy.Port, ProxyConfig.SocksVersion.Four, socksUsername, socksPassword), false);
|
|
||||||
break;
|
|
||||||
case ProxyType.Socks5:
|
|
||||||
webRequest.Proxy = new SocksWebProxy(new ProxyConfig(IPAddress.Parse("127.0.0.1"), GetNextFreePort(), addresses[0], request.Proxy.Port, ProxyConfig.SocksVersion.Five, socksUsername, socksPassword), false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.Headers != null)
|
if (request.Headers != null)
|
||||||
{
|
{
|
||||||
|
@ -110,6 +85,50 @@ namespace NzbDrone.Common.Http.Dispatchers
|
||||||
return new HttpResponse(request, new HttpHeader(httpWebResponse.Headers), data, httpWebResponse.StatusCode);
|
return new HttpResponse(request, new HttpHeader(httpWebResponse.Headers), data, httpWebResponse.StatusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void AddProxy(HttpWebRequest webRequest, HttpRequest request)
|
||||||
|
{
|
||||||
|
var proxySettings = _proxySettingsProvider.GetProxySettings(request);
|
||||||
|
if (proxySettings != null)
|
||||||
|
{
|
||||||
|
webRequest.Proxy = _webProxyCache.Get(proxySettings.Key, () => CreateWebProxy(proxySettings), TimeSpan.FromMinutes(5));
|
||||||
|
}
|
||||||
|
|
||||||
|
_webProxyCache.ClearExpired();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IWebProxy CreateWebProxy(HttpRequestProxySettings proxySettings)
|
||||||
|
{
|
||||||
|
var addresses = Dns.GetHostAddresses(proxySettings.Host);
|
||||||
|
|
||||||
|
if(addresses.Length > 1)
|
||||||
|
{
|
||||||
|
var ipv4Only = addresses.Where(a => a.AddressFamily == AddressFamily.InterNetwork);
|
||||||
|
if (ipv4Only.Any())
|
||||||
|
{
|
||||||
|
addresses = ipv4Only.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (proxySettings.Type)
|
||||||
|
{
|
||||||
|
case ProxyType.Http:
|
||||||
|
if (proxySettings.Username.IsNotNullOrWhiteSpace() && proxySettings.Password.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return new WebProxy(proxySettings.Host + ":" + proxySettings.Port, proxySettings.BypassLocalAddress, proxySettings.SubnetFilterAsArray, new NetworkCredential(proxySettings.Username, proxySettings.Password));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new WebProxy(proxySettings.Host + ":" + proxySettings.Port, proxySettings.BypassLocalAddress, proxySettings.SubnetFilterAsArray);
|
||||||
|
}
|
||||||
|
case ProxyType.Socks4:
|
||||||
|
return new SocksWebProxy(new ProxyConfig(IPAddress.Loopback, GetNextFreePort(), addresses[0], proxySettings.Port, ProxyConfig.SocksVersion.Four, proxySettings.Username, proxySettings.Password), false);
|
||||||
|
case ProxyType.Socks5:
|
||||||
|
return new SocksWebProxy(new ProxyConfig(IPAddress.Loopback, GetNextFreePort(), addresses[0], proxySettings.Port, ProxyConfig.SocksVersion.Five, proxySettings.Username, proxySettings.Password), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual void AddRequestHeaders(HttpWebRequest webRequest, HttpHeader headers)
|
protected virtual void AddRequestHeaders(HttpWebRequest webRequest, HttpHeader headers)
|
||||||
{
|
{
|
||||||
foreach (var header in headers)
|
foreach (var header in headers)
|
||||||
|
|
|
@ -35,21 +35,15 @@ namespace NzbDrone.Common.Http
|
||||||
|
|
||||||
public HttpClient(IEnumerable<IHttpRequestInterceptor> requestInterceptors, ICacheManager cacheManager, IRateLimitService rateLimitService, IHttpDispatcher httpDispatcher, Logger logger)
|
public HttpClient(IEnumerable<IHttpRequestInterceptor> requestInterceptors, ICacheManager cacheManager, IRateLimitService rateLimitService, IHttpDispatcher httpDispatcher, Logger logger)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
|
||||||
_rateLimitService = rateLimitService;
|
|
||||||
_requestInterceptors = requestInterceptors.ToList();
|
_requestInterceptors = requestInterceptors.ToList();
|
||||||
ServicePointManager.DefaultConnectionLimit = 12;
|
_rateLimitService = rateLimitService;
|
||||||
_httpDispatcher = httpDispatcher;
|
_httpDispatcher = httpDispatcher;
|
||||||
|
_logger = logger;
|
||||||
|
|
||||||
|
ServicePointManager.DefaultConnectionLimit = 12;
|
||||||
_cookieContainerCache = cacheManager.GetCache<CookieContainer>(typeof(HttpClient));
|
_cookieContainerCache = cacheManager.GetCache<CookieContainer>(typeof(HttpClient));
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpClient(IEnumerable<IHttpRequestInterceptor> requestInterceptors, ICacheManager cacheManager, IRateLimitService rateLimitService, Logger logger)
|
|
||||||
: this(requestInterceptors, cacheManager, rateLimitService, null, logger)
|
|
||||||
{
|
|
||||||
_httpDispatcher = new FallbackHttpDispatcher(cacheManager.GetCache<bool>(typeof(HttpClient), "curlTLSFallback"), _logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpResponse Execute(HttpRequest request)
|
public HttpResponse Execute(HttpRequest request)
|
||||||
{
|
{
|
||||||
foreach (var interceptor in _requestInterceptors)
|
foreach (var interceptor in _requestInterceptors)
|
||||||
|
|
|
@ -41,7 +41,6 @@ namespace NzbDrone.Common.Http
|
||||||
public bool StoreResponseCookie { get; set; }
|
public bool StoreResponseCookie { get; set; }
|
||||||
public TimeSpan RequestTimeout { get; set; }
|
public TimeSpan RequestTimeout { get; set; }
|
||||||
public TimeSpan RateLimit { get; set; }
|
public TimeSpan RateLimit { get; set; }
|
||||||
public HttpRequestProxySettings Proxy {get; set;}
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
|
||||||
namespace NzbDrone.Common.Http
|
namespace NzbDrone.Common.Http
|
||||||
{
|
{
|
||||||
public class HttpRequestProxySettings
|
public class HttpRequestProxySettings
|
||||||
{
|
{
|
||||||
public HttpRequestProxySettings(ProxyType type, string host, int port, string filterSubnet, bool bypassLocalAddress, string username = null, string password = null)
|
public HttpRequestProxySettings(ProxyType type, string host, int port, string bypassFilter, bool bypassLocalAddress, string username = null, string password = null)
|
||||||
{
|
{
|
||||||
Type = type;
|
Type = type;
|
||||||
Host = host;
|
Host = host.IsNullOrWhiteSpace() ? "127.0.0.1" : host;
|
||||||
Port = port;
|
Port = port;
|
||||||
Username = username;
|
Username = username ?? string.Empty;
|
||||||
Password = password;
|
Password = password ?? string.Empty;
|
||||||
SubnetFilter = filterSubnet;
|
BypassFilter = bypassFilter ?? string.Empty;
|
||||||
BypassLocalAddress = bypassLocalAddress;
|
BypassLocalAddress = bypassLocalAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,27 +22,34 @@ namespace NzbDrone.Common.Http
|
||||||
public int Port { get; private set; }
|
public int Port { get; private set; }
|
||||||
public string Username { get; private set; }
|
public string Username { get; private set; }
|
||||||
public string Password { get; private set; }
|
public string Password { get; private set; }
|
||||||
public string SubnetFilter { get; private set; }
|
public string BypassFilter { get; private set; }
|
||||||
public bool BypassLocalAddress { get; private set; }
|
public bool BypassLocalAddress { get; private set; }
|
||||||
|
|
||||||
public string[] SubnetFilterAsArray
|
public string[] SubnetFilterAsArray
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(SubnetFilter))
|
if (!string.IsNullOrWhiteSpace(BypassFilter))
|
||||||
{
|
{
|
||||||
return SubnetFilter.Split(';');
|
return BypassFilter.Split(';');
|
||||||
}
|
}
|
||||||
return new string[] { };
|
return new string[] { };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ShouldProxyBeBypassed(Uri url)
|
public string Key
|
||||||
{
|
{
|
||||||
//We are utilising the WebProxy implementation here to save us having to reimplement it. This way we use Microsofts implementation
|
get
|
||||||
WebProxy proxy = new WebProxy(Host + ":" + Port, BypassLocalAddress, SubnetFilterAsArray);
|
{
|
||||||
|
return string.Join("_",
|
||||||
return proxy.IsBypassed(url);
|
Type,
|
||||||
|
Host,
|
||||||
|
Port,
|
||||||
|
Username,
|
||||||
|
Password,
|
||||||
|
BypassFilter,
|
||||||
|
BypassLocalAddress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace NzbDrone.Common.Http
|
||||||
|
{
|
||||||
|
public interface IHttpProxySettingsProvider
|
||||||
|
{
|
||||||
|
HttpRequestProxySettings GetProxySettings(HttpRequest request);
|
||||||
|
}
|
||||||
|
}
|
|
@ -171,6 +171,7 @@
|
||||||
<Compile Include="Http\HttpRequestProxySettings.cs" />
|
<Compile Include="Http\HttpRequestProxySettings.cs" />
|
||||||
<Compile Include="Http\HttpResponse.cs" />
|
<Compile Include="Http\HttpResponse.cs" />
|
||||||
<Compile Include="Http\HttpUri.cs" />
|
<Compile Include="Http\HttpUri.cs" />
|
||||||
|
<Compile Include="Http\IHttpProxySettingsProvider.cs" />
|
||||||
<Compile Include="Http\IHttpRequestInterceptor.cs" />
|
<Compile Include="Http\IHttpRequestInterceptor.cs" />
|
||||||
<Compile Include="Http\JsonRpcRequestBuilder.cs" />
|
<Compile Include="Http\JsonRpcRequestBuilder.cs" />
|
||||||
<Compile Include="Http\JsonRpcResponse.cs" />
|
<Compile Include="Http\JsonRpcResponse.cs" />
|
||||||
|
|
|
@ -3,6 +3,7 @@ using NUnit.Framework;
|
||||||
using NzbDrone.Common.Cache;
|
using NzbDrone.Common.Cache;
|
||||||
using NzbDrone.Common.Cloud;
|
using NzbDrone.Common.Cloud;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
|
using NzbDrone.Common.Http.Dispatchers;
|
||||||
using NzbDrone.Common.TPL;
|
using NzbDrone.Common.TPL;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
|
|
||||||
|
@ -13,7 +14,7 @@ namespace NzbDrone.Core.Test.Framework
|
||||||
protected void UseRealHttp()
|
protected void UseRealHttp()
|
||||||
{
|
{
|
||||||
Mocker.SetConstant<IHttpProvider>(new HttpProvider(TestLogger));
|
Mocker.SetConstant<IHttpProvider>(new HttpProvider(TestLogger));
|
||||||
Mocker.SetConstant<IHttpClient>(new HttpClient(new IHttpRequestInterceptor[0], Mocker.Resolve<CacheManager>(), Mocker.Resolve<RateLimitService>(), TestLogger));
|
Mocker.SetConstant<IHttpClient>(new HttpClient(new IHttpRequestInterceptor[0], Mocker.Resolve<CacheManager>(), Mocker.Resolve<RateLimitService>(), Mocker.Resolve<FallbackHttpDispatcher>(), TestLogger));
|
||||||
Mocker.SetConstant<ISonarrCloudRequestBuilder>(new SonarrCloudRequestBuilder());
|
Mocker.SetConstant<ISonarrCloudRequestBuilder>(new SonarrCloudRequestBuilder());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
using NzbDrone.Common.Http;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Net;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Http
|
||||||
|
{
|
||||||
|
public class HttpProxySettingsProvider : IHttpProxySettingsProvider
|
||||||
|
{
|
||||||
|
private readonly IConfigService _configService;
|
||||||
|
|
||||||
|
public HttpProxySettingsProvider(IConfigService configService)
|
||||||
|
{
|
||||||
|
_configService = configService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpRequestProxySettings GetProxySettings(HttpRequest request)
|
||||||
|
{
|
||||||
|
if (!_configService.ProxyEnabled)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var proxySettings = new HttpRequestProxySettings(_configService.ProxyType,
|
||||||
|
_configService.ProxyHostname,
|
||||||
|
_configService.ProxyPort,
|
||||||
|
_configService.ProxySubnetFilter,
|
||||||
|
_configService.ProxyBypassLocalAddresses,
|
||||||
|
_configService.ProxyUsername,
|
||||||
|
_configService.ProxyPassword);
|
||||||
|
|
||||||
|
if (ShouldProxyBeBypassed(proxySettings, request.Url))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return proxySettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ShouldProxyBeBypassed(HttpRequestProxySettings proxySettings, HttpUri url)
|
||||||
|
{
|
||||||
|
//We are utilising the WebProxy implementation here to save us having to reimplement it. This way we use Microsofts implementation
|
||||||
|
var proxy = new WebProxy(proxySettings.Host + ":" + proxySettings.Port, proxySettings.BypassLocalAddress, proxySettings.SubnetFilterAsArray);
|
||||||
|
|
||||||
|
return proxy.IsBypassed((Uri)url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,40 +0,0 @@
|
||||||
using NzbDrone.Common.Http;
|
|
||||||
using NzbDrone.Core.Configuration;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Http
|
|
||||||
{
|
|
||||||
public class ProxyHttpInterceptor : IHttpRequestInterceptor
|
|
||||||
{
|
|
||||||
private readonly IConfigService _configService;
|
|
||||||
|
|
||||||
public ProxyHttpInterceptor(IConfigService configService)
|
|
||||||
{
|
|
||||||
this._configService = configService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpResponse PostResponse(HttpResponse response)
|
|
||||||
{
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpRequest PreRequest(HttpRequest request)
|
|
||||||
{
|
|
||||||
if(_configService.ProxyEnabled)
|
|
||||||
{
|
|
||||||
request.Proxy = new HttpRequestProxySettings(_configService.ProxyType,
|
|
||||||
_configService.ProxyHostname,
|
|
||||||
_configService.ProxyPort,
|
|
||||||
_configService.ProxySubnetFilter,
|
|
||||||
_configService.ProxyBypassLocalAddresses,
|
|
||||||
_configService.ProxyUsername,
|
|
||||||
_configService.ProxyPassword);
|
|
||||||
}
|
|
||||||
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -515,7 +515,7 @@
|
||||||
<Compile Include="Housekeeping\HousekeepingCommand.cs" />
|
<Compile Include="Housekeeping\HousekeepingCommand.cs" />
|
||||||
<Compile Include="Housekeeping\HousekeepingService.cs" />
|
<Compile Include="Housekeeping\HousekeepingService.cs" />
|
||||||
<Compile Include="Housekeeping\IHousekeepingTask.cs" />
|
<Compile Include="Housekeeping\IHousekeepingTask.cs" />
|
||||||
<Compile Include="Http\ProxyHttpInterceptor.cs" />
|
<Compile Include="Http\HttpProxySettingsProvider.cs" />
|
||||||
<Compile Include="Http\TorcacheHttpInterceptor.cs" />
|
<Compile Include="Http\TorcacheHttpInterceptor.cs" />
|
||||||
<Compile Include="Indexers\BitMeTv\BitMeTv.cs" />
|
<Compile Include="Indexers\BitMeTv\BitMeTv.cs" />
|
||||||
<Compile Include="Indexers\BitMeTv\BitMeTvSettings.cs" />
|
<Compile Include="Indexers\BitMeTv\BitMeTvSettings.cs" />
|
||||||
|
|
|
@ -4,6 +4,7 @@ using Nancy.Bootstrapper;
|
||||||
using NzbDrone.Api;
|
using NzbDrone.Api;
|
||||||
using NzbDrone.Common.Composition;
|
using NzbDrone.Common.Composition;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
|
using NzbDrone.Common.Http.Dispatchers;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Organizer;
|
using NzbDrone.Core.Organizer;
|
||||||
using NzbDrone.SignalR;
|
using NzbDrone.SignalR;
|
||||||
|
@ -42,6 +43,7 @@ namespace NzbDrone.Host
|
||||||
AutoRegisterImplementations<NzbDronePersistentConnection>();
|
AutoRegisterImplementations<NzbDronePersistentConnection>();
|
||||||
|
|
||||||
Container.Register<INancyBootstrapper, NancyBootstrapper>();
|
Container.Register<INancyBootstrapper, NancyBootstrapper>();
|
||||||
|
Container.Register<IHttpDispatcher, FallbackHttpDispatcher>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Common.Composition;
|
using NzbDrone.Common.Composition;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
|
using NzbDrone.Common.Http.Dispatchers;
|
||||||
|
|
||||||
namespace NzbDrone.Update
|
namespace NzbDrone.Update
|
||||||
{
|
{
|
||||||
|
@ -10,7 +11,7 @@ namespace NzbDrone.Update
|
||||||
private UpdateContainerBuilder(IStartupContext startupContext, string[] assemblies)
|
private UpdateContainerBuilder(IStartupContext startupContext, string[] assemblies)
|
||||||
: base(startupContext, assemblies)
|
: base(startupContext, assemblies)
|
||||||
{
|
{
|
||||||
|
Container.Register<IHttpDispatcher, FallbackHttpDispatcher>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IContainer Build(IStartupContext startupContext)
|
public static IContainer Build(IStartupContext startupContext)
|
||||||
|
|
Loading…
Reference in New Issue