diff --git a/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs b/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs index 84b1e856d..3070037da 100644 --- a/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs +++ b/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs @@ -106,7 +106,7 @@ public bool EnableWinAuth /// /// Are we using a custom upstream HTTP(S) proxy? /// - public ExternalProxy? CustomUpStreamProxyUsed { get; internal set; } + public IExternalProxy? CustomUpStreamProxyUsed { get; internal set; } /// /// Local endpoint via which we make the request. diff --git a/src/Titanium.Web.Proxy/Helpers/WinHttp/WinHttpWebProxyFinder.cs b/src/Titanium.Web.Proxy/Helpers/WinHttp/WinHttpWebProxyFinder.cs index 9ccbf31d9..8b8ec3295 100644 --- a/src/Titanium.Web.Proxy/Helpers/WinHttp/WinHttpWebProxyFinder.cs +++ b/src/Titanium.Web.Proxy/Helpers/WinHttp/WinHttpWebProxyFinder.cs @@ -95,7 +95,7 @@ public bool GetAutoProxies(Uri destination, out IList? proxyList) return true; } - public ExternalProxy? GetProxy(Uri destination) + public IExternalProxy? GetProxy(Uri destination) { if (GetAutoProxies(destination, out var proxies)) { diff --git a/src/Titanium.Web.Proxy/Models/ExternalProxy.cs b/src/Titanium.Web.Proxy/Models/ExternalProxy.cs index 4c1deca60..931248233 100644 --- a/src/Titanium.Web.Proxy/Models/ExternalProxy.cs +++ b/src/Titanium.Web.Proxy/Models/ExternalProxy.cs @@ -6,7 +6,7 @@ namespace Titanium.Web.Proxy.Models /// /// An upstream proxy this proxy uses if any. /// - public class ExternalProxy + public class ExternalProxy : IExternalProxy { private static readonly Lazy defaultCredentials = new Lazy(() => CredentialCache.DefaultNetworkCredentials); diff --git a/src/Titanium.Web.Proxy/Models/IExternalProxy.cs b/src/Titanium.Web.Proxy/Models/IExternalProxy.cs new file mode 100644 index 000000000..7eb877859 --- /dev/null +++ b/src/Titanium.Web.Proxy/Models/IExternalProxy.cs @@ -0,0 +1,37 @@ +namespace Titanium.Web.Proxy.Models +{ + public interface IExternalProxy + { + /// + /// Use default windows credentials? + /// + bool UseDefaultCredentials { get; set; } + + /// + /// Bypass this proxy for connections to localhost? + /// + bool BypassLocalhost { get; set; } + + /// + /// Username. + /// + string? UserName { get; set; } + + /// + /// Password. + /// + string? Password { get; set; } + + /// + /// Host name. + /// + string HostName { get; set; } + + /// + /// Port. + /// + int Port { get; set; } + + string ToString(); + } +} diff --git a/src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs b/src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs index ac11521b1..56feb818f 100644 --- a/src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs +++ b/src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs @@ -49,7 +49,7 @@ internal TcpConnectionFactory(ProxyServer server) internal string GetConnectionCacheKey(string remoteHostName, int remotePort, bool isHttps, List? applicationProtocols, - IPEndPoint? upStreamEndPoint, ExternalProxy? externalProxy) + IPEndPoint? upStreamEndPoint, IExternalProxy? externalProxy) { // http version is ignored since its an application level decision b/w HTTP 1.0/1.1 // also when doing connect request MS Edge browser sends http 1.0 but uses 1.1 after server sends 1.1 its response. @@ -115,7 +115,7 @@ internal async Task GetConnectionCacheKey(ProxyServer server, SessionEve applicationProtocols = new List { applicationProtocol }; } - ExternalProxy? customUpStreamProxy = null; + IExternalProxy? customUpStreamProxy = null; bool isHttps = session.IsHttps; if (server.GetCustomUpStreamProxyFunc != null) @@ -170,7 +170,7 @@ internal Task GetServerConnection(ProxyServer server, Sessi internal async Task GetServerConnection(ProxyServer server, SessionEventArgsBase session, bool isConnect, List? applicationProtocols, bool noCache, CancellationToken cancellationToken) { - ExternalProxy? customUpStreamProxy = null; + IExternalProxy? customUpStreamProxy = null; bool isHttps = session.IsHttps; if (server.GetCustomUpStreamProxyFunc != null) @@ -208,7 +208,7 @@ internal async Task GetServerConnection(ProxyServer server, /// internal async Task GetServerConnection(string remoteHostName, int remotePort, Version httpVersion, bool isHttps, List? applicationProtocols, bool isConnect, - ProxyServer proxyServer, SessionEventArgsBase? session, IPEndPoint? upStreamEndPoint, ExternalProxy? externalProxy, + ProxyServer proxyServer, SessionEventArgsBase? session, IPEndPoint? upStreamEndPoint, IExternalProxy? externalProxy, bool noCache, CancellationToken cancellationToken) { var sslProtocol = session?.ProxyClient.Connection.SslProtocol ?? SslProtocols.None; @@ -262,7 +262,7 @@ internal async Task GetServerConnection(string remoteHostNa /// private async Task createServerConnection(string remoteHostName, int remotePort, Version httpVersion, bool isHttps, SslProtocols sslProtocol, List? applicationProtocols, bool isConnect, - ProxyServer proxyServer, SessionEventArgsBase? session, IPEndPoint? upStreamEndPoint, ExternalProxy? externalProxy, string cacheKey, + ProxyServer proxyServer, SessionEventArgsBase? session, IPEndPoint? upStreamEndPoint, IExternalProxy? externalProxy, string cacheKey, CancellationToken cancellationToken) { // deny connection to proxy end points to avoid infinite connection loop. @@ -304,7 +304,7 @@ private async Task createServerConnection(string remoteHost bool retry = true; var enabledSslProtocols = sslProtocol; - retry: +retry: try { string hostname = useUpstreamProxy ? externalProxy!.HostName : remoteHostName; diff --git a/src/Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs b/src/Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs index ef40391bb..1aea09b55 100644 --- a/src/Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs +++ b/src/Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs @@ -17,7 +17,7 @@ internal class TcpServerConnection : IDisposable { internal TcpServerConnection(ProxyServer proxyServer, TcpClient tcpClient, CustomBufferedStream stream, string hostName, int port, bool isHttps, SslApplicationProtocol negotiatedApplicationProtocol, - Version version, bool useUpstreamProxy, ExternalProxy? upStreamProxy, IPEndPoint? upStreamEndPoint, string cacheKey) + Version version, bool useUpstreamProxy, IExternalProxy? upStreamProxy, IPEndPoint? upStreamEndPoint, string cacheKey) { this.tcpClient = tcpClient; LastAccess = DateTime.Now; @@ -41,7 +41,7 @@ internal TcpServerConnection(ProxyServer proxyServer, TcpClient tcpClient, Custo internal bool IsClosed => Stream.IsClosed; - internal ExternalProxy? UpStreamProxy { get; set; } + internal IExternalProxy? UpStreamProxy { get; set; } internal string HostName { get; set; } diff --git a/src/Titanium.Web.Proxy/ProxyServer.cs b/src/Titanium.Web.Proxy/ProxyServer.cs index 31e3ff34f..b6017f76a 100644 --- a/src/Titanium.Web.Proxy/ProxyServer.cs +++ b/src/Titanium.Web.Proxy/ProxyServer.cs @@ -61,7 +61,7 @@ public partial class ProxyServer : IDisposable /// private WinHttpWebProxyFinder? systemProxyResolver; - + /// /// /// Initializes a new instance of ProxyServer class with provided parameters. @@ -145,7 +145,7 @@ public ProxyServer(string? rootCertificateName, string? rootCertificateIssuerNam /// Defaults to false. /// public bool EnableWinAuth { get; set; } - + /// /// Enable disable HTTP/2 support. /// Warning: HTTP/2 support is very limited @@ -253,12 +253,12 @@ public ProxyServer(string? rootCertificateName, string? rootCertificateIssuerNam /// /// External proxy used for Http requests. /// - public ExternalProxy? UpStreamHttpProxy { get; set; } + public IExternalProxy? UpStreamHttpProxy { get; set; } /// /// External proxy used for Https requests. /// - public ExternalProxy? UpStreamHttpsProxy { get; set; } + public IExternalProxy? UpStreamHttpsProxy { get; set; } /// /// Local adapter/NIC endpoint where proxy makes request via. @@ -275,7 +275,7 @@ public ProxyServer(string? rootCertificateName, string? rootCertificateIssuerNam /// A callback to provide authentication credentials for up stream proxy this proxy is using for HTTP(S) requests. /// User should return the ExternalProxy object with valid credentials. /// - public Func>? GetCustomUpStreamProxyFunc { get; set; } + public Func>? GetCustomUpStreamProxyFunc { get; set; } /// /// Callback for error events in this proxy instance. @@ -709,7 +709,7 @@ private void validateEndPointAsSystemProxy(ExplicitProxyEndPoint endPoint) /// /// The session. /// The external proxy as task result. - private Task getSystemUpStreamProxy(SessionEventArgsBase sessionEventArgs) + private Task getSystemUpStreamProxy(SessionEventArgsBase sessionEventArgs) { var proxy = systemProxyResolver!.GetProxy(sessionEventArgs.HttpClient.Request.RequestUri); return Task.FromResult(proxy); diff --git a/tests/Titanium.Web.Proxy.IntegrationTests/NestedProxyTests.cs b/tests/Titanium.Web.Proxy.IntegrationTests/NestedProxyTests.cs index 7980c6012..2ed0d10e9 100644 --- a/tests/Titanium.Web.Proxy.IntegrationTests/NestedProxyTests.cs +++ b/tests/Titanium.Web.Proxy.IntegrationTests/NestedProxyTests.cs @@ -69,7 +69,7 @@ public async Task Smoke_Test_Nested_Proxy_UserData() }; var client = testSuite.GetClient(proxy1, true); - + var response = await client.PostAsync(new Uri(server.ListeningHttpsUrl), new StringContent("hello server. I am a client."));