Make hosting configuration consistent

This commit is contained in:
Pavel Krymets 2015-11-09 10:54:15 -08:00
parent 5bb737b6ad
commit 660f1cad10
8 changed files with 148 additions and 34 deletions

View File

@ -1,6 +1,7 @@
// 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.IO;
using Microsoft.AspNet.FileProviders;
using Microsoft.Extensions.Configuration;
@ -9,14 +10,14 @@ namespace Microsoft.AspNet.Hosting
{
public static class HostingEnvironmentExtensions
{
private const string OldEnvironmentKey = "ASPNET_ENV";
private const string EnvironmentKey = "Hosting:Environment";
private const string WebRootKey = "webroot";
public static void Initialize(this IHostingEnvironment hostingEnvironment, string applicationBasePath, IConfiguration config)
public static void Initialize(this IHostingEnvironment hostingEnvironment, string applicationBasePath, WebHostOptions options)
{
var webRoot = config?[WebRootKey];
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
var webRoot = options.WebRoot;
if (webRoot == null)
{
// Default to /wwwroot if it exists.
@ -43,7 +44,7 @@ namespace Microsoft.AspNet.Hosting
}
hostingEnvironment.WebRootFileProvider = new PhysicalFileProvider(hostingEnvironment.WebRootPath);
var environmentName = config?[EnvironmentKey] ?? config?[OldEnvironmentKey];
var environmentName = options.Environment;
hostingEnvironment.EnvironmentName = environmentName ?? hostingEnvironment.EnvironmentName;
}
}

View File

@ -24,11 +24,11 @@ namespace Microsoft.AspNet.Hosting.Internal
{
// This is defined by IIS's HttpPlatformHandler.
private static readonly string ServerPort = "HTTP_PLATFORM_PORT";
private static readonly string DetailedErrors = "Hosting:DetailedErrors";
private readonly IServiceCollection _applicationServiceCollection;
private readonly IStartupLoader _startupLoader;
private readonly ApplicationLifetime _applicationLifetime;
private readonly WebHostOptions _options;
private readonly IConfiguration _config;
private readonly bool _captureStartupErrors;
@ -47,6 +47,7 @@ namespace Microsoft.AspNet.Hosting.Internal
public HostingEngine(
IServiceCollection appServices,
IStartupLoader startupLoader,
WebHostOptions options,
IConfiguration config,
bool captureStartupErrors)
{
@ -66,6 +67,7 @@ namespace Microsoft.AspNet.Hosting.Internal
}
_config = config;
_options = options;
_applicationServiceCollection = appServices;
_startupLoader = startupLoader;
_captureStartupErrors = captureStartupErrors;
@ -226,9 +228,7 @@ namespace Microsoft.AspNet.Hosting.Internal
// Generate an HTML error page.
var runtimeEnv = _applicationServices.GetRequiredService<IRuntimeEnvironment>();
var hostingEnv = _applicationServices.GetRequiredService<IHostingEnvironment>();
var showDetailedErrors = hostingEnv.IsDevelopment()
|| string.Equals("true", _config[DetailedErrors], StringComparison.OrdinalIgnoreCase)
|| string.Equals("1", _config[DetailedErrors], StringComparison.OrdinalIgnoreCase);
var showDetailedErrors = hostingEnv.IsDevelopment() || _options.DetailedErrors;
var errorBytes = StartupExceptionPage.GenerateErrorHtml(showDetailedErrors, runtimeEnv, ex);
return context =>

View File

@ -12,6 +12,7 @@ namespace Microsoft.AspNet.Hosting
public class WebApplication
{
private const string HostingJsonFile = "hosting.json";
private const string EnvironmentVariablesPrefix = "ASPNET_";
private const string ConfigFileKey = "config";
public static void Run(string[] args)
@ -40,12 +41,7 @@ namespace Microsoft.AspNet.Hosting
var tempBuilder = new ConfigurationBuilder().AddCommandLine(args);
var tempConfig = tempBuilder.Build();
var configFilePath = tempConfig[ConfigFileKey] ?? HostingJsonFile;
var config = new ConfigurationBuilder()
.AddJsonFile(configFilePath, optional: true)
.AddEnvironmentVariables()
.AddCommandLine(args)
.Build();
var config = LoadHostingConfiguration(configFilePath, args);
var hostBuilder = new WebHostBuilder(config, captureStartupErrors: true);
if (startupType != null)
@ -81,5 +77,14 @@ namespace Microsoft.AspNet.Hosting
appLifetime.ApplicationStopping.WaitHandle.WaitOne();
}
}
internal static IConfiguration LoadHostingConfiguration(string configJsonPath, string[] args)
{
return new ConfigurationBuilder()
.AddJsonFile(configJsonPath, optional: true)
.AddEnvironmentVariables(prefix: EnvironmentVariablesPrefix)
.AddCommandLine(args)
.Build();
}
}
}

View File

@ -21,15 +21,10 @@ namespace Microsoft.AspNet.Hosting
{
public class WebHostBuilder
{
public const string OldApplicationKey = "app";
public const string ApplicationKey = "Hosting:Application";
public const string OldServerKey = "server";
public const string ServerKey = "Hosting:Server";
private readonly IHostingEnvironment _hostingEnvironment;
private readonly ILoggerFactory _loggerFactory;
private readonly IConfiguration _config;
private readonly WebHostOptions _options;
private Action<IServiceCollection> _configureServices;
@ -64,6 +59,7 @@ namespace Microsoft.AspNet.Hosting
_hostingEnvironment = new HostingEnvironment();
_loggerFactory = new LoggerFactory();
_config = config;
_options = new WebHostOptions(config);
_captureStartupErrors = captureStartupErrors;
}
@ -130,18 +126,18 @@ namespace Microsoft.AspNet.Hosting
var appEnvironment = hostingContainer.GetRequiredService<IApplicationEnvironment>();
var startupLoader = hostingContainer.GetRequiredService<IStartupLoader>();
_hostingEnvironment.Initialize(appEnvironment.ApplicationBasePath, _config);
var engine = new HostingEngine(hostingServices, startupLoader, _config, _captureStartupErrors);
_hostingEnvironment.Initialize(appEnvironment.ApplicationBasePath, _options);
var engine = new HostingEngine(hostingServices, startupLoader, _options, _config, _captureStartupErrors);
// Only one of these should be set, but they are used in priority
engine.Server = _server;
engine.ServerFactory = _serverFactory;
engine.ServerFactoryLocation = _config[ServerKey] ?? _config[OldServerKey] ?? _serverFactoryLocation;
engine.ServerFactoryLocation = _options.Server ?? _serverFactoryLocation;
// Only one of these should be set, but they are used in priority
engine.Startup = _startup;
engine.StartupType = _startupType;
engine.StartupAssemblyName = _startupAssemblyName ?? _config[ApplicationKey] ?? _config[OldApplicationKey] ?? appEnvironment.ApplicationName;
engine.StartupAssemblyName = _startupAssemblyName ?? _options.Application ?? appEnvironment.ApplicationName;
return engine;
}

View File

@ -0,0 +1,47 @@
// 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.Extensions.Configuration;
namespace Microsoft.AspNet.Hosting
{
public class WebHostOptions
{
private const string ApplicationKey = "app";
private const string DetailedErrorsKey = "detailedErrors";
private const string EnvironmentKey = "environment";
private const string ServerKey = "server";
private const string WebRootKey = "webroot";
private const string OldEnvironmentKey = "ENV";
public WebHostOptions()
{
}
public WebHostOptions(IConfiguration configuration)
{
if (configuration == null)
{
throw new ArgumentNullException(nameof(configuration));
}
Application = configuration[ApplicationKey];
DetailedErrors = string.Equals("true", configuration[DetailedErrorsKey], StringComparison.OrdinalIgnoreCase)
|| string.Equals("1", configuration[DetailedErrorsKey], StringComparison.OrdinalIgnoreCase);
Environment = configuration[EnvironmentKey] ?? configuration[OldEnvironmentKey];
Server = configuration[ServerKey];
WebRoot = configuration[WebRootKey];
}
public string Application { get; set; }
public bool DetailedErrors { get; set; }
public string Environment { get; set; }
public string Server { get; set; }
public string WebRoot { get; set; }
}
}

