Skip to content
This repository was archived by the owner on Jul 9, 2023. It is now read-only.

Commit 69aa126

Browse files
committed
Adds ability to handle upstream proxy connect failures
Adds ability to handle upstream proxy connect failures by using a new upstream proxy.
1 parent 0366b34 commit 69aa126

File tree

3 files changed

+32
-0
lines changed

3 files changed

+32
-0
lines changed

examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ public ProxyTestController()
4242
proxyServer.ForwardToUpstreamGateway = true;
4343
proxyServer.CertificateManager.SaveFakeCertificates = true;
4444

45+
// this is just to show the functionality, provided implementations use junk value
46+
//proxyServer.GetCustomUpStreamProxyFunc = onGetCustomUpStreamProxyFunc;
47+
//proxyServer.CustomUpStreamProxyFailureFunc = onCustomUpStreamProxyFailureFunc;
48+
4549
// optionally set the Certificate Engine
4650
// Under Mono or Non-Windows runtimes only BouncyCastle will be supported
4751
//proxyServer.CertificateManager.CertificateEngine = Network.CertificateEngine.BouncyCastle;
@@ -116,6 +120,18 @@ public void Stop()
116120
//proxyServer.CertificateManager.RemoveTrustedRootCertificates();
117121
}
118122

123+
private async Task<IExternalProxy> onGetCustomUpStreamProxyFunc(SessionEventArgsBase arg)
124+
{
125+
// this is just to show the functionality, provided values are junk
126+
return new ExternalProxy() { BypassLocalhost = false, HostName = "127.0.0.9", Port = 9090, Password = "fake", UserName = "fake", UseDefaultCredentials = false };
127+
}
128+
129+
private async Task<IExternalProxy> onCustomUpStreamProxyFailureFunc(SessionEventArgsBase arg)
130+
{
131+
// this is just to show the functionality, provided values are junk
132+
return new ExternalProxy() { BypassLocalhost = false, HostName = "127.0.0.10", Port = 9191, Password = "fake2", UserName = "fake2", UseDefaultCredentials = false };
133+
}
134+
119135
private async Task onBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
120136
{
121137
string hostname = e.HttpClient.Request.RequestUri.Host;

src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,16 @@ private async Task<TcpServerConnection> createServerConnection(string remoteHost
397397

398398
if (tcpClient == null)
399399
{
400+
if (session != null && proxyServer.CustomUpStreamProxyFailureFunc != null)
401+
{
402+
var newUpstreamProxy = await proxyServer.CustomUpStreamProxyFailureFunc(session);
403+
if (newUpstreamProxy != null)
404+
{
405+
session.CustomUpStreamProxyUsed = newUpstreamProxy;
406+
session.TimeLine["Retrying Upstream Proxy Connection"] = DateTime.Now;
407+
return await createServerConnection(remoteHostName, remotePort, httpVersion, isHttps, sslProtocol, applicationProtocols, isConnect, proxyServer, session, upStreamEndPoint, externalProxy, cacheKey, cancellationToken);
408+
}
409+
}
400410
throw new Exception($"Could not establish connection to {hostname}", lastException);
401411
}
402412

src/Titanium.Web.Proxy/ProxyServer.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,12 @@ public ProxyServer(string? rootCertificateName, string? rootCertificateIssuerNam
283283
/// </summary>
284284
public Func<SessionEventArgsBase, Task<IExternalProxy?>>? GetCustomUpStreamProxyFunc { get; set; }
285285

286+
/// <summary>
287+
/// A callback to provide a chance for an upstream proxy failure to be handled by a new upstream proxy.
288+
/// User should return the ExternalProxy object with valid credentials or null.
289+
/// </summary>
290+
public Func<SessionEventArgsBase, Task<IExternalProxy?>>? CustomUpStreamProxyFailureFunc { get; set; }
291+
286292
/// <summary>
287293
/// Callback for error events in this proxy instance.
288294
/// </summary>

0 commit comments

Comments
 (0)