mirror of
https://github.com/Jackett/Jackett.git
synced 2025-09-17 17:34:09 +02:00
allow proxy changes without restart
This commit is contained in:
@@ -9,10 +9,14 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Jackett.Models.Config
|
namespace Jackett.Models.Config
|
||||||
{
|
{
|
||||||
public class ServerConfig
|
public class ServerConfig : IObservable<ServerConfig>
|
||||||
{
|
{
|
||||||
|
[JsonIgnore]
|
||||||
|
protected List<IObserver<ServerConfig>> observers;
|
||||||
|
|
||||||
public ServerConfig(RuntimeSettings runtimeSettings)
|
public ServerConfig(RuntimeSettings runtimeSettings)
|
||||||
{
|
{
|
||||||
|
observers = new List<IObserver<ServerConfig>>();
|
||||||
Port = 9117;
|
Port = 9117;
|
||||||
AllowExternal = System.Environment.OSVersion.Platform == PlatformID.Unix;
|
AllowExternal = System.Environment.OSVersion.Platform == PlatformID.Unix;
|
||||||
RuntimeSettings = runtimeSettings;
|
RuntimeSettings = runtimeSettings;
|
||||||
@@ -109,5 +113,42 @@ namespace Jackett.Models.Config
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IDisposable Subscribe(IObserver<ServerConfig> observer)
|
||||||
|
{
|
||||||
|
if (!observers.Contains(observer))
|
||||||
|
{
|
||||||
|
observers.Add(observer);
|
||||||
|
}
|
||||||
|
return new UnSubscriber(observers, observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class UnSubscriber : IDisposable
|
||||||
|
{
|
||||||
|
private List<IObserver<ServerConfig>> lstObservers;
|
||||||
|
private IObserver<ServerConfig> observer;
|
||||||
|
|
||||||
|
public UnSubscriber(List<IObserver<ServerConfig>> ObserversCollection, IObserver<ServerConfig> observer)
|
||||||
|
{
|
||||||
|
this.lstObservers = ObserversCollection;
|
||||||
|
this.observer = observer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (this.observer != null)
|
||||||
|
{
|
||||||
|
lstObservers.Remove(this.observer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ConfigChanged()
|
||||||
|
{
|
||||||
|
foreach (var obs in observers)
|
||||||
|
{
|
||||||
|
obs.OnNext(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -136,6 +136,7 @@ namespace Jackett.Common.Plumbing
|
|||||||
config.InstanceId = StringUtil.GenerateRandom(64);
|
config.InstanceId = StringUtil.GenerateRandom(64);
|
||||||
configService.SaveConfig(config);
|
configService.SaveConfig(config);
|
||||||
}
|
}
|
||||||
|
config.ConfigChanged();
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -21,32 +21,54 @@ namespace Jackett.Utils.Clients
|
|||||||
public class HttpWebClient : WebClient
|
public class HttpWebClient : WebClient
|
||||||
{
|
{
|
||||||
static protected Dictionary<string, ICollection<string>> trustedCertificates = new Dictionary<string, ICollection<string>>();
|
static protected Dictionary<string, ICollection<string>> trustedCertificates = new Dictionary<string, ICollection<string>>();
|
||||||
static protected SocksWebProxy socksWebProxy;
|
static protected string webProxyUrl;
|
||||||
|
static protected IWebProxy webProxy;
|
||||||
|
|
||||||
static public void InitSocksWebProxy(ServerConfig serverConfig)
|
static public void InitProxy(ServerConfig serverConfig)
|
||||||
{
|
{
|
||||||
if (socksWebProxy != null)
|
// dispose old SocksWebProxy
|
||||||
|
if (webProxy != null && webProxy is SocksWebProxy)
|
||||||
{
|
{
|
||||||
socksWebProxy.Dispose();
|
((SocksWebProxy)webProxy).Dispose();
|
||||||
|
webProxy = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serverConfig.ProxyType != ProxyType.Http)
|
webProxyUrl = serverConfig.GetProxyUrl();
|
||||||
|
if (!string.IsNullOrWhiteSpace(webProxyUrl))
|
||||||
{
|
{
|
||||||
var addresses = Dns.GetHostAddressesAsync(serverConfig.ProxyUrl).Result;
|
if (serverConfig.ProxyType != ProxyType.Http)
|
||||||
var socksConfig = new ProxyConfig
|
|
||||||
{
|
{
|
||||||
SocksAddress = addresses.FirstOrDefault(),
|
var addresses = Dns.GetHostAddressesAsync(serverConfig.ProxyUrl).Result;
|
||||||
Username = serverConfig.ProxyUsername,
|
var socksConfig = new ProxyConfig
|
||||||
Password = serverConfig.ProxyPassword,
|
{
|
||||||
Version = serverConfig.ProxyType == ProxyType.Socks4 ?
|
SocksAddress = addresses.FirstOrDefault(),
|
||||||
ProxyConfig.SocksVersion.Four :
|
Username = serverConfig.ProxyUsername,
|
||||||
ProxyConfig.SocksVersion.Five
|
Password = serverConfig.ProxyPassword,
|
||||||
};
|
Version = serverConfig.ProxyType == ProxyType.Socks4 ?
|
||||||
if (serverConfig.ProxyPort.HasValue)
|
ProxyConfig.SocksVersion.Four :
|
||||||
{
|
ProxyConfig.SocksVersion.Five
|
||||||
socksConfig.SocksPort = serverConfig.ProxyPort.Value;
|
};
|
||||||
|
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
|
||||||
|
};
|
||||||
}
|
}
|
||||||
socksWebProxy = new SocksWebProxy(socksConfig, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,8 +78,16 @@ namespace Jackett.Utils.Clients
|
|||||||
c: c,
|
c: c,
|
||||||
sc: sc)
|
sc: sc)
|
||||||
{
|
{
|
||||||
if (socksWebProxy == null)
|
if (webProxyUrl == null)
|
||||||
InitSocksWebProxy(sc);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
override public void Init()
|
override public void Init()
|
||||||
@@ -112,42 +142,16 @@ namespace Jackett.Utils.Clients
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var useProxy = false;
|
|
||||||
|
|
||||||
using (ClearanceHandler clearanceHandlr = new ClearanceHandler())
|
using (ClearanceHandler clearanceHandlr = new ClearanceHandler())
|
||||||
{
|
{
|
||||||
IWebProxy proxyServer = null;
|
|
||||||
var proxyUrl = serverConfig.GetProxyUrl();
|
|
||||||
if (!string.IsNullOrWhiteSpace(proxyUrl))
|
|
||||||
{
|
|
||||||
useProxy = true;
|
|
||||||
if (serverConfig.ProxyType != ProxyType.Http)
|
|
||||||
{
|
|
||||||
proxyServer = socksWebProxy;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NetworkCredential creds = null;
|
|
||||||
if (!serverConfig.ProxyIsAnonymous)
|
|
||||||
{
|
|
||||||
var username = serverConfig.ProxyUsername;
|
|
||||||
var password = serverConfig.ProxyPassword;
|
|
||||||
creds = new NetworkCredential(username, password);
|
|
||||||
}
|
|
||||||
proxyServer = new WebProxy(proxyUrl)
|
|
||||||
{
|
|
||||||
BypassProxyOnLocal = false,
|
|
||||||
Credentials = creds
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
using (HttpClientHandler clientHandlr = new HttpClientHandler
|
using (HttpClientHandler clientHandlr = new HttpClientHandler
|
||||||
{
|
{
|
||||||
CookieContainer = cookies,
|
CookieContainer = cookies,
|
||||||
AllowAutoRedirect = false, // Do not use this - Bugs ahoy! Lost cookies and more.
|
AllowAutoRedirect = false, // Do not use this - Bugs ahoy! Lost cookies and more.
|
||||||
UseCookies = true,
|
UseCookies = true,
|
||||||
Proxy = proxyServer,
|
Proxy = webProxy,
|
||||||
UseProxy = useProxy,
|
UseProxy = (webProxy != null),
|
||||||
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
|
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
@@ -33,54 +33,38 @@ namespace Jackett.Utils.Clients
|
|||||||
HttpClient client;
|
HttpClient client;
|
||||||
|
|
||||||
static protected Dictionary<string, ICollection<string>> trustedCertificates = new Dictionary<string, ICollection<string>>();
|
static protected Dictionary<string, ICollection<string>> trustedCertificates = new Dictionary<string, ICollection<string>>();
|
||||||
static protected SocksWebProxy socksWebProxy;
|
static protected string webProxyUrl;
|
||||||
|
static protected IWebProxy webProxy;
|
||||||
|
|
||||||
static public void InitSocksWebProxy(ServerConfig serverConfig)
|
static public void InitProxy(ServerConfig serverConfig)
|
||||||
{
|
{
|
||||||
if (socksWebProxy != null)
|
// dispose old SocksWebProxy
|
||||||
|
if (webProxy != null && webProxy is SocksWebProxy)
|
||||||
{
|
{
|
||||||
socksWebProxy.Dispose();
|
((SocksWebProxy)webProxy).Dispose();
|
||||||
|
webProxy = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serverConfig.ProxyType != ProxyType.Http)
|
webProxyUrl = serverConfig.GetProxyUrl();
|
||||||
|
if (!string.IsNullOrWhiteSpace(webProxyUrl))
|
||||||
{
|
{
|
||||||
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;
|
|
||||||
}
|
|
||||||
socksWebProxy = new SocksWebProxy(socksConfig, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpWebClient2(IProcessService p, Logger l, IConfigurationService c, ServerConfig sc)
|
|
||||||
: base(p: p,
|
|
||||||
l: l,
|
|
||||||
c: c,
|
|
||||||
sc: sc)
|
|
||||||
{
|
|
||||||
if (socksWebProxy == null)
|
|
||||||
InitSocksWebProxy(sc);
|
|
||||||
|
|
||||||
cookies = new CookieContainer();
|
|
||||||
var useProxy = false;
|
|
||||||
IWebProxy proxyServer = null;
|
|
||||||
var proxyUrl = serverConfig.GetProxyUrl();
|
|
||||||
if (!string.IsNullOrWhiteSpace(proxyUrl))
|
|
||||||
{
|
|
||||||
useProxy = true;
|
|
||||||
if (serverConfig.ProxyType != ProxyType.Http)
|
if (serverConfig.ProxyType != ProxyType.Http)
|
||||||
{
|
{
|
||||||
proxyServer = socksWebProxy;
|
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
|
else
|
||||||
{
|
{
|
||||||
@@ -91,22 +75,38 @@ namespace Jackett.Utils.Clients
|
|||||||
var password = serverConfig.ProxyPassword;
|
var password = serverConfig.ProxyPassword;
|
||||||
creds = new NetworkCredential(username, password);
|
creds = new NetworkCredential(username, password);
|
||||||
}
|
}
|
||||||
proxyServer = new WebProxy(proxyUrl)
|
webProxy = new WebProxy(webProxyUrl)
|
||||||
{
|
{
|
||||||
BypassProxyOnLocal = false,
|
BypassProxyOnLocal = false,
|
||||||
Credentials = creds
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateClient()
|
||||||
|
{
|
||||||
clearanceHandlr = new ClearanceHandler();
|
clearanceHandlr = new ClearanceHandler();
|
||||||
clientHandlr = new HttpClientHandler
|
clientHandlr = new HttpClientHandler
|
||||||
{
|
{
|
||||||
CookieContainer = cookies,
|
CookieContainer = cookies,
|
||||||
AllowAutoRedirect = false, // Do not use this - Bugs ahoy! Lost cookies and more.
|
AllowAutoRedirect = false, // Do not use this - Bugs ahoy! Lost cookies and more.
|
||||||
UseCookies = true,
|
UseCookies = true,
|
||||||
Proxy = proxyServer,
|
Proxy = webProxy,
|
||||||
UseProxy = useProxy,
|
UseProxy = (webProxy != null),
|
||||||
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
|
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,6 +114,20 @@ namespace Jackett.Utils.Clients
|
|||||||
client = new HttpClient(clearanceHandlr);
|
client = new HttpClient(clearanceHandlr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called everytime the ServerConfig changes
|
||||||
|
public override void OnNext(ServerConfig value)
|
||||||
|
{
|
||||||
|
var newProxyUrl = serverConfig.GetProxyUrl();
|
||||||
|
if (webProxyUrl != newProxyUrl) // if proxy URL changed
|
||||||
|
InitProxy(serverConfig);
|
||||||
|
|
||||||
|
// recreate client if needed (can't just change the proxy attribute)
|
||||||
|
if (!ReferenceEquals(clientHandlr.Proxy, webProxy))
|
||||||
|
{
|
||||||
|
CreateClient();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override public void Init()
|
override public void Init()
|
||||||
{
|
{
|
||||||
if (serverConfig.RuntimeSettings.IgnoreSslErrors == true)
|
if (serverConfig.RuntimeSettings.IgnoreSslErrors == true)
|
||||||
|
@@ -13,8 +13,9 @@ using Jackett.Models.Config;
|
|||||||
|
|
||||||
namespace Jackett.Utils.Clients
|
namespace Jackett.Utils.Clients
|
||||||
{
|
{
|
||||||
public abstract class WebClient
|
public abstract class WebClient : IObserver<ServerConfig>
|
||||||
{
|
{
|
||||||
|
protected IDisposable ServerConfigUnsubscriber;
|
||||||
protected Logger logger;
|
protected Logger logger;
|
||||||
protected IConfigurationService configService;
|
protected IConfigurationService configService;
|
||||||
protected readonly ServerConfig serverConfig;
|
protected readonly ServerConfig serverConfig;
|
||||||
@@ -32,6 +33,10 @@ namespace Jackett.Utils.Clients
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual protected void OnConfigChange()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual public void AddTrustedCertificate(string host, string hash)
|
virtual public void AddTrustedCertificate(string host, string hash)
|
||||||
{
|
{
|
||||||
// not implemented by default
|
// not implemented by default
|
||||||
@@ -44,6 +49,7 @@ namespace Jackett.Utils.Clients
|
|||||||
configService = c;
|
configService = c;
|
||||||
serverConfig = sc;
|
serverConfig = sc;
|
||||||
ClientType = GetType().Name;
|
ClientType = GetType().Name;
|
||||||
|
ServerConfigUnsubscriber = serverConfig.Subscribe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
async protected Task DelayRequest(WebRequest request)
|
async protected Task DelayRequest(WebRequest request)
|
||||||
@@ -165,5 +171,20 @@ namespace Jackett.Utils.Clients
|
|||||||
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||||
|
|
||||||
abstract public void Init();
|
abstract public void Init();
|
||||||
|
|
||||||
|
public virtual void OnCompleted()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnError(Exception error)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnNext(ServerConfig value)
|
||||||
|
{
|
||||||
|
// nothing by default
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -187,6 +187,8 @@ namespace Jackett.Controllers.V20
|
|||||||
serverConfig.BlackholeDir = saveDir;
|
serverConfig.BlackholeDir = saveDir;
|
||||||
configService.SaveConfig(serverConfig);
|
configService.SaveConfig(serverConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serverConfig.ConfigChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
@@ -195,6 +197,6 @@ namespace Jackett.Controllers.V20
|
|||||||
return logCache.Logs;
|
return logCache.Logs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user