Commit 27ccf183 authored by justcoding121's avatar justcoding121

#543 Fix reverse proxy. add tests.

parent 8db82807
......@@ -34,10 +34,6 @@ namespace Titanium.Web.Proxy
var clientStream = new CustomBufferedStream(clientConnection.GetStream(), BufferPool, BufferSize);
var clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize);
Task<TcpServerConnection> prefetchConnectionTask = null;
bool closeServerConnection = false;
bool calledRequestHandler = false;
try
{
var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken);
......@@ -63,16 +59,7 @@ namespace Titanium.Web.Proxy
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;
//do client authentication using fake certificate
......@@ -140,39 +127,29 @@ namespace Titanium.Web.Proxy
return;
}
}
calledRequestHandler = true;
// HTTPS server created - we can now decrypt the client's traffic
// Now create the request
await handleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter,
cancellationTokenSource, isHttps ? httpsHostName : null, null, prefetchConnectionTask);
cancellationTokenSource, isHttps ? httpsHostName : null, null, null);
}
catch (ProxyException e)
{
closeServerConnection = true;
onException(clientStream, e);
}
catch (IOException e)
{
closeServerConnection = true;
onException(clientStream, new Exception("Connection was aborted", e));
}
catch (SocketException e)
{
closeServerConnection = true;
onException(clientStream, new Exception("Could not connect", e));
}
catch (Exception e)
{
closeServerConnection = true;
onException(clientStream, new Exception("Error occured in whilst handling the client", e));
}
finally
{
if (!calledRequestHandler)
{
await tcpConnectionFactory.Release(prefetchConnectionTask, closeServerConnection);
}
clientStream.Dispose();
if (!cancellationTokenSource.IsCancellationRequested)
......
......@@ -2,11 +2,11 @@
using System.Net;
using System.Net.Http;
namespace Titanium.Web.Proxy.IntegrationTests
namespace Titanium.Web.Proxy.IntegrationTests.Helpers
{
public static class TestHelper
{
public static HttpClient CreateHttpClient(int localProxyPort)
public static HttpClient GetHttpClient(int localProxyPort)
{
var proxy = new TestProxy($"http://localhost:{localProxyPort}");
......@@ -19,6 +19,11 @@ namespace Titanium.Web.Proxy.IntegrationTests
return new HttpClient(handler);
}
public static HttpClient GetHttpClient()
{
return new HttpClient(new HttpClientHandler());
}
public class TestProxy : IWebProxy
{
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.Linq;
using System.Net;
using System.Net.Http;
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.EventArguments;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
namespace Titanium.Web.Proxy.IntegrationTests
{
......@@ -19,123 +11,177 @@ namespace Titanium.Web.Proxy.IntegrationTests
public class InterceptionTests
{
[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) =>
{
if (e.HttpClient.Request.Url.Contains("localhost"))
{
var testUrl = $"http://{testHost}:{server.HttpListeningPort}";
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);
};
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
var client = testSuite.GetClient(proxy);
var response = await client.GetAsync(new Uri(server.ListeningHttpUrl));
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadAsStringAsync();
Assert.IsTrue(body.Contains("TitaniumWebProxy-Stopped!!"));
var body = await response.Content.ReadAsStringAsync();
Assert.IsTrue(body.Contains("TitaniumWebProxy-Stopped!!"));
}
}
}
}
private class ProxyTestController : IDisposable
[TestMethod]
public async Task Can_Intercept_Post_Requests()
{
private readonly ProxyServer proxyServer;
public int ListeningPort => proxyServer.ProxyEndPoints[0].Port;
public CertificateManager CertificateManager => proxyServer.CertificateManager;
var testSuite = new TestSuite();
public ProxyTestController()
var server = testSuite.GetServer();
server.HandleRequest((context) =>
{
proxyServer = new ProxyServer();
var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 0, true);
proxyServer.AddEndPoint(explicitEndPoint);
proxyServer.BeforeRequest += OnRequest;
proxyServer.Start();
}
public async Task OnRequest(object sender, SessionEventArgs e)
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"))
{
if (e.HttpClient.Request.HasBody)
{
var body = await e.GetRequestBodyAsString();
}
e.Ok("<html><body>TitaniumWebProxy-Stopped!!</body></html>");
return;
}
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()
{
proxyServer.BeforeRequest -= OnRequest;
proxyServer.Stop();
proxyServer.Dispose();
}
}
private class Server : IDisposable
[TestMethod]
public async Task Can_Intercept_Put_Requests()
{
public int HttpListeningPort;
public int HttpsListeningPort;
var testSuite = new TestSuite();
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()
var server = testSuite.GetServer();
server.HandleRequest((context) =>
{
host.Dispose();
}
return context.Response.WriteAsync("I am server. I received your greetings.");
});
private class Startup
var proxy = testSuite.GetProxy();
proxy.BeforeRequest += async (sender, e) =>
{
public void Configure(IApplicationBuilder app)
if (e.HttpClient.Request.Url.Contains("localhost"))
{
app.Run(context =>
{
return context.Response.WriteAsync("Server received you request.");
});
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!!"));
}
[TestMethod]
public async Task Can_Intercept_Patch_Requests()
{
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();
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.PatchAsync(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!!"));
}
[TestMethod]
public async Task Can_Intercept_Delete_Requests()
{
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();
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 @@
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" 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="MSTest.TestAdapter" Version="1.4.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
......
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<TargetFramework>net45</TargetFramework>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile>
</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