Commit 27ccf183 authored by justcoding121's avatar justcoding121

#543 Fix reverse proxy. add tests.

parent 8db82807
...@@ -34,10 +34,6 @@ namespace Titanium.Web.Proxy ...@@ -34,10 +34,6 @@ namespace Titanium.Web.Proxy
var clientStream = new CustomBufferedStream(clientConnection.GetStream(), BufferPool, BufferSize); var clientStream = new CustomBufferedStream(clientConnection.GetStream(), BufferPool, BufferSize);
var clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize); var clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize);
Task<TcpServerConnection> prefetchConnectionTask = null;
bool closeServerConnection = false;
bool calledRequestHandler = false;
try try
{ {
var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken); var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken);
...@@ -63,15 +59,6 @@ namespace Titanium.Web.Proxy ...@@ -63,15 +59,6 @@ namespace Titanium.Web.Proxy
if (endPoint.DecryptSsl && args.DecryptSsl) if (endPoint.DecryptSsl && args.DecryptSsl)
{ {
if(EnableTcpServerConnectionPrefetch)
{
//don't pass cancellation token here
//it could cause floating server connections when client exits
prefetchConnectionTask = tcpConnectionFactory.GetServerConnection(httpsHostName, endPoint.Port,
httpVersion: null, isHttps: true, applicationProtocols: null, isConnect: false,
proxyServer: this, session: null, upStreamEndPoint: UpStreamEndPoint, externalProxy: UpStreamHttpsProxy,
noCache: false, cancellationToken: CancellationToken.None);
}
SslStream sslStream = null; SslStream sslStream = null;
...@@ -140,39 +127,29 @@ namespace Titanium.Web.Proxy ...@@ -140,39 +127,29 @@ namespace Titanium.Web.Proxy
return; return;
} }
} }
calledRequestHandler = true;
// HTTPS server created - we can now decrypt the client's traffic // HTTPS server created - we can now decrypt the client's traffic
// Now create the request // Now create the request
await handleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter, await handleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter,
cancellationTokenSource, isHttps ? httpsHostName : null, null, prefetchConnectionTask); cancellationTokenSource, isHttps ? httpsHostName : null, null, null);
} }
catch (ProxyException e) catch (ProxyException e)
{ {
closeServerConnection = true;
onException(clientStream, e); onException(clientStream, e);
} }
catch (IOException e) catch (IOException e)
{ {
closeServerConnection = true;
onException(clientStream, new Exception("Connection was aborted", e)); onException(clientStream, new Exception("Connection was aborted", e));
} }
catch (SocketException e) catch (SocketException e)
{ {
closeServerConnection = true;
onException(clientStream, new Exception("Could not connect", e)); onException(clientStream, new Exception("Could not connect", e));
} }
catch (Exception e) catch (Exception e)
{ {
closeServerConnection = true;
onException(clientStream, new Exception("Error occured in whilst handling the client", e)); onException(clientStream, new Exception("Error occured in whilst handling the client", e));
} }
finally finally
{ {
if (!calledRequestHandler)
{
await tcpConnectionFactory.Release(prefetchConnectionTask, closeServerConnection);
}
clientStream.Dispose(); clientStream.Dispose();
if (!cancellationTokenSource.IsCancellationRequested) if (!cancellationTokenSource.IsCancellationRequested)
......
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
namespace Titanium.Web.Proxy.IntegrationTests namespace Titanium.Web.Proxy.IntegrationTests.Helpers
{ {
public static class TestHelper public static class TestHelper
{ {
public static HttpClient CreateHttpClient(int localProxyPort) public static HttpClient GetHttpClient(int localProxyPort)
{ {
var proxy = new TestProxy($"http://localhost:{localProxyPort}"); var proxy = new TestProxy($"http://localhost:{localProxyPort}");
...@@ -19,6 +19,11 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -19,6 +19,11 @@ namespace Titanium.Web.Proxy.IntegrationTests
return new HttpClient(handler); return new HttpClient(handler);
} }
public static HttpClient GetHttpClient()
{
return new HttpClient(new HttpClientHandler());
}
public class TestProxy : IWebProxy public class TestProxy : IWebProxy
{ {
public Uri ProxyUri { get; set; } public Uri ProxyUri { get; set; }
......
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Titanium.Web.Proxy.IntegrationTests
{
[TestClass]
public class HttpsTests
{
[TestMethod]
public async Task Can_Handle_Https_Request()
{
var testSuite = new TestSuite();
var server = testSuite.GetServer();
server.HandleRequest((context) =>
{
return context.Response.WriteAsync("I am server. I received your greetings.");
});
var proxy = testSuite.GetProxy();
var client = testSuite.GetClient(proxy);
var response = await client.PostAsync(new Uri(server.ListeningHttpsUrl),
new StringContent("hello server. I am a client."));
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadAsStringAsync();
Assert.AreEqual("I am server. I received your greetings.", body);
}
}
}
using System; using System;
using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
namespace Titanium.Web.Proxy.IntegrationTests namespace Titanium.Web.Proxy.IntegrationTests
{ {
...@@ -19,123 +11,177 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -19,123 +11,177 @@ namespace Titanium.Web.Proxy.IntegrationTests
public class InterceptionTests public class InterceptionTests
{ {
[TestMethod] [TestMethod]
public async Task Can_Intercept_Post_Requests() public async Task Can_Intercept_Get_Requests()
{ {
string testHost = "localhost"; var testSuite = new TestSuite();
using (var proxy = new ProxyTestController()) var server = testSuite.GetServer();
server.HandleRequest((context) =>
{ {
var serverCertificate = await proxy.CertificateManager.CreateServerCertificate(testHost); return context.Response.WriteAsync("I am server. I received your greetings.");
});
using (var server = new Server(serverCertificate)) var proxy = testSuite.GetProxy();
proxy.BeforeRequest += async (sender, e) =>
{ {
var testUrl = $"http://{testHost}:{server.HttpListeningPort}"; if (e.HttpClient.Request.Url.Contains("localhost"))
using (var client = TestHelper.CreateHttpClient(proxy.ListeningPort))
{ {
var response = await client.PostAsync(new Uri(testUrl), new StringContent("hello!")); e.Ok("<html><body>TitaniumWebProxy-Stopped!!</body></html>");
return;
}
await Task.FromResult(0);
};
var client = testSuite.GetClient(proxy);
var response = await client.GetAsync(new Uri(server.ListeningHttpUrl));
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadAsStringAsync(); var body = await response.Content.ReadAsStringAsync();
Assert.IsTrue(body.Contains("TitaniumWebProxy-Stopped!!")); Assert.IsTrue(body.Contains("TitaniumWebProxy-Stopped!!"));
}
}
}
} }
private class ProxyTestController : IDisposable [TestMethod]
public async Task Can_Intercept_Post_Requests()
{ {
private readonly ProxyServer proxyServer; var testSuite = new TestSuite();
public int ListeningPort => proxyServer.ProxyEndPoints[0].Port;
public CertificateManager CertificateManager => proxyServer.CertificateManager;
public ProxyTestController() var server = testSuite.GetServer();
server.HandleRequest((context) =>
{ {
proxyServer = new ProxyServer(); return context.Response.WriteAsync("I am server. I received your greetings.");
var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 0, true); });
proxyServer.AddEndPoint(explicitEndPoint);
proxyServer.BeforeRequest += OnRequest;
proxyServer.Start();
}
public async Task OnRequest(object sender, SessionEventArgs e) var proxy = testSuite.GetProxy();
proxy.BeforeRequest += async (sender, e) =>
{ {
if (e.HttpClient.Request.Url.Contains("localhost")) if (e.HttpClient.Request.Url.Contains("localhost"))
{ {
if (e.HttpClient.Request.HasBody)
{
var body = await e.GetRequestBodyAsString();
}
e.Ok("<html><body>TitaniumWebProxy-Stopped!!</body></html>"); e.Ok("<html><body>TitaniumWebProxy-Stopped!!</body></html>");
return; return;
} }
await Task.FromResult(0); await Task.FromResult(0);
};
var client = testSuite.GetClient(proxy);
var response = await client.PostAsync(new Uri(server.ListeningHttpUrl),
new StringContent("hello server. I am a client."));
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadAsStringAsync();
Assert.IsTrue(body.Contains("TitaniumWebProxy-Stopped!!"));
} }
public void Dispose() [TestMethod]
public async Task Can_Intercept_Put_Requests()
{ {
proxyServer.BeforeRequest -= OnRequest; var testSuite = new TestSuite();
proxyServer.Stop();
proxyServer.Dispose(); var server = testSuite.GetServer();
server.HandleRequest((context) =>
{
return context.Response.WriteAsync("I am server. I received your greetings.");
});
var proxy = testSuite.GetProxy();
proxy.BeforeRequest += async (sender, e) =>
{
if (e.HttpClient.Request.Url.Contains("localhost"))
{
e.Ok("<html><body>TitaniumWebProxy-Stopped!!</body></html>");
return;
} }
await Task.FromResult(0);
};
var client = testSuite.GetClient(proxy);
var response = await client.PutAsync(new Uri(server.ListeningHttpUrl),
new StringContent("hello server. I am a client."));
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadAsStringAsync();
Assert.IsTrue(body.Contains("TitaniumWebProxy-Stopped!!"));
} }
private class Server : IDisposable
[TestMethod]
public async Task Can_Intercept_Patch_Requests()
{ {
public int HttpListeningPort; var testSuite = new TestSuite();
public int HttpsListeningPort;
private IWebHost host; var server = testSuite.GetServer();
public Server(X509Certificate2 serverCertificate) server.HandleRequest((context) =>
{ {
host = new WebHostBuilder() return context.Response.WriteAsync("I am server. I received your greetings.");
.UseKestrel(options => });
var proxy = testSuite.GetProxy();
proxy.BeforeRequest += async (sender, e) =>
{ {
options.Listen(IPAddress.Loopback, 0); if (e.HttpClient.Request.Url.Contains("localhost"))
options.Listen(IPAddress.Loopback, 0, listenOptions =>
{ {
listenOptions.UseHttps(serverCertificate); e.Ok("<html><body>TitaniumWebProxy-Stopped!!</body></html>");
}); return;
}) }
.UseStartup<Startup>()
.Build();
host.Start(); await Task.FromResult(0);
};
string httpAddress = host.ServerFeatures var client = testSuite.GetClient(proxy);
.Get<IServerAddressesFeature>()
.Addresses
.First();
string httpsAddress = host.ServerFeatures var response = await client.PatchAsync(new Uri(server.ListeningHttpUrl),
.Get<IServerAddressesFeature>() new StringContent("hello server. I am a client."));
.Addresses
.Skip(1)
.First();
HttpListeningPort = int.Parse(httpAddress.Split(':')[2]); Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
HttpsListeningPort = int.Parse(httpsAddress.Split(':')[2]);
} var body = await response.Content.ReadAsStringAsync();
Assert.IsTrue(body.Contains("TitaniumWebProxy-Stopped!!"));
public void Dispose()
{
host.Dispose();
} }
private class Startup [TestMethod]
{ public async Task Can_Intercept_Delete_Requests()
public void Configure(IApplicationBuilder app)
{ {
app.Run(context => var testSuite = new TestSuite();
var server = testSuite.GetServer();
server.HandleRequest((context) =>
{ {
return context.Response.WriteAsync("Server received you request."); return context.Response.WriteAsync("I am server. I received your greetings.");
}); });
} var proxy = testSuite.GetProxy();
} proxy.BeforeRequest += async (sender, e) =>
{
if (e.HttpClient.Request.Url.Contains("localhost"))
{
e.Ok("<html><body>TitaniumWebProxy-Stopped!!</body></html>");
return;
} }
await Task.FromResult(0);
};
var client = testSuite.GetClient(proxy);
var response = await client.DeleteAsync(new Uri(server.ListeningHttpUrl));
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadAsStringAsync();
Assert.IsTrue(body.Contains("TitaniumWebProxy-Stopped!!"));
}
} }
} }
\ No newline at end of file
using Microsoft.AspNetCore.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.IntegrationTests
{
[TestClass]
public class NestedProxyTests
{
[TestMethod]
public async Task Smoke_Test_Nested_Proxy()
{
var testSuite = new TestSuite();
var server = testSuite.GetServer();
server.HandleRequest((context) =>
{
return context.Response.WriteAsync("I am server. I received your greetings.");
});
var proxy1 = testSuite.GetProxy();
var proxy2 = testSuite.GetProxy(proxy1);
var client = testSuite.GetClient(proxy2);
var response = await client.PostAsync(new Uri(server.ListeningHttpsUrl),
new StringContent("hello server. I am a client."));
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadAsStringAsync();
Assert.AreEqual("I am server. I received your greetings.", body);
}
}
}
using Microsoft.AspNetCore.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.IntegrationTests
{
[TestClass]
public class ReverseProxyTests
{
[TestMethod]
public async Task Smoke_Test_Http_To_Http_Reverse_Proxy()
{
var testSuite = new TestSuite();
var server = testSuite.GetServer();
server.HandleRequest((context) =>
{
return context.Response.WriteAsync("I am server. I received your greetings.");
});
var proxy = testSuite.GetReverseProxy();
proxy.BeforeRequest += async (sender, e) =>
{
e.HttpClient.Request.RequestUri = new Uri(server.ListeningHttpUrl);
await Task.FromResult(0);
};
var client = testSuite.GetReverseProxyClient();
var response = await client.PostAsync(new Uri($"http://localhost:{proxy.ProxyEndPoints[0].Port}"),
new StringContent("hello server. I am a client."));
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadAsStringAsync();
Assert.AreEqual("I am server. I received your greetings.", body);
}
[TestMethod]
public async Task Smoke_Test_Https_To_Http_Reverse_Proxy()
{
var testSuite = new TestSuite();
var server = testSuite.GetServer();
server.HandleRequest((context) =>
{
return context.Response.WriteAsync("I am server. I received your greetings.");
});
var proxy = testSuite.GetReverseProxy();
proxy.BeforeRequest += async (sender, e) =>
{
e.HttpClient.Request.RequestUri = new Uri(server.ListeningHttpUrl);
await Task.FromResult(0);
};
var client = testSuite.GetReverseProxyClient();
var response = await client.PostAsync(new Uri($"https://localhost:{proxy.ProxyEndPoints[0].Port}"),
new StringContent("hello server. I am a client."));
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadAsStringAsync();
Assert.AreEqual("I am server. I received your greetings.", body);
}
[TestMethod]
public async Task Smoke_Test_Http_To_Https_Reverse_Proxy()
{
var testSuite = new TestSuite();
var server = testSuite.GetServer();
server.HandleRequest((context) =>
{
return context.Response.WriteAsync("I am server. I received your greetings.");
});
var proxy = testSuite.GetReverseProxy();
proxy.BeforeRequest += async (sender, e) =>
{
e.HttpClient.Request.RequestUri = new Uri(server.ListeningHttpsUrl);
await Task.FromResult(0);
};
var client = testSuite.GetReverseProxyClient();
var response = await client.PostAsync(new Uri($"http://localhost:{proxy.ProxyEndPoints[0].Port}"),
new StringContent("hello server. I am a client."));
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadAsStringAsync();
Assert.AreEqual("I am server. I received your greetings.", body);
}
[TestMethod]
public async Task Smoke_Test_Https_To_Https_Reverse_Proxy()
{
var testSuite = new TestSuite();
var server = testSuite.GetServer();
server.HandleRequest((context) =>
{
return context.Response.WriteAsync("I am server. I received your greetings.");
});
var proxy = testSuite.GetReverseProxy();
proxy.BeforeRequest += async (sender, e) =>
{
e.HttpClient.Request.RequestUri = new Uri(server.ListeningHttpsUrl);
await Task.FromResult(0);
};
var client = testSuite.GetReverseProxyClient();
var response = await client.PostAsync(new Uri($"https://localhost:{proxy.ProxyEndPoints[0].Port}"),
new StringContent("hello server. I am a client."));
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadAsStringAsync();
Assert.AreEqual("I am server. I received your greetings.", body);
}
}
}
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
namespace Titanium.Web.Proxy.IntegrationTests.Setup
{
public class TestProxyServer : IDisposable
{
public ProxyServer ProxyServer { get; private set; }
public int ListeningPort => ProxyServer.ProxyEndPoints[0].Port;
public CertificateManager CertificateManager => ProxyServer.CertificateManager;
public TestProxyServer(bool isReverseProxy, ProxyServer upStreamProxy = null)
{
ProxyServer = new ProxyServer();
ProxyEndPoint explicitEndPoint = isReverseProxy ?
(ProxyEndPoint)new TransparentProxyEndPoint(IPAddress.Any, 0, true) :
new ExplicitProxyEndPoint(IPAddress.Any, 0, true);
ProxyServer.AddEndPoint(explicitEndPoint);
if (upStreamProxy != null)
{
ProxyServer.UpStreamHttpProxy = new ExternalProxy()
{
HostName = "localhost",
Port = upStreamProxy.ProxyEndPoints[0].Port
};
ProxyServer.UpStreamHttpsProxy = new ExternalProxy()
{
HostName = "localhost",
Port = upStreamProxy.ProxyEndPoints[0].Port
};
}
ProxyServer.Start();
}
public void Dispose()
{
ProxyServer.Stop();
ProxyServer.Dispose();
}
}
}
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Http;
using System;
using Microsoft.Extensions.DependencyInjection;
using System.Linq;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.IntegrationTests.Setup
{
//set up a kestrel test server
public class TestServer : IDisposable
{
public string ListeningHttpUrl => $"http://localhost:{HttpListeningPort}";
public string ListeningHttpsUrl => $"https://localhost:{HttpsListeningPort}";
public int HttpListeningPort { get; private set; }
public int HttpsListeningPort { get; private set; }
private IWebHost host;
public TestServer(X509Certificate2 serverCertificate)
{
var startUp = new Startup(() => requestHandler);
host = WebHost.CreateDefaultBuilder()
.ConfigureServices(s =>
{
s.AddSingleton<IStartup>(startUp);
})
.UseKestrel(options =>
{
options.Listen(IPAddress.Loopback, 0);
options.Listen(IPAddress.Loopback, 0, listenOptions =>
{
listenOptions.UseHttps(serverCertificate);
});
})
.Build();
host.Start();
var addresses = host.ServerFeatures
.Get<IServerAddressesFeature>()
.Addresses.ToArray();
string httpAddress = addresses[0];
HttpListeningPort = int.Parse(httpAddress.Split(':')[2]);
string httpsAddress = addresses[1];
HttpsListeningPort = int.Parse(httpsAddress.Split(':')[2]);
}
Func<HttpContext, Task> requestHandler = null;
public void HandleRequest(Func<HttpContext, Task> requestHandler)
{
this.requestHandler = requestHandler;
}
public void Dispose()
{
host.StopAsync().Wait();
host.Dispose();
}
private class Startup : IStartup
{
Func<Func<HttpContext, Task>> requestHandler;
public Startup(Func<Func<HttpContext, Task>> requestHandler)
{
this.requestHandler = requestHandler;
}
public void Configure(IApplicationBuilder app)
{
app.Run(context =>
{
if (requestHandler == null)
{
throw new Exception("Test server not configured to handle request.");
}
return requestHandler()(context);
});
}
public IServiceProvider ConfigureServices(IServiceCollection services)
{
return services.BuildServiceProvider();
}
}
}
}
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using Titanium.Web.Proxy.IntegrationTests.Helpers;
using Titanium.Web.Proxy.IntegrationTests.Setup;
namespace Titanium.Web.Proxy.IntegrationTests
{
public class TestSuite
{
private TestServer server;
public TestSuite()
{
var dummyProxy = new ProxyServer();
var serverCertificate = dummyProxy.CertificateManager.CreateServerCertificate("localhost").Result;
server = new TestServer(serverCertificate);
}
public TestServer GetServer()
{
return server;
}
public ProxyServer GetProxy(ProxyServer upStreamProxy = null)
{
if (upStreamProxy != null)
{
return new TestProxyServer(false, upStreamProxy).ProxyServer;
}
return new TestProxyServer(false).ProxyServer;
}
public ProxyServer GetReverseProxy(ProxyServer upStreamProxy = null)
{
if (upStreamProxy != null)
{
return new TestProxyServer(true, upStreamProxy).ProxyServer;
}
return new TestProxyServer(true).ProxyServer;
}
public HttpClient GetClient(ProxyServer proxyServer)
{
return TestHelper.GetHttpClient(proxyServer.ProxyEndPoints[0].Port);
}
public HttpClient GetReverseProxyClient()
{
return TestHelper.GetHttpClient();
}
}
}
using System;
using System.Linq;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
namespace Titanium.Web.Proxy.IntegrationTests
{
[TestClass]
public class SslTests
{
[TestMethod]
public async Task TestSsl()
{
string testHost = "localhost";
using (var proxy = new ProxyTestController())
{
var serverCertificate = await proxy.CertificateManager.CreateServerCertificate(testHost);
using (var server = new Server(serverCertificate))
{
var testUrl = $"https://{testHost}:{server.HttpsListeningPort}";
using (var client = TestHelper.CreateHttpClient(proxy.ListeningPort))
{
var response = await client.GetAsync(new Uri(testUrl));
Assert.IsNotNull(response);
}
}
}
}
private class ProxyTestController : IDisposable
{
private readonly ProxyServer proxyServer;
public int ListeningPort => proxyServer.ProxyEndPoints[0].Port;
public CertificateManager CertificateManager => proxyServer.CertificateManager;
public ProxyTestController()
{
proxyServer = new ProxyServer();
var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 0, true);
proxyServer.AddEndPoint(explicitEndPoint);
proxyServer.Start();
}
public void Dispose()
{
proxyServer.Stop();
proxyServer.Dispose();
}
}
private class Server : IDisposable
{
public int HttpListeningPort;
public int HttpsListeningPort;
private IWebHost host;
public Server(X509Certificate2 serverCertificate)
{
host = new WebHostBuilder()
.UseKestrel(options =>
{
options.Listen(IPAddress.Loopback, 0);
options.Listen(IPAddress.Loopback, 0, listenOptions =>
{
listenOptions.UseHttps(serverCertificate);
});
})
.UseStartup<Startup>()
.Build();
host.Start();
string httpAddress = host.ServerFeatures
.Get<IServerAddressesFeature>()
.Addresses
.First();
string httpsAddress = host.ServerFeatures
.Get<IServerAddressesFeature>()
.Addresses
.Skip(1)
.First();
HttpListeningPort = int.Parse(httpAddress.Split(':')[2]);
HttpsListeningPort = int.Parse(httpsAddress.Split(':')[2]);
}
public void Dispose()
{
host.Dispose();
}
private class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Run(context =>
{
return context.Response.WriteAsync("Server received you request.");
});
}
}
}
}
}
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
<PackageReference Include="Microsoft.AspNetCore.App" /> <PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" /> <PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" /> <PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
......
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>net45</TargetFramework>
<SignAssembly>true</SignAssembly> <SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile>
</PropertyGroup> </PropertyGroup>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment