Ordering sensitive configuration #582
This commit is contained in:
parent
3ea44c6f75
commit
ae47bb21a6
|
|
@ -2,10 +2,8 @@
|
|||
// 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 Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting.Server;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Hosting
|
||||
|
|
@ -19,20 +17,6 @@ namespace Microsoft.AspNetCore.Hosting
|
|||
/// Builds an <see cref="IWebHost"/> which hosts a web application.
|
||||
/// </summary>
|
||||
IWebHost Build();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the raw settings to be used by the web host. Values specified here will override
|
||||
/// the configuration set by <see cref="UseConfiguration(IConfiguration)"/>.
|
||||
/// </summary>
|
||||
IDictionary<string, string> Settings { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Specify the <see cref="IConfiguration"/> to be used by the web host. If no configuration is
|
||||
/// provided to the builder, the default configuration will be used.
|
||||
/// </summary>
|
||||
/// <param name="configuration">The <see cref="IConfiguration"/> to be used.</param>
|
||||
/// <returns>The <see cref="IWebHostBuilder"/>.</returns>
|
||||
IWebHostBuilder UseConfiguration(IConfiguration configuration);
|
||||
|
||||
/// <summary>
|
||||
/// Specify the <see cref="IServerFactory"/> to be used by the web host.
|
||||
|
|
@ -63,11 +47,18 @@ namespace Microsoft.AspNetCore.Hosting
|
|||
IWebHostBuilder Configure(Action<IApplicationBuilder> configureApplication);
|
||||
|
||||
/// <summary>
|
||||
/// Add or replace a setting in <see cref="Settings"/>.
|
||||
/// Add or replace a setting in the configuration.
|
||||
/// </summary>
|
||||
/// <param name="key">The key of the setting to add or replace.</param>
|
||||
/// <param name="value">The value of the setting to add or replace.</param>
|
||||
/// <returns>The <see cref="IWebHostBuilder"/>.</returns>
|
||||
IWebHostBuilder UseSetting(string key, string value);
|
||||
|
||||
/// <summary>
|
||||
/// Get the setting value from the configuration.
|
||||
/// </summary>
|
||||
/// <param name="key">The key of the setting to look up.</param>
|
||||
/// <returns>The value the setting currently contains.</returns>
|
||||
string GetSetting(string key);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
// 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.Collections.Generic;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Microsoft.AspNetCore.Hosting.Internal
|
||||
{
|
||||
public static class IConfigurationExtensions
|
||||
{
|
||||
// Temporary until Configuration/issues/370 is implemented.
|
||||
public static IEnumerable<KeyValuePair<string, string>> GetFlattenedSettings(this IConfiguration configuration)
|
||||
{
|
||||
var stack = new Stack<IConfiguration>();
|
||||
stack.Push(configuration);
|
||||
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
var config = stack.Pop();
|
||||
var section = config as IConfigurationSection;
|
||||
|
||||
if (section != null)
|
||||
{
|
||||
yield return new KeyValuePair<string, string>(section.Path, section.Value);
|
||||
}
|
||||
|
||||
foreach (var child in config.GetChildren())
|
||||
{
|
||||
stack.Push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Microsoft.AspNetCore.Hosting
|
||||
namespace Microsoft.AspNetCore.Hosting.Internal
|
||||
{
|
||||
public class WebHostConfiguration
|
||||
{
|
||||
|
|
@ -2,7 +2,6 @@
|
|||
// 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.Diagnostics;
|
||||
using System.Runtime.Versioning;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
|
@ -28,7 +27,7 @@ namespace Microsoft.AspNetCore.Hosting
|
|||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
private readonly ILoggerFactory _loggerFactory;
|
||||
|
||||
private IConfiguration _config;
|
||||
private IConfiguration _config = new ConfigurationBuilder().AddInMemoryCollection().Build();
|
||||
private WebHostOptions _options;
|
||||
|
||||
private Action<IServiceCollection> _configureServices;
|
||||
|
|
@ -40,26 +39,12 @@ namespace Microsoft.AspNetCore.Hosting
|
|||
// Only one of these should be set
|
||||
private IServerFactory _serverFactory;
|
||||
|
||||
private IDictionary<string, string> _settings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public WebHostBuilder()
|
||||
{
|
||||
_hostingEnvironment = new HostingEnvironment();
|
||||
_loggerFactory = new LoggerFactory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the raw settings to be used by the web host. Values specified here will override
|
||||
/// the configuration set by <see cref="UseConfiguration(IConfiguration)"/>.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Settings
|
||||
{
|
||||
get
|
||||
{
|
||||
return _settings;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add or replace a setting in <see cref="Settings"/>.
|
||||
/// </summary>
|
||||
|
|
@ -68,20 +53,18 @@ namespace Microsoft.AspNetCore.Hosting
|
|||
/// <returns>The <see cref="IWebHostBuilder"/>.</returns>
|
||||
public IWebHostBuilder UseSetting(string key, string value)
|
||||
{
|
||||
_settings[key] = value;
|
||||
_config[key] = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specify the <see cref="IConfiguration"/> to be used by the web host. If no configuration is
|
||||
/// provided to the builder, the default configuration will be used.
|
||||
/// Get the setting value from the configuration.
|
||||
/// </summary>
|
||||
/// <param name="configuration">The <see cref="IConfiguration"/> to be used.</param>
|
||||
/// <returns>The <see cref="IWebHostBuilder"/>.</returns>
|
||||
public IWebHostBuilder UseConfiguration(IConfiguration configuration)
|
||||
/// <param name="key">The key of the setting to look up.</param>
|
||||
/// <returns>The value the setting currently contains.</returns>
|
||||
public string GetSetting(string key)
|
||||
{
|
||||
_config = configuration;
|
||||
return this;
|
||||
return _config[key];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -187,15 +170,6 @@ namespace Microsoft.AspNetCore.Hosting
|
|||
|
||||
private IServiceCollection BuildHostingServices()
|
||||
{
|
||||
// Apply the configuration settings
|
||||
var configuration = _config ?? WebHostConfiguration.GetDefault();
|
||||
|
||||
var mergedConfiguration = new ConfigurationBuilder()
|
||||
.Add(new IncludedConfigurationProvider(configuration))
|
||||
.AddInMemoryCollection(_settings)
|
||||
.Build();
|
||||
|
||||
_config = mergedConfiguration;
|
||||
_options = new WebHostOptions(_config);
|
||||
|
||||
var services = new ServiceCollection();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Hosting.Internal;
|
||||
using Microsoft.AspNetCore.Hosting.Server;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
|
|
@ -21,6 +22,16 @@ namespace Microsoft.AspNetCore.Hosting
|
|||
return builder.UseConfiguration(WebHostConfiguration.GetDefault(args));
|
||||
}
|
||||
|
||||
public static IWebHostBuilder UseConfiguration(this IWebHostBuilder builder, IConfiguration configuration)
|
||||
{
|
||||
foreach (var setting in configuration.GetFlattenedSettings())
|
||||
{
|
||||
builder.UseSetting(setting.Key, setting.Value);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static IWebHostBuilder UseCaptureStartupErrors(this IWebHostBuilder hostBuilder, bool captureStartupError)
|
||||
{
|
||||
return hostBuilder.UseSetting(WebHostDefaults.CaptureStartupErrorsKey, captureStartupError ? "true" : "false");
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.TestHost
|
|||
|
||||
public TestServer(IWebHostBuilder builder)
|
||||
{
|
||||
if (!builder.Settings.ContainsKey(WebHostDefaults.CaptureStartupErrorsKey))
|
||||
if (string.IsNullOrEmpty(builder.GetSetting(WebHostDefaults.CaptureStartupErrorsKey)))
|
||||
{
|
||||
builder.UseCaptureStartupErrors(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,9 +124,10 @@ namespace Microsoft.AspNetCore.Hosting
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void CaptureStartupErrorsByDefault()
|
||||
public void DefaultConfigurationCapturesStartupErrors()
|
||||
{
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
.UseDefaultConfiguration()
|
||||
.UseServer(new TestServer())
|
||||
.UseStartup<StartupBoom>();
|
||||
|
||||
|
|
@ -146,6 +147,98 @@ namespace Microsoft.AspNetCore.Hosting
|
|||
Assert.Equal("A public method named 'ConfigureProduction' or 'Configure' could not be found in the 'Microsoft.AspNetCore.Hosting.Fakes.StartupBoom' type.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CodeBasedSettingsCodeBasedOverride()
|
||||
{
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
.UseSetting(WebHostDefaults.ServerKey, "ServerA")
|
||||
.UseSetting(WebHostDefaults.ServerKey, "ServerB")
|
||||
.UseServer(new TestServer())
|
||||
.UseStartup<StartupNoServices>();
|
||||
|
||||
var host = (WebHost)hostBuilder.Build();
|
||||
|
||||
Assert.Equal("ServerB", host.ServerFactoryLocation);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CodeBasedSettingsConfigBasedOverride()
|
||||
{
|
||||
var settings = new Dictionary<string, string>
|
||||
{
|
||||
{ WebHostDefaults.ServerKey, "ServerB" }
|
||||
};
|
||||
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(settings)
|
||||
.Build();
|
||||
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
.UseSetting(WebHostDefaults.ServerKey, "ServerA")
|
||||
.UseConfiguration(config)
|
||||
.UseServer(new TestServer())
|
||||
.UseStartup<StartupNoServices>();
|
||||
|
||||
var host = (WebHost)hostBuilder.Build();
|
||||
|
||||
Assert.Equal("ServerB", host.ServerFactoryLocation);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConfigBasedSettingsCodeBasedOverride()
|
||||
{
|
||||
var settings = new Dictionary<string, string>
|
||||
{
|
||||
{ WebHostDefaults.ServerKey, "ServerA" }
|
||||
};
|
||||
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(settings)
|
||||
.Build();
|
||||
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
.UseConfiguration(config)
|
||||
.UseSetting(WebHostDefaults.ServerKey, "ServerB")
|
||||
.UseServer(new TestServer())
|
||||
.UseStartup<StartupNoServices>();
|
||||
|
||||
var host = (WebHost)hostBuilder.Build();
|
||||
|
||||
Assert.Equal("ServerB", host.ServerFactoryLocation);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConfigBasedSettingsConfigBasedOverride()
|
||||
{
|
||||
var settings = new Dictionary<string, string>
|
||||
{
|
||||
{ WebHostDefaults.ServerKey, "ServerA" }
|
||||
};
|
||||
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(settings)
|
||||
.Build();
|
||||
|
||||
var overrideSettings = new Dictionary<string, string>
|
||||
{
|
||||
{ WebHostDefaults.ServerKey, "ServerB" }
|
||||
};
|
||||
|
||||
var overrideConfig = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(overrideSettings)
|
||||
.Build();
|
||||
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
.UseConfiguration(config)
|
||||
.UseConfiguration(overrideConfig)
|
||||
.UseServer(new TestServer())
|
||||
.UseStartup<StartupNoServices>();
|
||||
|
||||
var host = (WebHost)hostBuilder.Build();
|
||||
|
||||
Assert.Equal("ServerB", host.ServerFactoryLocation);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UseEnvironmentIsNotOverriden()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue