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

Implement configuration support #2186

Merged
merged 1 commit into from
Dec 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions KestrelHttpServer.sln
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27110.0
VisualStudioVersion = 15.0.27130.2010
MinimumVisualStudioVersion = 15.0.26730.03
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7972A5D6-3385-4127-9277-428506DD44FF}"
ProjectSection(SolutionItems) = preProject
Expand Down Expand Up @@ -104,6 +104,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Protocols.Abstractions", "s
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{C2910A13-B2C2-46D8-81D8-7E166F4F5981}"
ProjectSection(SolutionItems) = preProject
build\dependencies.props = build\dependencies.props
Copy link
Member

Choose a reason for hiding this comment

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

👍

build\repo.props = build\repo.props
build\repo.targets = build\repo.targets
EndProjectSection
Expand All @@ -119,7 +120,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kestrel.Transport.Libuv.Fun
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kestrel.Transport.Sockets.FunctionalTests", "test\Kestrel.Transport.Sockets.FunctionalTests\Kestrel.Transport.Sockets.FunctionalTests.csproj", "{9C7B6B5F-088A-436E-834B-6373EA36DEEE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Http2SampleApp", "samples\Http2SampleApp\Http2SampleApp.csproj", "{7BC22A4A-15D2-44C2-AB45-049F0FB562FA}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Http2SampleApp", "samples\Http2SampleApp\Http2SampleApp.csproj", "{7BC22A4A-15D2-44C2-AB45-049F0FB562FA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SystemdTestApp", "samples\SystemdTestApp\SystemdTestApp.csproj", "{A7994A41-CAF8-47A7-8975-F101F75B5BC1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -335,6 +338,18 @@ Global
{7BC22A4A-15D2-44C2-AB45-049F0FB562FA}.Release|x64.Build.0 = Release|Any CPU
{7BC22A4A-15D2-44C2-AB45-049F0FB562FA}.Release|x86.ActiveCfg = Release|Any CPU
{7BC22A4A-15D2-44C2-AB45-049F0FB562FA}.Release|x86.Build.0 = Release|Any CPU
{A7994A41-CAF8-47A7-8975-F101F75B5BC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A7994A41-CAF8-47A7-8975-F101F75B5BC1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A7994A41-CAF8-47A7-8975-F101F75B5BC1}.Debug|x64.ActiveCfg = Debug|Any CPU
{A7994A41-CAF8-47A7-8975-F101F75B5BC1}.Debug|x64.Build.0 = Debug|Any CPU
{A7994A41-CAF8-47A7-8975-F101F75B5BC1}.Debug|x86.ActiveCfg = Debug|Any CPU
{A7994A41-CAF8-47A7-8975-F101F75B5BC1}.Debug|x86.Build.0 = Debug|Any CPU
{A7994A41-CAF8-47A7-8975-F101F75B5BC1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7994A41-CAF8-47A7-8975-F101F75B5BC1}.Release|Any CPU.Build.0 = Release|Any CPU
{A7994A41-CAF8-47A7-8975-F101F75B5BC1}.Release|x64.ActiveCfg = Release|Any CPU
{A7994A41-CAF8-47A7-8975-F101F75B5BC1}.Release|x64.Build.0 = Release|Any CPU
{A7994A41-CAF8-47A7-8975-F101F75B5BC1}.Release|x86.ActiveCfg = Release|Any CPU
{A7994A41-CAF8-47A7-8975-F101F75B5BC1}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -359,6 +374,7 @@ Global
{74032D79-8EA7-4483-BD82-C38370420FFF} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
{9C7B6B5F-088A-436E-834B-6373EA36DEEE} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
{7BC22A4A-15D2-44C2-AB45-049F0FB562FA} = {8A3D00B8-1CCF-4BE6-A060-11104CE2D9CE}
{A7994A41-CAF8-47A7-8975-F101F75B5BC1} = {8A3D00B8-1CCF-4BE6-A060-11104CE2D9CE}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2D10D020-6770-47CA-BB8D-2C23FE3AE071}
Expand Down
3 changes: 3 additions & 0 deletions build/dependencies.props
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
<MicrosoftAspNetCoreHttpPackageVersion>2.1.0-preview1-27845</MicrosoftAspNetCoreHttpPackageVersion>
<MicrosoftAspNetCoreTestingPackageVersion>2.1.0-preview1-27845</MicrosoftAspNetCoreTestingPackageVersion>
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.1.0-preview1-27845</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
<MicrosoftExtensionsConfigurationBinderPackageVersion>2.1.0-preview1-27845</MicrosoftExtensionsConfigurationBinderPackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.1.0-preview1-27845</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.1.0-preview1-27845</MicrosoftExtensionsDependencyInjectionPackageVersion>
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>2.1.0-preview1-27845</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>2.1.0-preview1-27845</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingPackageVersion>2.1.0-preview1-27845</MicrosoftExtensionsLoggingPackageVersion>
Expand Down
17 changes: 16 additions & 1 deletion samples/SampleApp/SampleApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,26 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="$(MicrosoftExtensionsConfigurationJsonPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
</ItemGroup>

<ItemGroup>
<Content Include="../../test/shared/TestCertificates/testCert.pfx" CopyToOutputDirectory="PreserveNewest" />
<Content Include="testCert.pfx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<ItemGroup>
<Content Update="appsettings.Development.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="appsettings.Production.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

</Project>
59 changes: 57 additions & 2 deletions samples/SampleApp/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@

using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Net;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -48,10 +50,31 @@ public static Task Main(string[] args)
{
factory.AddConsole();
})
.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
Copy link
Member

Choose a reason for hiding this comment

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

At least one of these appsettings files is required now, right?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, they're optional in the sample. The config is additive on top of the endpoints defined in code.

})
.UseKestrel((context, options) =>
{
if (context.HostingEnvironment.IsDevelopment())
{
ShowConfig(context.Configuration);
}

var basePort = context.Configuration.GetValue<int?>("BASE_PORT") ?? 5000;

options.ConfigureEndpointDefaults(opt =>
{
opt.Protocols = HttpProtocols.Http1;
});

options.ConfigureHttpsDefaults(httpsOptions =>
{
httpsOptions.SslProtocols = SslProtocols.Tls12;
});

// Run callbacks on the transport thread
options.ApplicationSchedulingMode = SchedulingMode.Inline;

Expand All @@ -71,11 +94,34 @@ public static Task Main(string[] args)

options.ListenLocalhost(basePort + 2, listenOptions =>
{
listenOptions.UseHttps("testCert.pfx", "testPassword");
// Use default dev cert
listenOptions.UseHttps();
});

options.ListenAnyIP(basePort + 3);

options.ListenAnyIP(basePort + 4, listenOptions =>
{
listenOptions.UseHttps(StoreName.My, "aspnet.test", allowInvalid: true);
});

options
.Configure()
.Endpoint(IPAddress.Loopback, basePort + 5)
.LocalhostEndpoint(basePort + 6)
.Load();

options
.Configure(context.Configuration.GetSection("Kestrel"))
.Endpoint("NamedEndpoint", opt =>
{
opt.ListenOptions.Protocols = HttpProtocols.Http1;
})
.Endpoint("NamedHttpsEndpoint", opt =>
{
opt.HttpsOptions.SslProtocols = SslProtocols.Tls12;
});

options.UseSystemd();

// The following section should be used to demo sockets
Expand All @@ -96,5 +142,14 @@ public static Task Main(string[] args)

return hostBuilder.Build().RunAsync();
}

private static void ShowConfig(IConfiguration config)
{
foreach (var pair in config.GetChildren())
{
Console.WriteLine($"{pair.Path} - {pair.Value}");
ShowConfig(pair);
}
}
}
}
15 changes: 15 additions & 0 deletions samples/SampleApp/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"Kestrel": {
"Endpoints": {
"NamedEndpoint": { "Url": "http://localhost:6000" },
"NamedHttpsEndpoint": {
"Url": "https://localhost:6443",
"Certificate": {
"Subject": "aspnet.test",
"Store": "My",
"AllowInvalid": true
}
}
}
}
}
14 changes: 14 additions & 0 deletions samples/SampleApp/appsettings.Production.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"Kestrel": {
"Endpoints": {
"NamedEndpoint": { "Url": "http://*:6000" },
"NamedHttpsEndpoint": {
"Url": "https://*:6443",
"Certificate": {
"Path": "testCert.pfx",
"Password": "testPassword"
}
}
}
}
}
6 changes: 6 additions & 0 deletions samples/SampleApp/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"Kestrel": {
"Endpoints": {
}
}
}
92 changes: 92 additions & 0 deletions samples/SystemdTestApp/Startup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// 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;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace SystemdTestApp
{
public class Startup
{
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
var logger = loggerFactory.CreateLogger("Default");

app.Run(async context =>
{
var connectionFeature = context.Connection;
logger.LogDebug($"Peer: {connectionFeature.RemoteIpAddress?.ToString()}:{connectionFeature.RemotePort}"
+ $"{Environment.NewLine}"
+ $"Sock: {connectionFeature.LocalIpAddress?.ToString()}:{connectionFeature.LocalPort}");

var response = $"hello, world{Environment.NewLine}";
context.Response.ContentLength = response.Length;
context.Response.ContentType = "text/plain";
await context.Response.WriteAsync(response);
});
}

public static Task Main(string[] args)
{
TaskScheduler.UnobservedTaskException += (sender, e) =>
{
Console.WriteLine("Unobserved exception: {0}", e.Exception);
};

var hostBuilder = new WebHostBuilder()
.ConfigureLogging((_, factory) =>
{
factory.AddConsole();
})
.UseKestrel((context, options) =>
{
var basePort = context.Configuration.GetValue<int?>("BASE_PORT") ?? 5000;

// Run callbacks on the transport thread
options.ApplicationSchedulingMode = SchedulingMode.Inline;

options.Listen(IPAddress.Loopback, basePort, listenOptions =>
{
// Uncomment the following to enable Nagle's algorithm for this endpoint.
//listenOptions.NoDelay = false;

listenOptions.UseConnectionLogging();
});

options.Listen(IPAddress.Loopback, basePort + 1, listenOptions =>
{
listenOptions.UseHttps("testCert.pfx", "testPassword");
listenOptions.UseConnectionLogging();
});

options.UseSystemd();

// The following section should be used to demo sockets
//options.ListenUnixSocket("/tmp/kestrel-test.sock");
})
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>();

if (string.Equals(Process.GetCurrentProcess().Id.ToString(), Environment.GetEnvironmentVariable("LISTEN_PID")))
{
// Use libuv if activated by systemd, since that's currently the only transport that supports being passed a socket handle.
hostBuilder.UseLibuv(options =>
{
// Uncomment the following line to change the default number of libuv threads for all endpoints.
// options.ThreadCount = 4;
});
}

return hostBuilder.Build().RunAsync();
}
}
}
23 changes: 23 additions & 0 deletions samples/SystemdTestApp/SystemdTestApp.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFrameworks>netcoreapp2.1;netcoreapp2.0;net461</TargetFrameworks>
<IsPackable>false</IsPackable>
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Kestrel\Kestrel.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
</ItemGroup>

<ItemGroup>
<Content Include="testCert.pfx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

</Project>
Binary file added samples/SystemdTestApp/testCert.pfx
Binary file not shown.
15 changes: 15 additions & 0 deletions src/Kestrel.Core/CoreStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -480,4 +480,19 @@
<data name="ServiceCertificateRequired" xml:space="preserve">
<value>The server certificate parameter is required.</value>
</data>
<data name="BindingToDefaultAddresses" xml:space="preserve">
<value>No listening endpoints were configured. Binding to {address0} and {address1} by default.</value>
</data>
<data name="CertNotFoundInStore" xml:space="preserve">
<value>The requested certificate {subject} could not be found in {storeLocation}/{storeName} with AllowInvalid setting: {allowInvalid}.</value>
</data>
<data name="EndpointMissingUrl" xml:space="preserve">
<value>The endpoint {endpointName} is missing the required 'Url' parameter.</value>
</data>
<data name="NoCertSpecifiedNoDevelopmentCertificateFound" xml:space="preserve">
<value>Unable to configure HTTPS endpoint. No server certificate was specified and the default developer certificate could not be found. Try running 'dotnet developercertificates https -t' to setup a developer certificate for use with localhost. For information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054</value>
</data>
<data name="MultipleCertificateSources" xml:space="preserve">
<value>The endpoint {endpointName} specified multiple certificate sources.</value>
</data>
</root>
26 changes: 26 additions & 0 deletions src/Kestrel.Core/EndpointConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// 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;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Https;
using Microsoft.Extensions.Configuration;

namespace Microsoft.AspNetCore.Server.Kestrel
{
public class EndpointConfiguration
{
internal EndpointConfiguration(bool isHttps, ListenOptions listenOptions, HttpsConnectionAdapterOptions httpsOptions, IConfigurationSection configSection)
{
IsHttps = isHttps;
ListenOptions = listenOptions ?? throw new ArgumentNullException(nameof(listenOptions));
HttpsOptions = httpsOptions ?? throw new ArgumentNullException(nameof(httpsOptions));
ConfigSection = configSection ?? throw new ArgumentNullException(nameof(configSection));
}

public bool IsHttps { get; }
public ListenOptions ListenOptions { get; }
public HttpsConnectionAdapterOptions HttpsOptions { get; }
public IConfigurationSection ConfigSection { get; }
}
}
Loading