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

Add a Configuration package and tests. #1878

Closed
wants to merge 10 commits into from

Conversation

Tratcher
Copy link
Member

@Tratcher Tratcher commented Jun 1, 2017

#1875, aspnet/Hosting#1095
This moves config code from Microsoft.AspNetCore.dll down to Kestrel's own config package. A reaction PR will follow for MetaPackages.
The cross targeting is due to the src package.

@Tratcher Tratcher added this to the 2.0.0-preview2 milestone Jun 1, 2017
@Tratcher Tratcher self-assigned this Jun 1, 2017
@Tratcher Tratcher requested review from davidfowl, cesarblum and HaoK June 1, 2017 16:04
/// <returns>
/// The Microsoft.AspNetCore.Hosting.IWebHostBuilder.
/// </returns>
public static IWebHostBuilder UseKestrelWithConfiguration(this IWebHostBuilder hostBuilder)
Copy link
Member

@davidfowl davidfowl Jun 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this and why do we need it?

Copy link
Member

@HaoK HaoK Jun 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there no way to takeover the default UseKestrel() which would make it match all of the other AddXyz()'s that also add default AddConfigureOptions?

Can we just add a reference to Microsoft.AspNetCore.Certificates.Configuration.Sources and ConfigurationBinder in Microsoft.AspNetCore.Server.Kestrel and do this inside of UseKestrel?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not without pulling in the .Https dependency.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets just make the .Kestrel package the uber one and nuke this package.


namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
{
internal class KestrelServerConfigureOptions : ConfigureDefaultOptions<KestrelServerOptions>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this public.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want all of these ConfigureDefaultOptions public? Or just Kestrel's since its doing real work unlike the rest which are usually one liners that only call GetSection().Bind which are mostly private.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be pubternal yea.

Copy link
Member

@HaoK HaoK Jun 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I'll file an issue to make them all pubternal post preview2 if I don't end up touching them again this week. We need to standardize the naming then.

Xyz.Infrastructure/Internal.ConfigureDefaultXyzOptions?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.Internal

<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;kestrel</PackageTags>
<NoWarn>CS1591;$(NoWarn)</NoWarn>
<EnableApiCheck>false</EnableApiCheck>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Certificates.Configuration.Sources" Version="$(AspNetCoreVersion)" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PrivateAssets=All

@@ -28,6 +29,7 @@ public static IWebHostBuilder UseKestrel(this IWebHostBuilder hostBuilder)
return hostBuilder.ConfigureServices(services =>
{
services.AddTransient<IConfigureOptions<KestrelServerOptions>, KestrelServerOptionsSetup>();
services.AddTransient<IConfigureOptions<KestrelServerOptions>, KestrelServerConfigureOptions>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right.

@@ -28,6 +29,7 @@ public static IWebHostBuilder UseKestrel(this IWebHostBuilder hostBuilder)
return hostBuilder.ConfigureServices(services =>
{
services.AddTransient<IConfigureOptions<KestrelServerOptions>, KestrelServerOptionsSetup>();
services.AddTransient<IConfigureOptions<KestrelServerOptions>, KestrelServerConfigureOptions>();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing it this way temporarily to work around aspnet/DependencyInjection#500

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@HaoK are all of the other sub systems doing this for preview2?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That works, the other alternative would be to register

services.AddTransient<IConfigureOptions<KestrelServerOptions>, ConfigureDefaults<KestrelServerConfigureOptions>()

Which would let us just remove this line once the DI is fixed.

For preview 2 I don't think it really matters which one we do. Its slightly easier to cleanup if we go with lining up all the defaults for now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

chatted a bit offline with @davidfowl lets use services.AddTransient<IConfigureOptions<KestrelServerOptions>, ConfigureDefaults<ConfigureDefaultKestrelServerOptions>() so when the DI issues is fixed, we only have to remove this line, and won't have to update the ConfigureDefaultOptions class

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's getting fixed: aspnet/DependencyInjection#530
That said, @halter73 says we can't rely on that because it doesn't guarantee the same ordering and KestrelServerConfigureOptions requires KestrelServerOptionsSetup to have run first.


if (!IPAddress.TryParse(configAddress, out var address))
{
throw new InvalidOperationException($"Invalid IP address in configuration: {configAddress}");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User facing strings should go in the resx file.

}
catch (KeyNotFoundException) when (certificateConfig.Value.Equals(DevelopmentSSLCertificateName, StringComparison.Ordinal) && _hostingEnvironment.IsDevelopment())
{
var storeLoader = new CertificateStoreLoader();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know you're just moving the code, but it still bothers me that we're newing this up here. I think loading the default cert should be a method on CertificateLoader. Thoughts?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This really isn't the time to refactor it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah just file an issue for post preview 2 :)

if (certificate == null)
{
var logger = _loggerFactory.CreateLogger("Microsoft.AspNetCore.Server.Kestrel.KestrelServerConfigureOptions");
logger.LogError("No HTTPS certificate was found for development. For information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resx


if (certificate == null)
{
throw new InvalidOperationException($"No certificate found for endpoint '{endPoint.Key}'.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resx

}
catch (Exception ex)
{
throw new InvalidOperationException("Unable to configure HTTPS endpoint. For information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.", ex);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resx

@@ -4,19 +4,22 @@

<PropertyGroup>
<Description>ASP.NET Core Kestrel cross-platform web server.</Description>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks>netstandard2.0;netcoreapp2.0</TargetFrameworks>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cert loader sources package requires it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is the ifdef?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, what happens on .NET Framework?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It uses the netstandard version that doesn't have this new feature

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which does what?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just move this to the Core project. Currently only the "meta" project only contains WebHostBuilderKestrelExtensions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nvm. I just realized this depends on both the Core and Https projects.


namespace Microsoft.AspNetCore.Server.Kestrel.Internal
{
public class KestrelServerConfigureOptions : IConfigureOptions<KestrelServerOptions>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now the only class in the meta project other than WebHostBuilderKestrelExtensions. Why not just put this in Core/Internal alongside KestrelServerOptionsSetup? Or better yet, just combine this with KestrelServerOptionsSetup.

Copy link
Member

@davidfowl davidfowl Jun 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, lets keep core clean. I don't want configuration leaking into the core APIs. The "meta package" is where all of the dependencies sit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can't combine them as one is a true default that you always want to apply, while the config binding one is a 'squishy' default, that we only want to apply by default via WebHostBuilder

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It requires .Https

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wouldn't work anyway since this calls UseHttps() 😢

private static int GetWebHostPort(IWebHost webHost)
=> webHost.ServerFeatures.Get<IServerAddressesFeature>().Addresses
.Select(serverAddress => new Uri(serverAddress).Port)
.FirstOrDefault();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Single()

using Microsoft.Extensions.DependencyInjection;
using Xunit;

namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any tests verifying the behavior when something goes wrong like being given an invalid address value or a bad/missing cert? Would the host fail to start even if there are other addresses that are successfully configured?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It throws. I added a test.

<ProjectReference Include="..\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.csproj" />
</ItemGroup>

<ItemGroup>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove?

@Tratcher
Copy link
Member Author

Tratcher commented Jun 2, 2017

That should be everything, Please review.

@Tratcher
Copy link
Member Author

Tratcher commented Jun 2, 2017

rebased and merged.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants