Skip to content
This repository has been archived by the owner on Dec 18, 2018. It is now read-only.

Commit

Permalink
Remove ListenOptions.Scheme and move IConnectionFilter to .Internal n…
Browse files Browse the repository at this point in the history
…amespace

Add an internal API to ListenOptions to determine if an endpoint is configured to use HTTPS. This is a temporary as the design of connection adapters and configuration will churn before release.
  • Loading branch information
Nate McMaster committed Apr 13, 2017
1 parent 8258d30 commit ed4a27a
Show file tree
Hide file tree
Showing 16 changed files with 83 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

using System.IO;

namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
{
// Even though this only includes the non-adapted ConnectionStream currently, this is a context in case
// we want to add more connection metadata later.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using System.IO;
using Microsoft.AspNetCore.Http.Features;

namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
{
public interface IAdaptedConnection
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@

using System.Threading.Tasks;

namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
{
public interface IConnectionAdapter
{
bool IsHttps { get; }
Task<IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public LoggingConnectionAdapter(ILogger logger)
_logger = logger;
}

public bool IsHttps => false;

public Task<IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context)
{
return Task.FromResult<IAdaptedConnection>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public IConnectionContext OnConnection(IConnectionInformation connectionInfo)
});

_serviceContext.Log.ConnectionStart(connectionId);
KestrelEventSource.Log.ConnectionStart(_listenOptions, connection, connectionInfo);
KestrelEventSource.Log.ConnectionStart(connection, connectionInfo);

// Since data cannot be added to the inputPipe by the transport until OnConnection returns,
// Frame.RequestProcessingAsync is guaranteed to unblock the transport thread before calling
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Generic;
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter;
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter;
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.Kestrel.Internal.System;
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,13 @@ private KestrelEventSource()
// - Avoid renaming methods or parameters marked with EventAttribute. EventSource uses these to form the event object.

[NonEvent]
public void ConnectionStart(ListenOptions listenOptions, IConnectionContext context, IConnectionInformation information)
public void ConnectionStart(IConnectionContext context, IConnectionInformation information)
{
// avoid allocating strings unless this event source is enabled
if (IsEnabled())
{
ConnectionStart(
context.ConnectionId,
listenOptions.Scheme,
information.LocalEndPoint.ToString(),
information.RemoteEndPoint.ToString());
}
Expand All @@ -42,14 +41,12 @@ public void ConnectionStart(ListenOptions listenOptions, IConnectionContext cont
[MethodImpl(MethodImplOptions.NoInlining)]
[Event(1, Level = EventLevel.Verbose)]
private void ConnectionStart(string connectionId,
string scheme,
string localEndPoint,
string remoteEndPoint)
{
WriteEvent(
1,
connectionId,
scheme,
localEndPoint,
remoteEndPoint
);
Expand Down
29 changes: 10 additions & 19 deletions src/Microsoft.AspNetCore.Server.Kestrel.Core/KestrelServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ public async Task StartAsync<TContext>(IHttpApplication<TContext> application, C
{
throw new InvalidOperationException($"HTTPS endpoints can only be configured using {nameof(KestrelServerOptions)}.{nameof(KestrelServerOptions.Listen)}().");
}
else if (!parsedAddress.Scheme.Equals("http", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException($"Unrecognized scheme in server address '{address}'. Only 'http://' is supported.");
}

if (!string.IsNullOrEmpty(parsedAddress.PathBase))
{
Expand All @@ -166,10 +170,7 @@ public async Task StartAsync<TContext>(IHttpApplication<TContext> application, C

if (parsedAddress.IsUnixPipe)
{
listenOptions.Add(new ListenOptions(parsedAddress.UnixPipePath)
{
Scheme = parsedAddress.Scheme,
});
listenOptions.Add(new ListenOptions(parsedAddress.UnixPipePath));
}
else
{
Expand All @@ -185,10 +186,7 @@ public async Task StartAsync<TContext>(IHttpApplication<TContext> application, C
else
{
// These endPoints will be added later to _serverAddresses.Addresses
listenOptions.Add(new ListenOptions(CreateIPEndPoint(parsedAddress))
{
Scheme = parsedAddress.Scheme,
});
listenOptions.Add(new ListenOptions(CreateIPEndPoint(parsedAddress)));
}
}
}
Expand All @@ -209,8 +207,7 @@ public async Task StartAsync<TContext>(IHttpApplication<TContext> application, C
throw new IOException($"Failed to bind to address {endPoint}: address already in use.", ex);
}

// If requested port was "0", replace with assigned dynamic port.
_serverAddresses.Addresses.Add(endPoint.ToString());
_serverAddresses.Addresses.Add(endPoint.GetDisplayName());
}
}
catch (Exception ex)
Expand Down Expand Up @@ -285,10 +282,7 @@ private async Task StartLocalhostAsync<TContext>(ServerAddress parsedAddress, Se

try
{
var ipv4ListenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, parsedAddress.Port))
{
Scheme = parsedAddress.Scheme,
};
var ipv4ListenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, parsedAddress.Port));

var connectionHandler = new ConnectionHandler<TContext>(ipv4ListenOptions, serviceContext, application);
var transport = _transportFactory.Create(ipv4ListenOptions, connectionHandler);
Expand All @@ -307,10 +301,7 @@ private async Task StartLocalhostAsync<TContext>(ServerAddress parsedAddress, Se

try
{
var ipv6ListenOptions = new ListenOptions(new IPEndPoint(IPAddress.IPv6Loopback, parsedAddress.Port))
{
Scheme = parsedAddress.Scheme,
};
var ipv6ListenOptions = new ListenOptions(new IPEndPoint(IPAddress.IPv6Loopback, parsedAddress.Port));

var connectionHandler = new ConnectionHandler<TContext>(ipv6ListenOptions, serviceContext, application);
var transport = _transportFactory.Create(ipv6ListenOptions, connectionHandler);
Expand Down Expand Up @@ -349,4 +340,4 @@ internal static IPEndPoint CreateIPEndPoint(ServerAddress address)
return new IPEndPoint(ip, address.Port);
}
}
}
}
27 changes: 15 additions & 12 deletions src/Microsoft.AspNetCore.Server.Kestrel.Core/ListenOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter;
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;

namespace Microsoft.AspNetCore.Server.Kestrel.Core
Expand Down Expand Up @@ -82,26 +83,28 @@ internal ListenOptions(ulong fileHandle)
/// </remarks>
public List<IConnectionAdapter> ConnectionAdapters { get; } = new List<IConnectionAdapter>();

// Scheme is hopefully only a temporary measure for back compat with IServerAddressesFeature.
// TODO: Allow connection adapters to configure the scheme
public string Scheme { get; set; } = "http";

public override string ToString()
/// <summary>
/// Gets the name of this endpoint to display on command-line when the web server starts.
/// </summary>
internal string GetDisplayName()
{
// Use http scheme for all addresses. If https should be used for this endPoint,
// it can still be configured for this endPoint specifically.
var scheme = ConnectionAdapters.Any(f => f.IsHttps)
? "https"
: "http";

switch (Type)
{
case ListenType.IPEndPoint:
return $"{Scheme}://{IPEndPoint}";
return $"{scheme}://{IPEndPoint}";
case ListenType.SocketPath:
return $"{Scheme}://unix:{SocketPath}";
return $"{scheme}://unix:{SocketPath}";
case ListenType.FileHandle:
// This was never supported via --server.urls, so no need to include Scheme.
return "http://<file handle>";
return $"{scheme}://<file handle>";
default:
throw new InvalidOperationException();
}
}

public override string ToString() => GetDisplayName();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter;
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Https.Internal;
using Microsoft.Extensions.Logging;

Expand Down Expand Up @@ -40,6 +40,8 @@ public HttpsConnectionAdapter(HttpsConnectionAdapterOptions options, ILoggerFact
_logger = loggerFactory?.CreateLogger(nameof(HttpsConnectionAdapter));
}

public bool IsHttps => true;

public async Task<IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context)
{
SslStream sslStream;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,22 @@ public void ThrowsWhenBindingLocalhostToDynamicPort()
}
}

[Theory]
[InlineData("https://localhost")]
[InlineData("ftp://localhost")]
public void ThrowsForUnsupportedAddressFromHosting(string addr)
{
var hostBuilder = new WebHostBuilder()
.UseKestrel()
.UseUrls(addr)
.Configure(ConfigureEchoAddress);

using (var host = hostBuilder.Build())
{
Assert.Throws<InvalidOperationException>(() => host.Start());
}
}

private void ThrowsWhenBindingLocalhostToAddressInUse(AddressFamily addressFamily, IPAddress address)
{
using (var socket = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter;
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal;
using Microsoft.AspNetCore.Testing;
using Xunit;

Expand Down Expand Up @@ -112,6 +112,8 @@ private class RewritingConnectionAdapter : IConnectionAdapter
{
private RewritingStream _rewritingStream;

public bool IsHttps => false;

public Task<IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context)
{
_rewritingStream = new RewritingStream(context.ConnectionStream);
Expand All @@ -123,6 +125,8 @@ public Task<IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext conte

private class AsyncConnectionAdapter : IConnectionAdapter
{
public bool IsHttps => false;

public async Task<IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context)
{
await Task.Delay(100);
Expand All @@ -132,6 +136,8 @@ public async Task<IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext

private class ThrowingConnectionAdapter : IConnectionAdapter
{
public bool IsHttps => false;

public Task<IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context)
{
throw new Exception();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ await connection.SendAll("GET / HTTP/1.1",

{
var start = Assert.Single(events, e => e.EventName == "ConnectionStart");
Assert.All(new[] { "connectionId", "scheme", "remoteEndPoint", "localEndPoint" }, p => Assert.Contains(p, start.PayloadNames));
Assert.Equal("http", GetProperty(start, "scheme"));
Assert.All(new[] { "connectionId", "remoteEndPoint", "localEndPoint" }, p => Assert.Contains(p, start.PayloadNames));
Assert.Equal($"127.0.0.1:{port}", GetProperty(start, "localEndPoint"));
}
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers;
Expand Down Expand Up @@ -46,7 +47,7 @@ public async Task ConnectionsGetRoundRobinedToSecondaryListeners()
await libuvThreadPrimary.StartAsync();
var listenerPrimary = new ListenerPrimary(transportContextPrimary);
await listenerPrimary.StartAsync(pipeName, pipeMessage, listenOptions, libuvThreadPrimary);
var address = listenOptions.ToString();
var address = GetUri(listenOptions);

// Until a secondary listener is added, TCP connections get dispatched directly
Assert.Equal("Primary", await HttpClientSlim.GetStringAsync(address));
Expand Down Expand Up @@ -108,7 +109,7 @@ public async Task NonListenerPipeConnectionsAreLoggedAndIgnored()
await libuvThreadPrimary.StartAsync();
var listenerPrimary = new ListenerPrimary(transportContextPrimary);
await listenerPrimary.StartAsync(pipeName, pipeMessage, listenOptions, libuvThreadPrimary);
var address = listenOptions.ToString();
var address = GetUri(listenOptions);

// Add secondary listener
var libuvThreadSecondary = new LibuvThread(libuvTransport);
Expand Down Expand Up @@ -217,7 +218,7 @@ public async Task PipeConnectionsWithWrongMessageAreLoggedAndIgnored()
await libuvThreadPrimary.StartAsync();
var listenerPrimary = new ListenerPrimary(transportContextPrimary);
await listenerPrimary.StartAsync(pipeName, pipeMessage, listenOptions, libuvThreadPrimary);
var address = listenOptions.ToString();
var address = GetUri(listenOptions);

// Add secondary listener with wrong pipe message
var libuvThreadSecondary = new LibuvThread(libuvTransport);
Expand Down Expand Up @@ -249,7 +250,7 @@ public async Task PipeConnectionsWithWrongMessageAreLoggedAndIgnored()
}

private static async Task AssertResponseEventually(
string address,
Uri address,
string expected,
string[] allowed = null,
int maxRetries = 100,
Expand All @@ -273,5 +274,19 @@ private static async Task AssertResponseEventually(

Assert.True(false, $"'{address}' failed to respond with '{expected}' in {maxRetries} retries.");
}

private static Uri GetUri(ListenOptions options)
{
if (options.Type != ListenType.IPEndPoint)
{
throw new InvalidOperationException($"Could not determine a proper URI for options with Type {options.Type}");
}

var scheme = options.ConnectionAdapters.Any(f => f.IsHttps)
? "https"
: "http";

return new Uri($"{scheme}://{options.IPEndPoint}");
}
}
}
2 changes: 2 additions & 0 deletions test/shared/PassThroughConnectionAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ namespace Microsoft.AspNetCore.Testing
{
public class PassThroughConnectionAdapter : IConnectionAdapter
{
public bool IsHttps => false;

public Task<IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context)
{
var adapted = new AdaptedConnection(new LoggingStream(context.ConnectionStream, new TestApplicationErrorLogger()));
Expand Down

0 comments on commit ed4a27a

Please sign in to comment.