diff --git a/samples/SampleApp/Startup.cs b/samples/SampleApp/Startup.cs index f471f345cb..c9a27b42ff 100644 --- a/samples/SampleApp/Startup.cs +++ b/samples/SampleApp/Startup.cs @@ -6,6 +6,12 @@ using Microsoft.AspNet.Builder; using Microsoft.AspNet.Http; using Microsoft.Extensions.Logging; +#if DNX451 +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Microsoft.AspNet.Server.Kestrel.Https; +#endif + namespace SampleApp { public class Startup @@ -16,6 +22,21 @@ namespace SampleApp loggerFactory.AddConsole(LogLevel.Debug); +#if DNX451 + var testCertPath = Path.Combine( + Environment.CurrentDirectory, + @"../../test/Microsoft.AspNet.Server.KestrelTests/TestResources/testCert.cer"); + + if (File.Exists(testCertPath)) + { + app.UseKestrelHttps(new X509Certificate2(testCertPath)); + } + else + { + Console.WriteLine("Could not find certificate at '{0}'. HTTPS is not enabled.", testCertPath); + } +#endif + app.Run(async context => { Console.WriteLine("{0} {1}{2}{3}", diff --git a/samples/SampleApp/project.json b/samples/SampleApp/project.json index f4b23cfc64..fb159ea155 100644 --- a/samples/SampleApp/project.json +++ b/samples/SampleApp/project.json @@ -17,9 +17,8 @@ } }, "commands": { - "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel", - "run": "Microsoft.AspNet.Server.Kestrel", - "run-socket": "Microsoft.AspNet.Server.Kestrel --server.urls http://unix:/tmp/kestrel-test.sock", - "kestrel": "Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5000;https://localhost:5001" + "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5000;https://localhost:5001", + "kestrel": "Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5000;https://localhost:5001", + "run-socket": "Microsoft.AspNet.Server.Kestrel --server.urls http://unix:/tmp/kestrel-test.sock" } } diff --git a/test/Microsoft.AspNet.Server.KestrelTests/ConnectionFilterTests.cs b/test/Microsoft.AspNet.Server.KestrelTests/ConnectionFilterTests.cs new file mode 100644 index 0000000000..20c5b8fc1b --- /dev/null +++ b/test/Microsoft.AspNet.Server.KestrelTests/ConnectionFilterTests.cs @@ -0,0 +1,178 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; +using System.Threading.Tasks; +using Microsoft.AspNet.Server.Kestrel.Filter; +using Microsoft.AspNet.Server.Kestrel.Http; +using Xunit; + +namespace Microsoft.AspNet.Server.KestrelTests +{ + public class ConnectionFilterTests + { + private async Task App(Frame frame) + { + frame.ResponseHeaders.Clear(); + while (true) + { + var buffer = new byte[8192]; + var count = await frame.RequestBody.ReadAsync(buffer, 0, buffer.Length); + if (count == 0) + { + break; + } + await frame.ResponseBody.WriteAsync(buffer, 0, count); + } + } + + [Fact] + public async Task CanReadAndWriteWithRewritingConnectionFilter() + { + var filter = new RewritingConnectionFilter(); + var serviceContext = new TestServiceContext() + { + ConnectionFilter = filter + }; + var sendString = "POST / HTTP/1.0\r\n\r\nHello World?"; + + using (var server = new TestServer(App, serviceContext)) + { + using (var connection = new TestConnection()) + { + // "?" changes to "!" + await connection.SendEnd(sendString); + await connection.ReceiveEnd( + "HTTP/1.0 200 OK", + "", + "Hello World!"); + } + } + + Assert.Equal(sendString.Length, filter.BytesRead); + } + + [Fact] + public async Task CanReadAndWriteWithAsyncConnectionFilter() + { + var serviceContext = new TestServiceContext() + { + ConnectionFilter = new AsyncConnectionFilter() + }; + + using (var server = new TestServer(App, serviceContext)) + { + using (var connection = new TestConnection()) + { + await connection.SendEnd( + "POST / HTTP/1.0", + "", + "Hello World?"); + await connection.ReceiveEnd( + "HTTP/1.0 200 OK", + "", + "Hello World!"); + } + } + } + + private class RewritingConnectionFilter : IConnectionFilter + { + private static Task _empty = Task.FromResult(null); + + private RewritingStream _rewritingStream; + + public Task OnConnection(ConnectionFilterContext context) + { + _rewritingStream = new RewritingStream(context.Connection); + context.Connection = _rewritingStream; + return _empty; + } + + public int BytesRead => _rewritingStream.BytesRead; + } + + private class AsyncConnectionFilter : IConnectionFilter + { + public async Task OnConnection(ConnectionFilterContext context) + { + var oldConnection = context.Connection; + + // Set Connection to null to ensure it isn't used until the returned task completes. + context.Connection = null; + await Task.Delay(100); + + context.Connection = new RewritingStream(oldConnection); + } + } + + private class RewritingStream : Stream + { + private readonly Stream _innerStream; + + public RewritingStream(Stream innerStream) + { + _innerStream = innerStream; + } + + public int BytesRead { get; private set; } + + public override bool CanRead => _innerStream.CanRead; + + public override bool CanSeek => _innerStream.CanSeek; + + public override bool CanWrite => _innerStream.CanWrite; + + public override long Length => _innerStream.Length; + + public override long Position + { + get + { + return _innerStream.Position; + } + set + { + _innerStream.Position = value; + } + } + + public override void Flush() + { + // No-op + } + + public override int Read(byte[] buffer, int offset, int count) + { + var actual = _innerStream.Read(buffer, offset, count); + + BytesRead += actual; + + return actual; + } + + public override long Seek(long offset, SeekOrigin origin) + { + return _innerStream.Seek(offset, origin); + } + + public override void SetLength(long value) + { + _innerStream.SetLength(value); + } + + public override void Write(byte[] buffer, int offset, int count) + { + for (int i = 0; i < buffer.Length; i++) + { + if (buffer[i] == '?') + { + buffer[i] = (byte)'!'; + } + } + + _innerStream.Write(buffer, offset, count); + } + } + } +} diff --git a/test/Microsoft.AspNet.Server.KestrelTests/EngineTests.cs b/test/Microsoft.AspNet.Server.KestrelTests/EngineTests.cs index 10424fbc54..72867771b8 100644 --- a/test/Microsoft.AspNet.Server.KestrelTests/EngineTests.cs +++ b/test/Microsoft.AspNet.Server.KestrelTests/EngineTests.cs @@ -8,6 +8,7 @@ using System.Net.Sockets; using System.Text; using System.Threading.Tasks; using Microsoft.AspNet.Server.Kestrel; +using Microsoft.AspNet.Server.Kestrel.Filter; using Microsoft.AspNet.Server.Kestrel.Http; using Microsoft.Dnx.Runtime; using Microsoft.Dnx.Runtime.Infrastructure; @@ -20,6 +21,25 @@ namespace Microsoft.AspNet.Server.KestrelTests /// public class EngineTests { + public static TheoryData ConnectionFilterData + { + get + { + return new TheoryData + { + { + new TestServiceContext() + }, + { + new TestServiceContext + { + ConnectionFilter = new NoOpConnectionFilter() + } + } + }; + } + } + private async Task App(Frame frame) { frame.ResponseHeaders.Clear(); @@ -75,18 +95,20 @@ namespace Microsoft.AspNet.Server.KestrelTests return Task.FromResult(null); } - [Fact] - public void EngineCanStartAndStop() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public void EngineCanStartAndStop(ServiceContext testContext) { - var engine = new KestrelEngine(LibraryManager, new TestServiceContext()); + var engine = new KestrelEngine(LibraryManager, testContext); engine.Start(1); engine.Dispose(); } - [Fact] - public void ListenerCanCreateAndDispose() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public void ListenerCanCreateAndDispose(ServiceContext testContext) { - var engine = new KestrelEngine(LibraryManager, new TestServiceContext()); + var engine = new KestrelEngine(LibraryManager, testContext); engine.Start(1); var address = ServerAddress.FromUrl("http://localhost:54321/"); var started = engine.CreateServer(address, App); @@ -94,11 +116,11 @@ namespace Microsoft.AspNet.Server.KestrelTests engine.Dispose(); } - - [Fact] - public void ConnectionCanReadAndWrite() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public void ConnectionCanReadAndWrite(ServiceContext testContext) { - var engine = new KestrelEngine(LibraryManager, new TestServiceContext()); + var engine = new KestrelEngine(LibraryManager, testContext); engine.Start(1); var address = ServerAddress.FromUrl("http://localhost:54321/"); var started = engine.CreateServer(address, App); @@ -119,10 +141,12 @@ namespace Microsoft.AspNet.Server.KestrelTests engine.Dispose(); } - [Fact] - public async Task Http10() + + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task Http10(ServiceContext testContext) { - using (var server = new TestServer(App)) + using (var server = new TestServer(App, testContext)) { using (var connection = new TestConnection()) { @@ -138,10 +162,12 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - [Fact] - public async Task Http11() + + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task Http11(ServiceContext testContext) { - using (var server = new TestServer(AppChunked)) + using (var server = new TestServer(AppChunked, testContext)) { using (var connection = new TestConnection()) { @@ -165,11 +191,11 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - - [Fact] - public async Task Http10ContentLength() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task Http10ContentLength(ServiceContext testContext) { - using (var server = new TestServer(App)) + using (var server = new TestServer(App, testContext)) { using (var connection = new TestConnection()) { @@ -186,10 +212,11 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - [Fact] - public async Task Http10TransferEncoding() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task Http10TransferEncoding(ServiceContext testContext) { - using (var server = new TestServer(App)) + using (var server = new TestServer(App, testContext)) { using (var connection = new TestConnection()) { @@ -206,11 +233,11 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - - [Fact] - public async Task Http10KeepAlive() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task Http10KeepAlive(ServiceContext testContext) { - using (var server = new TestServer(AppChunked)) + using (var server = new TestServer(AppChunked, testContext)) { using (var connection = new TestConnection()) { @@ -235,10 +262,11 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - [Fact] - public async Task Http10KeepAliveNotUsedIfResponseContentLengthNotSet() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task Http10KeepAliveNotUsedIfResponseContentLengthNotSet(ServiceContext testContext) { - using (var server = new TestServer(App)) + using (var server = new TestServer(App, testContext)) { using (var connection = new TestConnection()) { @@ -264,8 +292,9 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - [Fact] - public async Task Http10KeepAliveContentLength() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task Http10KeepAliveContentLength(ServiceContext testContext) { using (var server = new TestServer(AppChunked)) { @@ -294,8 +323,9 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - [Fact] - public async Task Http10KeepAliveTransferEncoding() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task Http10KeepAliveTransferEncoding(ServiceContext testContext) { using (var server = new TestServer(AppChunked)) { @@ -325,10 +355,11 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - [Fact] - public async Task Expect100ContinueForBody() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task Expect100ContinueForBody(ServiceContext testContext) { - using (var server = new TestServer(AppChunked)) + using (var server = new TestServer(AppChunked, testContext)) { using (var connection = new TestConnection()) { @@ -350,11 +381,11 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - - [Fact] - public async Task DisconnectingClient() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task DisconnectingClient(ServiceContext testContext) { - using (var server = new TestServer(App)) + using (var server = new TestServer(App, testContext)) { var socket = new Socket(SocketType.Stream, ProtocolType.IP); socket.Connect(IPAddress.Loopback, 54321); @@ -375,10 +406,11 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - [Fact] - public async Task ZeroContentLengthSetAutomaticallyAfterNoWrites() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task ZeroContentLengthSetAutomaticallyAfterNoWrites(ServiceContext testContext) { - using (var server = new TestServer(EmptyApp)) + using (var server = new TestServer(EmptyApp, testContext)) { using (var connection = new TestConnection()) { @@ -402,10 +434,11 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - [Fact] - public async Task ZeroContentLengthNotSetAutomaticallyForNonKeepAliveRequests() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task ZeroContentLengthNotSetAutomaticallyForNonKeepAliveRequests(ServiceContext testContext) { - using (var server = new TestServer(EmptyApp)) + using (var server = new TestServer(EmptyApp, testContext)) { using (var connection = new TestConnection()) { @@ -435,10 +468,11 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - [Fact] - public async Task ZeroContentLengthNotSetAutomaticallyForHeadRequests() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task ZeroContentLengthNotSetAutomaticallyForHeadRequests(ServiceContext testContext) { - using (var server = new TestServer(EmptyApp)) + using (var server = new TestServer(EmptyApp, testContext)) { using (var connection = new TestConnection()) { @@ -454,8 +488,9 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - [Fact] - public async Task ZeroContentLengthNotSetAutomaticallyForCertainStatusCodes() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task ZeroContentLengthNotSetAutomaticallyForCertainStatusCodes(ServiceContext testContext) { using (var server = new TestServer(async frame => { @@ -466,7 +501,7 @@ namespace Microsoft.AspNet.Server.KestrelTests var statusString = await reader.ReadLineAsync(); frame.StatusCode = int.Parse(statusString); } - })) + }, testContext)) { using (var connection = new TestConnection()) { @@ -504,8 +539,9 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - [Fact] - public async Task ThrowingResultsIn500Response() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task ThrowingResultsIn500Response(ServiceContext testContext) { bool onStartingCalled = false; @@ -521,7 +557,7 @@ namespace Microsoft.AspNet.Server.KestrelTests frame.ResponseHeaders.Clear(); frame.ResponseHeaders["Content-Length"] = new[] { "11" }; throw new Exception(); - })) + }, testContext)) { using (var connection = new TestConnection()) { @@ -555,8 +591,9 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - [Fact] - public async Task ThrowingAfterWritingKillsConnection() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task ThrowingAfterWritingKillsConnection(ServiceContext testContext) { bool onStartingCalled = false; @@ -572,7 +609,7 @@ namespace Microsoft.AspNet.Server.KestrelTests frame.ResponseHeaders["Content-Length"] = new[] { "11" }; await frame.ResponseBody.WriteAsync(Encoding.ASCII.GetBytes("Hello World"), 0, 11); throw new Exception(); - })) + }, testContext)) { using (var connection = new TestConnection()) { @@ -591,8 +628,9 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - [Fact] - public async Task ThrowingAfterPartialWriteKillsConnection() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task ThrowingAfterPartialWriteKillsConnection(ServiceContext testContext) { bool onStartingCalled = false; @@ -608,7 +646,7 @@ namespace Microsoft.AspNet.Server.KestrelTests frame.ResponseHeaders["Content-Length"] = new[] { "11" }; await frame.ResponseBody.WriteAsync(Encoding.ASCII.GetBytes("Hello"), 0, 5); throw new Exception(); - })) + }, testContext)) { using (var connection = new TestConnection()) { @@ -627,10 +665,11 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - [Fact] - public async Task ConnectionClosesWhenFinReceived() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task ConnectionClosesWhenFinReceived(ServiceContext testContext) { - using (var server = new TestServer(AppChunked)) + using (var server = new TestServer(AppChunked, testContext)) { using (var connection = new TestConnection()) { @@ -653,10 +692,11 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - [Fact] - public async Task ConnectionClosesWhenFinReceivedBeforeRequestCompletes() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task ConnectionClosesWhenFinReceivedBeforeRequestCompletes(ServiceContext testContext) { - using (var server = new TestServer(AppChunked)) + using (var server = new TestServer(AppChunked, testContext)) { using (var connection = new TestConnection()) { @@ -694,8 +734,9 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - [Fact] - public async Task ThrowingInOnStartingResultsIn500Response() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task ThrowingInOnStartingResultsIn500Response(ServiceContext testContext) { using (var server = new TestServer(frame => { @@ -710,7 +751,7 @@ namespace Microsoft.AspNet.Server.KestrelTests // If we write to the response stream, we will not get a 500. return Task.FromResult(null); - })) + }, testContext)) { using (var connection = new TestConnection()) { @@ -742,8 +783,9 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - [Fact] - public async Task ThrowingInOnStartingResultsInFailedWrites() + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task ThrowingInOnStartingResultsInFailedWrites(ServiceContext testContext) { using (var server = new TestServer(async frame => { @@ -764,7 +806,7 @@ namespace Microsoft.AspNet.Server.KestrelTests // The second write should succeed since the OnStarting callback will not be called again await frame.ResponseBody.WriteAsync(Encoding.ASCII.GetBytes("Exception!!"), 0, 11); - })) + }, testContext)) { using (var connection = new TestConnection()) { diff --git a/test/Microsoft.AspNet.Server.KestrelTests/HttpsConnectionFilterTests.cs b/test/Microsoft.AspNet.Server.KestrelTests/HttpsConnectionFilterTests.cs new file mode 100644 index 0000000000..4a824be407 --- /dev/null +++ b/test/Microsoft.AspNet.Server.KestrelTests/HttpsConnectionFilterTests.cs @@ -0,0 +1,74 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +#if DNX451 +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; +using Microsoft.AspNet.Server.Kestrel.Filter; +using Microsoft.AspNet.Server.Kestrel.Http; +using Microsoft.AspNet.Server.Kestrel.Https; +using Microsoft.AspNet.Testing.xunit; +using Xunit; + +namespace Microsoft.AspNet.Server.KestrelTests +{ + public class HttpsConnectionFilterTests + { + private async Task App(Frame frame) + { + frame.ResponseHeaders.Clear(); + while (true) + { + var buffer = new byte[8192]; + var count = await frame.RequestBody.ReadAsync(buffer, 0, buffer.Length); + if (count == 0) + { + break; + } + await frame.ResponseBody.WriteAsync(buffer, 0, count); + } + } + + // https://github.com/aspnet/KestrelHttpServer/issues/240 + // This test currently fails on mono because of an issue with SslStream. + [ConditionalFact] + [OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)] + public async Task CanReadAndWriteWithHttpsConnectionFilter() + { + RemoteCertificateValidationCallback validationCallback = + (sender, cert, chain, sslPolicyErrors) => true; + + try + { + ServicePointManager.ServerCertificateValidationCallback += validationCallback; + + var sereverAddress = "https://localhost:54321/"; + var serviceContext = new TestServiceContext() + { + ConnectionFilter = new HttpsConnectionFilter(new X509Certificate2(@"TestResources/testCert.cer"), new NoOpConnectionFilter()) + }; + + using (var server = new TestServer(App, serviceContext, sereverAddress)) + { + using (var client = new HttpClient()) + { + var result = await client.PostAsync(sereverAddress, new FormUrlEncodedContent(new[] { + new KeyValuePair("content", "Hello World?") + })); + + Assert.Equal("content=Hello+World%3F", await result.Content.ReadAsStringAsync()); + } + } + } + finally + { + ServicePointManager.ServerCertificateValidationCallback -= validationCallback; + } + } + } +} +#endif diff --git a/test/Microsoft.AspNet.Server.KestrelTests/TestResources/testCert.cer b/test/Microsoft.AspNet.Server.KestrelTests/TestResources/testCert.cer new file mode 100644 index 0000000000..75b57442b0 Binary files /dev/null and b/test/Microsoft.AspNet.Server.KestrelTests/TestResources/testCert.cer differ diff --git a/test/Microsoft.AspNet.Server.KestrelTests/TestServer.cs b/test/Microsoft.AspNet.Server.KestrelTests/TestServer.cs index 667ecdd6c7..4624dc1e9c 100644 --- a/test/Microsoft.AspNet.Server.KestrelTests/TestServer.cs +++ b/test/Microsoft.AspNet.Server.KestrelTests/TestServer.cs @@ -19,8 +19,17 @@ namespace Microsoft.AspNet.Server.KestrelTests private IDisposable _server; public TestServer(Func app) + : this(app, new TestServiceContext()) { - Create(app); + } + + public TestServer(Func app, ServiceContext context) + : this(app, context, "http://localhost:54321/") + { + } + public TestServer(Func app, ServiceContext context, string serverAddress) + { + Create(app, context, serverAddress); } ILibraryManager LibraryManager @@ -45,14 +54,14 @@ namespace Microsoft.AspNet.Server.KestrelTests } } - public void Create(Func app) + public void Create(Func app, ServiceContext context, string serverAddress) { _engine = new KestrelEngine( LibraryManager, - new TestServiceContext()); + context); _engine.Start(1); _server = _engine.CreateServer( - ServerAddress.FromUrl("http://localhost:54321/"), + ServerAddress.FromUrl(serverAddress), app); } diff --git a/test/Microsoft.AspNet.Server.KestrelTests/project.json b/test/Microsoft.AspNet.Server.KestrelTests/project.json index 907cb11eca..9cb03bd95e 100644 --- a/test/Microsoft.AspNet.Server.KestrelTests/project.json +++ b/test/Microsoft.AspNet.Server.KestrelTests/project.json @@ -2,10 +2,16 @@ "version": "1.0.0-*", "dependencies": { "xunit.runner.aspnet": "2.0.0-aspnet-*", - "Microsoft.AspNet.Server.Kestrel": "1.0.0-*" + "Microsoft.AspNet.Server.Kestrel": "1.0.0-*", + "Microsoft.AspNet.Testing": "1.0.0-*" }, "frameworks": { - "dnx451": { }, + "dnx451": { + "dependencies": { + "System.Net.Http": "4.0.1-beta-*", + "Microsoft.AspNet.Server.Kestrel.Https": "1.0.0-*" + } + }, "dnxcore50": { "dependencies": { "System.Diagnostics.TraceSource": "4.0.0-beta-*",