#if !UNITY_WEBGL || UNITY_EDITOR
using System;
using Best.HTTP.Shared;
using Best.HTTP.Hosts.Connections;
using Best.HTTP.Request.Timings;
namespace Best.HTTP.Proxies.Autodetect
{
///
/// Interface for custom proxy-detection logic.
///
public interface IProxyDetector
{
///
/// Receives the instance this detector has to try to find a proxy.
///
/// instance to find a proxy for
/// A concrete implementation, or null if no proxy could be found.
Proxy GetProxy(HTTPRequest request);
}
///
/// Possible detection modes the can be in.
///
public enum ProxyDetectionMode
{
///
/// In Continuous mode the ProxyDetector will check for a proxy for every request.
///
Continuous,
///
/// This mode will cache the first Proxy found and use it for consecutive requests.
///
CacheFirstFound
}
///
/// Helper class to contain, manage and execute logic to detect available proxy on the network. It's a wrapper class to execute the various s.
///
public sealed class ProxyDetector
{
public static IProxyDetector[] GetDefaultDetectors() => new IProxyDetector[] {
// HTTPManager.Proxy has the highest priority
new ProgrammaticallyAddedProxyDetector(),
// then comes the environment set
new EnvironmentProxyDetector(),
// .net framework's detector
new FrameworkProxyDetector(),
#if UNITY_ANDROID && !UNITY_EDITOR
new AndroidProxyDetector(),
#endif
};
private IProxyDetector[] _proxyDetectors;
private ProxyDetectionMode _detectionMode;
private bool _attached;
public ProxyDetector()
: this(ProxyDetectionMode.CacheFirstFound, GetDefaultDetectors())
{ }
public ProxyDetector(ProxyDetectionMode detectionMode)
:this(detectionMode, GetDefaultDetectors())
{ }
public ProxyDetector(ProxyDetectionMode detectionMode, IProxyDetector[] proxyDetectors)
{
this._detectionMode = detectionMode;
this._proxyDetectors = proxyDetectors;
if (this._proxyDetectors != null)
Reattach();
}
public void Reattach()
{
HTTPManager.Logger.Information(nameof(ProxyDetector), $"{nameof(Reattach)}({this._attached})");
if (!this._attached)
{
RequestEventHelper.OnEvent += OnRequestEvent;
this._attached = true;
}
}
///
/// Call Detach() to disable ProxyDetector's logic to find and set a proxy.
///
public void Detach()
{
HTTPManager.Logger.Information(nameof(ProxyDetector), $"{nameof(Detach)}({this._attached})");
if (this._attached)
{
RequestEventHelper.OnEvent -= OnRequestEvent;
this._attached = false;
}
}
private void OnRequestEvent(RequestEventInfo @event)
{
// The Resend event is raised for every request when it's queued up (sent or redirected).
if (@event.Event == RequestEvents.Resend &&
@event.SourceRequest.ProxySettings != null &&
@event.SourceRequest.ProxySettings.Proxy == null)
{
Uri uri = @event.SourceRequest.CurrentUri;
if (uri.Scheme.Equals("file"))
return;
@event.SourceRequest.Timing.StartNext(TimingEventNames.ProxyDetection);
try
{
for (int i = 0; i < this._proxyDetectors.Length; i++)
{
var detector = this._proxyDetectors[i];
if (detector == null)
continue;
if (HTTPManager.Logger.IsDiagnostic)
HTTPManager.Logger.Verbose(nameof(ProxyDetector), $"Calling {detector.GetType().Name}'s GetProxy", @event.SourceRequest.Context);
Proxy proxy = null;
#if ENABLE_PROFILER
using (var _ = new Unity.Profiling.ProfilerMarker($"{detector.GetType().Name}.GetProxy").Auto())
#endif
proxy = detector.GetProxy(@event.SourceRequest);
#if ENABLE_PROFILER
using (var _ = new Unity.Profiling.ProfilerMarker($"{detector.GetType().Name}.UseProxyForAddress").Auto())
#endif
if (proxy != null && proxy.UseProxyForAddress(uri))
{
if (HTTPManager.Logger.IsDiagnostic)
HTTPManager.Logger.Verbose(nameof(ProxyDetector), $"[{detector.GetType().Name}] Proxy found: {proxy.Address} ", @event.SourceRequest.Context);
switch (this._detectionMode)
{
case ProxyDetectionMode.Continuous:
@event.SourceRequest.ProxySettings.Proxy = proxy;
break;
case ProxyDetectionMode.CacheFirstFound:
HTTPManager.Proxy = @event.SourceRequest.ProxySettings.Proxy = proxy;
HTTPManager.Logger.Verbose(nameof(ProxyDetector), $"Proxy cached in HTTPManager.Proxy!", @event.SourceRequest.Context);
Detach();
break;
}
return;
}
}
HTTPManager.Logger.Information(nameof(ProxyDetector), $"No Proxy for '{uri}'.", @event.SourceRequest.Context);
}
catch (Exception ex)
{
if (HTTPManager.Logger.IsDiagnostic)
HTTPManager.Logger.Exception(nameof(ProxyDetector), $"GetProxyFor({@event.SourceRequest.CurrentUri})", ex, @event.SourceRequest.Context);
}
finally
{
@event.SourceRequest.Timing.StartNext(TimingEventNames.Queued);
}
}
}
}
}
#endif