#1875 Add Configuration support and tests.
This commit is contained in:
parent
3c731ceb13
commit
c6e228d176
|
|
@ -71,6 +71,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.Kestrel.Tests", "test\Microsoft.AspNetCore.Server.Kestrel.Tests\Microsoft.AspNetCore.Server.Kestrel.Tests.csproj", "{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{FD3692F8-F5C7-49A5-8D69-29F8A87A9DB7}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
build\common.props = build\common.props
|
||||
build\dependencies.props = build\dependencies.props
|
||||
build\Key.snk = build\Key.snk
|
||||
build\repo.props = build\repo.props
|
||||
build\repo.targets = build\repo.targets
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -270,5 +279,6 @@ Global
|
|||
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
|
||||
{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
|
||||
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
|
||||
{FD3692F8-F5C7-49A5-8D69-29F8A87A9DB7} = {7972A5D6-3385-4127-9277-428506DD44FF}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -0,0 +1,116 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Microsoft.AspNetCore.Certificates.Configuration;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.Options.Infrastructure;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Internal
|
||||
{
|
||||
public class ConfigureDefaultKestrelServerOptions : ConfigureDefaultOptions<KestrelServerOptions>
|
||||
{
|
||||
private const string DefaultCertificateSubjectName = "CN=localhost";
|
||||
private const string DevelopmentSSLCertificateName = "localhost";
|
||||
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
private readonly IConfiguration _configurationRoot;
|
||||
private readonly ILoggerFactory _loggerFactory;
|
||||
|
||||
public ConfigureDefaultKestrelServerOptions(
|
||||
IServiceProvider services,
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
IConfiguration configurationRoot,
|
||||
ILoggerFactory loggerFactory)
|
||||
{
|
||||
_services = services;
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_configurationRoot = configurationRoot;
|
||||
_loggerFactory = loggerFactory;
|
||||
}
|
||||
|
||||
public override void Configure(string name, KestrelServerOptions options)
|
||||
{
|
||||
// Don't assume KestrelServerOptionsSetup has already set the services. Needed for UseHttps.
|
||||
options.ApplicationServices = _services;
|
||||
BindConfiguration(options);
|
||||
}
|
||||
|
||||
private void BindConfiguration(KestrelServerOptions options)
|
||||
{
|
||||
var certificateLoader = new CertificateLoader(_configurationRoot.GetSection("Certificates"), _loggerFactory, _hostingEnvironment.EnvironmentName);
|
||||
|
||||
foreach (var endPoint in _configurationRoot.GetSection("Microsoft:AspNetCore:Server:Kestrel:EndPoints").GetChildren())
|
||||
{
|
||||
BindEndPoint(options, endPoint, certificateLoader);
|
||||
}
|
||||
}
|
||||
|
||||
private void BindEndPoint(
|
||||
KestrelServerOptions options,
|
||||
IConfigurationSection endPoint,
|
||||
CertificateLoader certificateLoader)
|
||||
{
|
||||
var configAddress = endPoint.GetValue<string>("Address");
|
||||
var configPort = endPoint.GetValue<string>("Port");
|
||||
|
||||
if (!IPAddress.TryParse(configAddress, out var address))
|
||||
{
|
||||
throw new InvalidOperationException(KestrelStrings.FormatInvalidIp(configAddress));
|
||||
}
|
||||
|
||||
if (!int.TryParse(configPort, out var port))
|
||||
{
|
||||
throw new InvalidOperationException(KestrelStrings.FormatInvalidPort(configPort));
|
||||
}
|
||||
|
||||
options.Listen(address, port, listenOptions =>
|
||||
{
|
||||
var certificateConfig = endPoint.GetSection("Certificate");
|
||||
X509Certificate2 certificate = null;
|
||||
if (certificateConfig.Exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
certificate = certificateLoader.Load(certificateConfig).FirstOrDefault();
|
||||
}
|
||||
catch (KeyNotFoundException) when (certificateConfig.Value.Equals(DevelopmentSSLCertificateName, StringComparison.Ordinal) && _hostingEnvironment.IsDevelopment())
|
||||
{
|
||||
var storeLoader = new CertificateStoreLoader();
|
||||
certificate = storeLoader.Load(DefaultCertificateSubjectName, "My", StoreLocation.CurrentUser, validOnly: false) ??
|
||||
storeLoader.Load(DefaultCertificateSubjectName, "My", StoreLocation.LocalMachine, validOnly: false);
|
||||
|
||||
if (certificate == null)
|
||||
{
|
||||
var logger = _loggerFactory.CreateLogger("Microsoft.AspNetCore.Server.Kestrel.KestrelServerConfigureOptions");
|
||||
logger.LogError(KestrelStrings.NoCertFoundLog);
|
||||
}
|
||||
}
|
||||
|
||||
if (certificate == null)
|
||||
{
|
||||
throw new InvalidOperationException(KestrelStrings.FormatNoCertForEndpoint(endPoint.Key));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException(KestrelStrings.UnableToConfigureHttps, ex);
|
||||
}
|
||||
|
||||
listenOptions.UseHttps(certificate);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="InvalidIp" xml:space="preserve">
|
||||
<value>Invalid IP address in configuration: {configAddress}.</value>
|
||||
</data>
|
||||
<data name="InvalidPort" xml:space="preserve">
|
||||
<value>Invalid port in configuration: {configPort}.</value>
|
||||
</data>
|
||||
<data name="NoCertForEndpoint" xml:space="preserve">
|
||||
<value>No certificate found for endpoint {endPoint}.</value>
|
||||
</data>
|
||||
<data name="UnableToConfigureHttps" xml:space="preserve">
|
||||
<value>Unable to configure HTTPS endpoint. For information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.</value>
|
||||
</data>
|
||||
<data name="NoCertFoundLog" xml:space="preserve">
|
||||
<value>No HTTPS certificate was found for development. For information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core Kestrel cross-platform web server.</Description>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFrameworks>netstandard2.0;netcoreapp2.0</TargetFrameworks>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;kestrel</PackageTags>
|
||||
<NoWarn>CS1591;$(NoWarn)</NoWarn>
|
||||
|
|
@ -12,11 +12,14 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Certificates.Configuration.Sources" Version="$(AspNetCoreVersion)" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(AspNetCoreVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="$(AspNetCoreVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.AspNetCore.Server.Kestrel.Core\Microsoft.AspNetCore.Server.Kestrel.Core.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.AspNetCore.Server.Kestrel.Https\Microsoft.AspNetCore.Server.Kestrel.Https.csproj" />
|
||||
<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>
|
||||
|
|
|
|||
100
src/Microsoft.AspNetCore.Server.Kestrel/Properties/KestrelStrings.Designer.cs
generated
Normal file
100
src/Microsoft.AspNetCore.Server.Kestrel/Properties/KestrelStrings.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
// <auto-generated />
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel
|
||||
{
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
|
||||
internal static class KestrelStrings
|
||||
{
|
||||
private static readonly ResourceManager _resourceManager
|
||||
= new ResourceManager("Microsoft.AspNetCore.Server.Kestrel.KestrelStrings", typeof(KestrelStrings).GetTypeInfo().Assembly);
|
||||
|
||||
/// <summary>
|
||||
/// Invalid IP address in configuration: {configAddress}.
|
||||
/// </summary>
|
||||
internal static string InvalidIp
|
||||
{
|
||||
get => GetString("InvalidIp");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invalid IP address in configuration: {configAddress}.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidIp(object configAddress)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("InvalidIp", "configAddress"), configAddress);
|
||||
|
||||
/// <summary>
|
||||
/// Invalid port in configuration: {configPort}.
|
||||
/// </summary>
|
||||
internal static string InvalidPort
|
||||
{
|
||||
get => GetString("InvalidPort");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invalid port in configuration: {configPort}.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidPort(object configPort)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("InvalidPort", "configPort"), configPort);
|
||||
|
||||
/// <summary>
|
||||
/// No certificate found for endpoint {endPoint}.
|
||||
/// </summary>
|
||||
internal static string NoCertForEndpoint
|
||||
{
|
||||
get => GetString("NoCertForEndpoint");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// No certificate found for endpoint {endPoint}.
|
||||
/// </summary>
|
||||
internal static string FormatNoCertForEndpoint(object endPoint)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("NoCertForEndpoint", "endPoint"), endPoint);
|
||||
|
||||
/// <summary>
|
||||
/// Unable to configure HTTPS endpoint. For information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.
|
||||
/// </summary>
|
||||
internal static string UnableToConfigureHttps
|
||||
{
|
||||
get => GetString("UnableToConfigureHttps");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unable to configure HTTPS endpoint. For information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.
|
||||
/// </summary>
|
||||
internal static string FormatUnableToConfigureHttps()
|
||||
=> GetString("UnableToConfigureHttps");
|
||||
|
||||
/// <summary>
|
||||
/// No HTTPS certificate was found for development. For information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.
|
||||
/// </summary>
|
||||
internal static string NoCertFoundLog
|
||||
{
|
||||
get => GetString("NoCertFoundLog");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// No HTTPS certificate was found for development. For information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.
|
||||
/// </summary>
|
||||
internal static string FormatNoCertFoundLog()
|
||||
=> GetString("NoCertFoundLog");
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
||||
System.Diagnostics.Debug.Assert(value != null);
|
||||
|
||||
if (formatterNames != null)
|
||||
{
|
||||
for (var i = 0; i < formatterNames.Length; i++)
|
||||
{
|
||||
value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}");
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,10 +3,12 @@
|
|||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Hosting.Server;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.Options.Infrastructure;
|
||||
|
||||
namespace Microsoft.AspNetCore.Hosting
|
||||
{
|
||||
|
|
@ -28,6 +30,9 @@ namespace Microsoft.AspNetCore.Hosting
|
|||
return hostBuilder.ConfigureServices(services =>
|
||||
{
|
||||
services.AddTransient<IConfigureOptions<KestrelServerOptions>, KestrelServerOptionsSetup>();
|
||||
// https://github.com/aspnet/DependencyInjection/issues/500
|
||||
services.AddTransient<IConfigureOptions<KestrelServerOptions>, ConfigureDefaults<KestrelServerOptions>>();
|
||||
services.AddTransient<ConfigureDefaultOptions<KestrelServerOptions>, ConfigureDefaultKestrelServerOptions>();
|
||||
services.AddSingleton<IServer, KestrelServer>();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,153 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.Options.Infrastructure;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||
{
|
||||
public class ConfigurationTests
|
||||
{
|
||||
private void ConfigureEchoAddress(IApplicationBuilder app)
|
||||
{
|
||||
app.Run(context =>
|
||||
{
|
||||
return context.Response.WriteAsync(context.Request.GetDisplayUrl());
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BindsKestrelToInvalidIp_FailsToStart()
|
||||
{
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseConfiguration(new ConfigurationBuilder().AddInMemoryCollection(new Dictionary<string, string>()
|
||||
{
|
||||
{ "Microsoft:AspNetCore:Server:Kestrel:Endpoints:0:Address", "ABCDEFGH" },
|
||||
{ "Microsoft:AspNetCore:Server:Kestrel:Endpoints:0:Port", "0" }
|
||||
}).Build())
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
// Microsoft.AspNetCore.dll does this
|
||||
services.AddTransient(typeof(IConfigureOptions<>), typeof(ConfigureDefaults<>));
|
||||
})
|
||||
.Configure(ConfigureEchoAddress);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() => hostBuilder.Build());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("127.0.0.1", "127.0.0.1")]
|
||||
[InlineData("::1", "[::1]")]
|
||||
public async Task BindsKestrelHttpEndPointFromConfiguration(string endPointAddress, string requestAddress)
|
||||
{
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseConfiguration(new ConfigurationBuilder().AddInMemoryCollection(new Dictionary<string, string>()
|
||||
{
|
||||
{ "Microsoft:AspNetCore:Server:Kestrel:Endpoints:0:Address", $"{endPointAddress}" },
|
||||
{ "Microsoft:AspNetCore:Server:Kestrel:Endpoints:0:Port", "0" }
|
||||
}).Build())
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
// Microsoft.AspNetCore.dll does this
|
||||
services.AddTransient(typeof(IConfigureOptions<>), typeof(ConfigureDefaults<>));
|
||||
})
|
||||
.Configure(ConfigureEchoAddress);
|
||||
|
||||
using (var webHost = hostBuilder.Start())
|
||||
{
|
||||
var port = GetWebHostPort(webHost);
|
||||
|
||||
Assert.NotEqual(5000, port); // Default port
|
||||
|
||||
Assert.NotEqual(0, port);
|
||||
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
var response = await client.GetStringAsync($"http://{requestAddress}:{port}");
|
||||
Assert.Equal($"http://{requestAddress}:{port}/", response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindsKestrelHttpsEndPointFromConfiguration_ReferencedCertificateFile()
|
||||
{
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseConfiguration(new ConfigurationBuilder().AddInMemoryCollection(new Dictionary<string, string>()
|
||||
{
|
||||
{ "Microsoft:AspNetCore:Server:Kestrel:Endpoints:0:Address", "127.0.0.1" },
|
||||
{ "Microsoft:AspNetCore:Server:Kestrel:Endpoints:0:Port", "0" },
|
||||
{ "Microsoft:AspNetCore:Server:Kestrel:Endpoints:0:Certificate", "TestCert" },
|
||||
{ "Certificates:TestCert:Source", "File" },
|
||||
{ "Certificates:TestCert:Path", "testCert.pfx" },
|
||||
{ "Certificates:TestCert:Password", "testPassword" }
|
||||
}).Build())
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
// Microsoft.AspNetCore.dll does this
|
||||
services.AddTransient(typeof(IConfigureOptions<>), typeof(ConfigureDefaults<>));
|
||||
})
|
||||
.Configure(ConfigureEchoAddress);
|
||||
|
||||
using (var webHost = hostBuilder.Start())
|
||||
{
|
||||
var port = GetWebHostPort(webHost);
|
||||
|
||||
var response = await HttpClientSlim.GetStringAsync($"https://127.0.0.1:{port}", validateCertificate: false);
|
||||
Assert.Equal($"https://127.0.0.1:{port}/", response);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindsKestrelHttpsEndPointFromConfiguration_InlineCertificateFile()
|
||||
{
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseConfiguration(new ConfigurationBuilder().AddInMemoryCollection(new Dictionary<string, string>()
|
||||
{
|
||||
{ "Microsoft:AspNetCore:Server:Kestrel:Endpoints:0:Address", "127.0.0.1" },
|
||||
{ "Microsoft:AspNetCore:Server:Kestrel:Endpoints:0:Port", "0" },
|
||||
{ "Microsoft:AspNetCore:Server:Kestrel:Endpoints:0:Certificate:Source", "File" },
|
||||
{ "Microsoft:AspNetCore:Server:Kestrel:Endpoints:0:Certificate:Path", "testCert.pfx" },
|
||||
{ "Microsoft:AspNetCore:Server:Kestrel:Endpoints:0:Certificate:Password", "testPassword" }
|
||||
}).Build())
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
// Microsoft.AspNetCore.dll does this
|
||||
services.AddTransient(typeof(IConfigureOptions<>), typeof(ConfigureDefaults<>));
|
||||
})
|
||||
.Configure(ConfigureEchoAddress);
|
||||
|
||||
using (var webHost = hostBuilder.Start())
|
||||
{
|
||||
var port = GetWebHostPort(webHost);
|
||||
|
||||
var response = await HttpClientSlim.GetStringAsync($"https://127.0.0.1:{port}", validateCertificate: false);
|
||||
Assert.Equal($"https://127.0.0.1:{port}/", response);
|
||||
}
|
||||
}
|
||||
|
||||
private static int GetWebHostPort(IWebHost webHost)
|
||||
=> webHost.ServerFeatures.Get<IServerAddressesFeature>().Addresses
|
||||
.Select(serverAddress => new Uri(serverAddress).Port)
|
||||
.Single();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue