diff --git a/src/Jackett.Common/Utils/Clients/HttpWebClient.cs b/src/Jackett.Common/Utils/Clients/HttpWebClient.cs index 184adce0f..567a7bb22 100644 --- a/src/Jackett.Common/Utils/Clients/HttpWebClient.cs +++ b/src/Jackett.Common/Utils/Clients/HttpWebClient.cs @@ -1,17 +1,12 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Net; using System.Net.Http; -using System.Net.Security; -using System.Security.Cryptography.X509Certificates; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using CloudflareSolverRe; -using com.LandonKey.SocksWebProxy; -using com.LandonKey.SocksWebProxy.Proxy; using Jackett.Common.Helpers; using Jackett.Common.Models.Config; using Jackett.Common.Services.Interfaces; @@ -21,106 +16,19 @@ namespace Jackett.Common.Utils.Clients { public class HttpWebClient : WebClient { - protected static Dictionary> trustedCertificates = new Dictionary>(); - protected static string webProxyUrl; - protected static IWebProxy webProxy; - - [DebuggerNonUserCode] // avoid "Exception User-Unhandled" Visual Studio messages - public static bool ValidateCertificate(HttpRequestMessage request, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) - { - var hash = certificate.GetCertHashString(); - - - trustedCertificates.TryGetValue(hash, out var hosts); - if (hosts != null) - { - if (hosts.Contains(request.RequestUri.Host)) - return true; - } - - if (sslPolicyErrors != SslPolicyErrors.None) - { - // Throw exception with certificate details, this will cause a "Exception User-Unhandled" when running it in the Visual Studio debugger. - // The certificate is only available inside this function, so we can't catch it at the calling method. - throw new Exception("certificate validation failed: " + certificate.ToString()); - } - - return sslPolicyErrors == SslPolicyErrors.None; - } - - public static void InitProxy(ServerConfig serverConfig) - { - // dispose old SocksWebProxy - if (webProxy is SocksWebProxy proxy) - proxy.Dispose(); - webProxy = null; - webProxyUrl = serverConfig.GetProxyUrl(); - if (!string.IsNullOrWhiteSpace(webProxyUrl)) - { - if (serverConfig.ProxyType != ProxyType.Http) - { - var addresses = Dns.GetHostAddressesAsync(serverConfig.ProxyUrl).Result; - var socksConfig = new ProxyConfig - { - SocksAddress = addresses.FirstOrDefault(), - Username = serverConfig.ProxyUsername, - Password = serverConfig.ProxyPassword, - Version = serverConfig.ProxyType == ProxyType.Socks4 ? - ProxyConfig.SocksVersion.Four : - ProxyConfig.SocksVersion.Five - }; - if (serverConfig.ProxyPort.HasValue) - { - socksConfig.SocksPort = serverConfig.ProxyPort.Value; - } - webProxy = new SocksWebProxy(socksConfig, false); - } - else - { - NetworkCredential creds = null; - if (!serverConfig.ProxyIsAnonymous) - { - var username = serverConfig.ProxyUsername; - var password = serverConfig.ProxyPassword; - creds = new NetworkCredential(username, password); - } - webProxy = new WebProxy(webProxyUrl) - { - BypassProxyOnLocal = false, - Credentials = creds - }; - } - } - } - public HttpWebClient(IProcessService p, Logger l, IConfigurationService c, ServerConfig sc) : base(p: p, l: l, c: c, sc: sc) { - if (webProxyUrl == null) - InitProxy(sc); - } - - // Called everytime the ServerConfig changes - public override void OnNext(ServerConfig value) - { - var newProxyUrl = serverConfig.GetProxyUrl(); - if (webProxyUrl != newProxyUrl) // if proxy URL changed - InitProxy(serverConfig); } public override void Init() { ServicePointManager.DefaultConnectionLimit = 1000; - if (serverConfig.RuntimeSettings.IgnoreSslErrors == true) - { - logger.Info(string.Format("HttpWebClient: Disabling certificate validation")); - ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return true; }; - } - + base.Init(); } protected override async Task Run(WebRequest webRequest) @@ -301,17 +209,5 @@ namespace Jackett.Common.Utils.Clients } } } - - public override void AddTrustedCertificate(string host, string hash) - { - hash = hash.ToUpper(); - trustedCertificates.TryGetValue(hash.ToUpper(), out var hosts); - if (hosts == null) - { - hosts = new HashSet(); - trustedCertificates[hash] = hosts; - } - hosts.Add(host); - } } } diff --git a/src/Jackett.Common/Utils/Clients/HttpWebClient2.cs b/src/Jackett.Common/Utils/Clients/HttpWebClient2.cs index f8ea2f9d8..117020ac3 100644 --- a/src/Jackett.Common/Utils/Clients/HttpWebClient2.cs +++ b/src/Jackett.Common/Utils/Clients/HttpWebClient2.cs @@ -1,17 +1,12 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Net; using System.Net.Http; -using System.Net.Security; -using System.Security.Cryptography.X509Certificates; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using CloudflareSolverRe; -using com.LandonKey.SocksWebProxy; -using com.LandonKey.SocksWebProxy.Proxy; using Jackett.Common.Helpers; using Jackett.Common.Models.Config; using Jackett.Common.Services.Interfaces; @@ -27,88 +22,13 @@ namespace Jackett.Common.Utils.Clients private ClearanceHandler clearanceHandlr; private HttpClientHandler clientHandlr; private HttpClient client; - - protected static Dictionary> trustedCertificates = new Dictionary>(); - protected static string webProxyUrl; - protected static IWebProxy webProxy; - - [DebuggerNonUserCode] // avoid "Exception User-Unhandled" Visual Studio messages - public static bool ValidateCertificate(HttpRequestMessage request, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) - { - var hash = certificate.GetCertHashString(); - - - trustedCertificates.TryGetValue(hash, out var hosts); - if (hosts != null) - { - if (hosts.Contains(request.RequestUri.Host)) - return true; - } - - if (sslPolicyErrors != SslPolicyErrors.None) - { - // Throw exception with certificate details, this will cause a "Exception User-Unhandled" when running it in the Visual Studio debugger. - // The certificate is only available inside this function, so we can't catch it at the calling method. - throw new Exception("certificate validation failed: " + certificate.ToString()); - } - - return sslPolicyErrors == SslPolicyErrors.None; - } - - public static void InitProxy(ServerConfig serverConfig) - { - // dispose old SocksWebProxy - if (webProxy is SocksWebProxy proxy) - proxy.Dispose(); - webProxy = null; - webProxyUrl = serverConfig.GetProxyUrl(); - if (!string.IsNullOrWhiteSpace(webProxyUrl)) - { - if (serverConfig.ProxyType != ProxyType.Http) - { - var addresses = Dns.GetHostAddressesAsync(serverConfig.ProxyUrl).Result; - var socksConfig = new ProxyConfig - { - SocksAddress = addresses.FirstOrDefault(), - Username = serverConfig.ProxyUsername, - Password = serverConfig.ProxyPassword, - Version = serverConfig.ProxyType == ProxyType.Socks4 ? - ProxyConfig.SocksVersion.Four : - ProxyConfig.SocksVersion.Five - }; - if (serverConfig.ProxyPort.HasValue) - { - socksConfig.SocksPort = serverConfig.ProxyPort.Value; - } - webProxy = new SocksWebProxy(socksConfig, false); - } - else - { - NetworkCredential creds = null; - if (!serverConfig.ProxyIsAnonymous) - { - var username = serverConfig.ProxyUsername; - var password = serverConfig.ProxyPassword; - creds = new NetworkCredential(username, password); - } - webProxy = new WebProxy(webProxyUrl) - { - BypassProxyOnLocal = false, - Credentials = creds - }; - } - } - } - + public HttpWebClient2(IProcessService p, Logger l, IConfigurationService c, ServerConfig sc) : base(p: p, l: l, c: c, sc: sc) { - if (webProxyUrl == null) - InitProxy(sc); - cookies = new CookieContainer(); CreateClient(); } @@ -139,10 +59,7 @@ namespace Jackett.Common.Utils.Clients // Called everytime the ServerConfig changes public override void OnNext(ServerConfig value) { - var newProxyUrl = serverConfig.GetProxyUrl(); - if (webProxyUrl != newProxyUrl) // if proxy URL changed - InitProxy(serverConfig); - + base.OnNext(value); // recreate client if needed (can't just change the proxy attribute) if (!ReferenceEquals(clientHandlr.Proxy, webProxy)) { @@ -152,11 +69,7 @@ namespace Jackett.Common.Utils.Clients public override void Init() { - if (serverConfig.RuntimeSettings.IgnoreSslErrors == true) - { - logger.Info(string.Format("HttpWebClient2: Disabling certificate validation")); - ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return true; }; - } + base.Init(); ServicePointManager.SecurityProtocol = (SecurityProtocolType)192 | (SecurityProtocolType)768 | (SecurityProtocolType)3072; } @@ -316,17 +229,5 @@ namespace Jackett.Common.Utils.Clients ServerUtil.ResureRedirectIsFullyQualified(webRequest, result); return result; } - - public override void AddTrustedCertificate(string host, string hash) - { - hash = hash.ToUpper(); - trustedCertificates.TryGetValue(hash.ToUpper(), out var hosts); - if (hosts == null) - { - hosts = new HashSet(); - trustedCertificates[hash] = hosts; - } - hosts.Add(host); - } } } diff --git a/src/Jackett.Common/Utils/Clients/HttpWebClient2NetCore.cs b/src/Jackett.Common/Utils/Clients/HttpWebClient2NetCore.cs index 34f111bb5..b0260d3fc 100644 --- a/src/Jackett.Common/Utils/Clients/HttpWebClient2NetCore.cs +++ b/src/Jackett.Common/Utils/Clients/HttpWebClient2NetCore.cs @@ -1,17 +1,12 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Net; using System.Net.Http; -using System.Net.Security; -using System.Security.Cryptography.X509Certificates; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using CloudflareSolverRe; -using com.LandonKey.SocksWebProxy; -using com.LandonKey.SocksWebProxy.Proxy; using Jackett.Common.Helpers; using Jackett.Common.Models.Config; using Jackett.Common.Services.Interfaces; @@ -28,87 +23,12 @@ namespace Jackett.Common.Utils.Clients private HttpClientHandler clientHandlr; private HttpClient client; - protected static Dictionary> trustedCertificates = new Dictionary>(); - protected static string webProxyUrl; - protected static IWebProxy webProxy; - - [DebuggerNonUserCode] // avoid "Exception User-Unhandled" Visual Studio messages - public static bool ValidateCertificate(HttpRequestMessage request, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) - { - var hash = certificate.GetCertHashString(); - - - trustedCertificates.TryGetValue(hash, out var hosts); - if (hosts != null) - { - if (hosts.Contains(request.RequestUri.Host)) - return true; - } - - if (sslPolicyErrors != SslPolicyErrors.None) - { - // Throw exception with certificate details, this will cause a "Exception User-Unhandled" when running it in the Visual Studio debugger. - // The certificate is only available inside this function, so we can't catch it at the calling method. - throw new Exception("certificate validation failed: " + certificate.ToString()); - } - - return sslPolicyErrors == SslPolicyErrors.None; - } - - public static void InitProxy(ServerConfig serverConfig) - { - // dispose old SocksWebProxy - if (webProxy is SocksWebProxy proxy) - proxy.Dispose(); - webProxy = null; - webProxyUrl = serverConfig.GetProxyUrl(); - if (!string.IsNullOrWhiteSpace(webProxyUrl)) - { - if (serverConfig.ProxyType != ProxyType.Http) - { - var addresses = Dns.GetHostAddressesAsync(serverConfig.ProxyUrl).Result; - var socksConfig = new ProxyConfig - { - SocksAddress = addresses.FirstOrDefault(), - Username = serverConfig.ProxyUsername, - Password = serverConfig.ProxyPassword, - Version = serverConfig.ProxyType == ProxyType.Socks4 ? - ProxyConfig.SocksVersion.Four : - ProxyConfig.SocksVersion.Five - }; - if (serverConfig.ProxyPort.HasValue) - { - socksConfig.SocksPort = serverConfig.ProxyPort.Value; - } - webProxy = new SocksWebProxy(socksConfig, false); - } - else - { - NetworkCredential creds = null; - if (!serverConfig.ProxyIsAnonymous) - { - var username = serverConfig.ProxyUsername; - var password = serverConfig.ProxyPassword; - creds = new NetworkCredential(username, password); - } - webProxy = new WebProxy(webProxyUrl) - { - BypassProxyOnLocal = false, - Credentials = creds - }; - } - } - } - public HttpWebClient2NetCore(IProcessService p, Logger l, IConfigurationService c, ServerConfig sc) : base(p: p, l: l, c: c, sc: sc) { - if (webProxyUrl == null) - InitProxy(sc); - cookies = new CookieContainer(); CreateClient(); } @@ -139,10 +59,7 @@ namespace Jackett.Common.Utils.Clients // Called everytime the ServerConfig changes public override void OnNext(ServerConfig value) { - var newProxyUrl = serverConfig.GetProxyUrl(); - if (webProxyUrl != newProxyUrl) // if proxy URL changed - InitProxy(serverConfig); - + base.OnNext(value); // recreate client if needed (can't just change the proxy attribute) if (!ReferenceEquals(clientHandlr.Proxy, webProxy)) { @@ -154,11 +71,7 @@ namespace Jackett.Common.Utils.Clients { ServicePointManager.DefaultConnectionLimit = 1000; - if (serverConfig.RuntimeSettings.IgnoreSslErrors == true) - { - logger.Info(string.Format("HttpWebClient: Disabling certificate validation")); - ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return true; }; - } + base.Init(); } protected override async Task Run(WebRequest webRequest) @@ -316,17 +229,5 @@ namespace Jackett.Common.Utils.Clients ServerUtil.ResureRedirectIsFullyQualified(webRequest, result); return result; } - - public override void AddTrustedCertificate(string host, string hash) - { - hash = hash.ToUpper(); - trustedCertificates.TryGetValue(hash.ToUpper(), out var hosts); - if (hosts == null) - { - hosts = new HashSet(); - trustedCertificates[hash] = hosts; - } - hosts.Add(host); - } } } diff --git a/src/Jackett.Common/Utils/Clients/HttpWebClientNetCore.cs b/src/Jackett.Common/Utils/Clients/HttpWebClientNetCore.cs index afa458ee5..71cfa3b6e 100644 --- a/src/Jackett.Common/Utils/Clients/HttpWebClientNetCore.cs +++ b/src/Jackett.Common/Utils/Clients/HttpWebClientNetCore.cs @@ -1,17 +1,12 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Net; using System.Net.Http; -using System.Net.Security; -using System.Security.Cryptography.X509Certificates; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using CloudflareSolverRe; -using com.LandonKey.SocksWebProxy; -using com.LandonKey.SocksWebProxy.Proxy; using Jackett.Common.Helpers; using Jackett.Common.Models.Config; using Jackett.Common.Services.Interfaces; @@ -22,107 +17,18 @@ namespace Jackett.Common.Utils.Clients // custom HttpWebClient based WebClient for netcore (due to changed custom certificate validation API) public class HttpWebClientNetCore : WebClient { - protected static Dictionary> trustedCertificates = new Dictionary>(); - protected static string webProxyUrl; - protected static IWebProxy webProxy; - - [DebuggerNonUserCode] // avoid "Exception User-Unhandled" Visual Studio messages - public static bool ValidateCertificate(HttpRequestMessage request, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) - { - { - var hash = certificate.GetCertHashString(); - - - trustedCertificates.TryGetValue(hash, out var hosts); - if (hosts != null) - { - if (hosts.Contains(request.RequestUri.Host)) - return true; - } - - if (sslPolicyErrors != SslPolicyErrors.None) - { - // Throw exception with certificate details, this will cause a "Exception User-Unhandled" when running it in the Visual Studio debugger. - // The certificate is only available inside this function, so we can't catch it at the calling method. - throw new Exception("certificate validation failed: " + certificate.ToString()); - } - - return sslPolicyErrors == SslPolicyErrors.None; - } - } - - public static void InitProxy(ServerConfig serverConfig) - { - // dispose old SocksWebProxy - if (webProxy is SocksWebProxy proxy) - proxy.Dispose(); - webProxy = null; - webProxyUrl = serverConfig.GetProxyUrl(); - if (!string.IsNullOrWhiteSpace(webProxyUrl)) - { - if (serverConfig.ProxyType != ProxyType.Http) - { - var addresses = Dns.GetHostAddressesAsync(serverConfig.ProxyUrl).Result; - var socksConfig = new ProxyConfig - { - SocksAddress = addresses.FirstOrDefault(), - Username = serverConfig.ProxyUsername, - Password = serverConfig.ProxyPassword, - Version = serverConfig.ProxyType == ProxyType.Socks4 ? - ProxyConfig.SocksVersion.Four : - ProxyConfig.SocksVersion.Five - }; - if (serverConfig.ProxyPort.HasValue) - { - socksConfig.SocksPort = serverConfig.ProxyPort.Value; - } - webProxy = new SocksWebProxy(socksConfig, false); - } - else - { - NetworkCredential creds = null; - if (!serverConfig.ProxyIsAnonymous) - { - var username = serverConfig.ProxyUsername; - var password = serverConfig.ProxyPassword; - creds = new NetworkCredential(username, password); - } - webProxy = new WebProxy(webProxyUrl) - { - BypassProxyOnLocal = false, - Credentials = creds - }; - } - } - } - public HttpWebClientNetCore(IProcessService p, Logger l, IConfigurationService c, ServerConfig sc) : base(p: p, l: l, c: c, sc: sc) { - if (webProxyUrl == null) - InitProxy(sc); } - - // Called everytime the ServerConfig changes - public override void OnNext(ServerConfig value) - { - var newProxyUrl = serverConfig.GetProxyUrl(); - if (webProxyUrl != newProxyUrl) // if proxy URL changed - InitProxy(serverConfig); - } - public override void Init() { ServicePointManager.DefaultConnectionLimit = 1000; - if (serverConfig.RuntimeSettings.IgnoreSslErrors == true) - { - logger.Info(string.Format("HttpWebClient: Disabling certificate validation")); - ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return true; }; - } + base.Init(); } protected override async Task Run(WebRequest webRequest) @@ -304,17 +210,5 @@ namespace Jackett.Common.Utils.Clients } } } - - public override void AddTrustedCertificate(string host, string hash) - { - hash = hash.ToUpper(); - trustedCertificates.TryGetValue(hash.ToUpper(), out var hosts); - if (hosts == null) - { - hosts = new HashSet(); - trustedCertificates[hash] = hosts; - } - hosts.Add(host); - } } } diff --git a/src/Jackett.Common/Utils/Clients/WebClient.cs b/src/Jackett.Common/Utils/Clients/WebClient.cs index 602269d25..03f1d127f 100644 --- a/src/Jackett.Common/Utils/Clients/WebClient.cs +++ b/src/Jackett.Common/Utils/Clients/WebClient.cs @@ -1,12 +1,18 @@ using System; using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Net; using System.Net.Http; using System.Net.Http.Headers; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; using System.Text; -using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Web; using AutoMapper; +using com.LandonKey.SocksWebProxy; +using com.LandonKey.SocksWebProxy.Proxy; using Jackett.Common.Models.Config; using Jackett.Common.Services.Interfaces; using NLog; @@ -24,6 +30,82 @@ namespace Jackett.Common.Utils.Clients protected TimeSpan requestDelayTimeSpan; protected string ClientType; public bool EmulateBrowser = true; + + protected static Dictionary> trustedCertificates = new Dictionary>(); + protected static string webProxyUrl; + protected static IWebProxy webProxy; + + + [DebuggerNonUserCode] // avoid "Exception User-Unhandled" Visual Studio messages + public static bool ValidateCertificate(HttpRequestMessage request, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) + { + { + var hash = certificate.GetCertHashString(); + + + trustedCertificates.TryGetValue(hash, out var hosts); + if (hosts != null) + { + if (hosts.Contains(request.RequestUri.Host)) + return true; + } + + if (sslPolicyErrors != SslPolicyErrors.None) + { + // Throw exception with certificate details, this will cause a "Exception User-Unhandled" when running it in the Visual Studio debugger. + // The certificate is only available inside this function, so we can't catch it at the calling method. + throw new Exception("certificate validation failed: " + certificate.ToString()); + } + + return sslPolicyErrors == SslPolicyErrors.None; + } + } + public static void InitProxy(ServerConfig serverConfig) + { + // dispose old SocksWebProxy + if (webProxy is SocksWebProxy proxy) + proxy.Dispose(); + webProxy = null; + webProxyUrl = serverConfig.GetProxyUrl(); + if (!string.IsNullOrWhiteSpace(webProxyUrl)) + { + if (serverConfig.ProxyType != ProxyType.Http) + { + var addresses = Dns.GetHostAddressesAsync(serverConfig.ProxyUrl).Result; + var socksConfig = new ProxyConfig + { + SocksAddress = addresses.FirstOrDefault(), + Username = serverConfig.ProxyUsername, + Password = serverConfig.ProxyPassword, + Version = serverConfig.ProxyType == ProxyType.Socks4 ? + ProxyConfig.SocksVersion.Four : + ProxyConfig.SocksVersion.Five + }; + if (serverConfig.ProxyPort.HasValue) + { + socksConfig.SocksPort = serverConfig.ProxyPort.Value; + } + webProxy = new SocksWebProxy(socksConfig, false); + } + else + { + NetworkCredential creds = null; + if (!serverConfig.ProxyIsAnonymous) + { + var username = serverConfig.ProxyUsername; + var password = serverConfig.ProxyPassword; + creds = new NetworkCredential(username, password); + } + webProxy = new WebProxy(webProxyUrl) + { + BypassProxyOnLocal = false, + Credentials = creds + }; + } + } + } + + public double requestDelay { get => requestDelayTimeSpan.TotalSeconds; @@ -36,7 +118,14 @@ namespace Jackett.Common.Utils.Clients public virtual void AddTrustedCertificate(string host, string hash) { - // not implemented by default + hash = hash.ToUpper(); + trustedCertificates.TryGetValue(hash.ToUpper(), out var hosts); + if (hosts == null) + { + hosts = new HashSet(); + trustedCertificates[hash] = hosts; + } + hosts.Add(host); } public WebClient(IProcessService p, Logger l, IConfigurationService c, ServerConfig sc) @@ -47,6 +136,9 @@ namespace Jackett.Common.Utils.Clients serverConfig = sc; ClientType = GetType().Name; ServerConfigUnsubscriber = serverConfig.Subscribe(this); + + if (webProxyUrl == null) + InitProxy(sc); } protected async Task DelayRequest(WebRequest request) @@ -130,7 +222,15 @@ namespace Jackett.Common.Utils.Clients protected virtual async Task Run(WebRequest webRequest) => throw new NotImplementedException(); #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously - public abstract void Init(); + public virtual void Init() + { + if (serverConfig.RuntimeSettings.IgnoreSslErrors == true) + { + logger.Info($"WebClient({ClientType}): Disabling certificate validation"); + ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return true; }; + } + } + public virtual void OnCompleted() => throw new NotImplementedException(); @@ -138,7 +238,9 @@ namespace Jackett.Common.Utils.Clients public virtual void OnNext(ServerConfig value) { - // nothing by default + var newProxyUrl = serverConfig.GetProxyUrl(); + if (webProxyUrl != newProxyUrl) // if proxy URL changed + InitProxy(serverConfig); } /**