View File

@ -98,7 +98,7 @@ namespace Microsoft.AspNet.Hosting
{
var vals = new Dictionary<string, string>
{
{ "Hosting:Server", "Microsoft.AspNet.Hosting.Tests" }
{ "Server", "Microsoft.AspNet.Hosting.Tests" }
};
var builder = new ConfigurationBuilder()
@ -114,7 +114,7 @@ namespace Microsoft.AspNet.Hosting
{
var vals = new Dictionary<string, string>
{
{ "Hosting:Server", "Microsoft.AspNet.Hosting.Tests" },
{ "Server", "Microsoft.AspNet.Hosting.Tests" },
{ "HTTP_PLATFORM_PORT", "abc123" }
};
@ -132,7 +132,7 @@ namespace Microsoft.AspNet.Hosting
{
var vals = new Dictionary<string, string>
{
{ "Hosting:Server", "Microsoft.AspNet.Hosting.Tests" }
{ "Server", "Microsoft.AspNet.Hosting.Tests" }
};
var builder = new ConfigurationBuilder()
@ -250,7 +250,9 @@ namespace Microsoft.AspNet.Hosting
{
var vals = new Dictionary<string, string>
{
{ "ASPNET_ENV", "Staging" }
// Old key is actualy ASPNET_ENV but WebHostConfiguration expects environment
// variable names stripped from ASPNET_ prefix so using just ENV here
{ "ENV", "Staging" }
};
var builder = new ConfigurationBuilder()
@ -267,7 +269,7 @@ namespace Microsoft.AspNet.Hosting
{
var vals = new Dictionary<string, string>
{
{ "Hosting:Environment", "Staging" }
{ "Environment", "Staging" }
};
var builder = new ConfigurationBuilder()

View File

@ -129,7 +129,7 @@ namespace Microsoft.AspNet.Hosting
var vals = new Dictionary<string, string>
{
{ "server", "Microsoft.AspNet.Hosting.Tests" },
{ "Hosting:DetailedErrors", "true" },
{ "DetailedErrors", "true" },
};
var builder = new ConfigurationBuilder()
.AddInMemoryCollection(vals);

View File

@ -0,0 +1,63 @@
// 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;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Builder.Internal;
using Microsoft.AspNet.Hosting.Fakes;
using Microsoft.AspNet.Hosting.Startup;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.OptionsModel;
using Xunit;
namespace Microsoft.AspNet.Hosting.Tests
{
public class WebHostConfigurationTests
{
[Fact]
public void ReadsParametersCorrectly()
{
var parameters = new Dictionary<string, string>()
{
{"webroot", "wwwroot"},
{"server", "Microsoft.AspNet.Server.Kestrel"},
{"app", "MyProjectReference"},
{"environment", "Development"},
{"detailederrors", "true"},
};
var config = new WebHostOptions(new ConfigurationBuilder().AddInMemoryCollection(parameters).Build());
Assert.Equal("wwwroot", config.WebRoot);
Assert.Equal("Microsoft.AspNet.Server.Kestrel", config.Server);
Assert.Equal("MyProjectReference", config.Application);
Assert.Equal("Development", config.Environment);
Assert.Equal(true, config.DetailedErrors);
}
[Fact]
public void ReadsOldEnvKey()
{
var parameters = new Dictionary<string, string>() { { "ENV", "Development" } };
var config = new WebHostOptions(new ConfigurationBuilder().AddInMemoryCollection(parameters).Build());
Assert.Equal("Development", config.Environment);
}
[Theory]
[InlineData("1", true)]
[InlineData("0", false)]
public void AllowsNumberForDetailedErrors(string value, bool expected)
{
var parameters = new Dictionary<string, string>() { { "detailedErrors", value } };
var config = new WebHostOptions(new ConfigurationBuilder().AddInMemoryCollection(parameters).Build());
Assert.Equal(expected, config.DetailedErrors);
}
}
}