Merge branch 'release' into dev
This commit is contained in:
commit
5e425b24ec
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Features
|
namespace Microsoft.AspNetCore.Hosting.Server.Features
|
||||||
{
|
{
|
||||||
public interface IServerAddressesFeature
|
public interface IServerAddressesFeature
|
||||||
{
|
{
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
// 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 Microsoft.Extensions.Configuration;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Hosting.Server
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a factory for creating servers.
|
|
||||||
/// </summary>
|
|
||||||
public interface IServerFactory
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Creates <see cref="IServer"/> based on the given configuration.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="configuration">An instance of <see cref="IConfiguration"/>.</param>
|
|
||||||
/// <returns>The created server.</returns>
|
|
||||||
IServer CreateServer(IConfiguration configuration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -7,7 +7,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal
|
||||||
{
|
{
|
||||||
internal static class ServerLoader
|
internal static class ServerLoader
|
||||||
{
|
{
|
||||||
internal static Type ResolveServerFactoryType(string assemblyName)
|
internal static Type ResolveServerType(string assemblyName)
|
||||||
{
|
{
|
||||||
var assembly = Assembly.Load(new AssemblyName(assemblyName));
|
var assembly = Assembly.Load(new AssemblyName(assemblyName));
|
||||||
if (assembly == null)
|
if (assembly == null)
|
||||||
|
|
@ -16,12 +16,12 @@ namespace Microsoft.AspNetCore.Hosting.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
var serverTypeInfo = assembly.DefinedTypes.Where(
|
var serverTypeInfo = assembly.DefinedTypes.Where(
|
||||||
t => t.ImplementedInterfaces.FirstOrDefault(interf => interf.Equals(typeof(IServerFactory))) != null)
|
t => t.ImplementedInterfaces.FirstOrDefault(interf => interf.Equals(typeof(IServer))) != null)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
|
|
||||||
if (serverTypeInfo == null)
|
if (serverTypeInfo == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"No server type found that implements IServerFactory in assembly: {assemblyName}.");
|
throw new InvalidOperationException($"No server type found that implements IServer in assembly: {assemblyName}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return serverTypeInfo.AsType();
|
return serverTypeInfo.AsType();
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,10 @@ using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Microsoft.AspNetCore.Hosting.Builder;
|
using Microsoft.AspNetCore.Hosting.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting.Server;
|
using Microsoft.AspNetCore.Hosting.Server;
|
||||||
|
using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||||
using Microsoft.AspNetCore.Hosting.Startup;
|
using Microsoft.AspNetCore.Hosting.Startup;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Server.Features;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
@ -39,8 +39,6 @@ namespace Microsoft.AspNetCore.Hosting.Internal
|
||||||
internal StartupMethods Startup { get; set; }
|
internal StartupMethods Startup { get; set; }
|
||||||
internal Type StartupType { get; set; }
|
internal Type StartupType { get; set; }
|
||||||
|
|
||||||
private IServerFactory ServerFactory { get; set; }
|
|
||||||
|
|
||||||
private IServer Server { get; set; }
|
private IServer Server { get; set; }
|
||||||
|
|
||||||
public WebHost(
|
public WebHost(
|
||||||
|
|
@ -209,14 +207,25 @@ namespace Microsoft.AspNetCore.Hosting.Internal
|
||||||
{
|
{
|
||||||
if (Server == null)
|
if (Server == null)
|
||||||
{
|
{
|
||||||
ServerFactory = _applicationServices.GetRequiredService<IServerFactory>();
|
Server = _applicationServices.GetRequiredService<IServer>();
|
||||||
Server = ServerFactory.CreateServer(_config);
|
|
||||||
|
|
||||||
var addresses = Server.Features?.Get<IServerAddressesFeature>()?.Addresses;
|
var addresses = Server.Features?.Get<IServerAddressesFeature>()?.Addresses;
|
||||||
if (addresses != null && !addresses.IsReadOnly && addresses.Count == 0)
|
if (addresses != null && !addresses.IsReadOnly && addresses.Count == 0)
|
||||||
{
|
{
|
||||||
// Provide a default address if there aren't any configured.
|
var urls = _config[WebHostDefaults.ServerUrlsKey];
|
||||||
addresses.Add("http://localhost:5000");
|
if (!string.IsNullOrEmpty(urls))
|
||||||
|
{
|
||||||
|
foreach (var value in urls.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
addresses.Add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addresses.Count == 0)
|
||||||
|
{
|
||||||
|
// Provide a default address if there aren't any configured.
|
||||||
|
addresses.Add("http://localhost:5000");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal
|
||||||
DetailedErrors = ParseBool(configuration, WebHostDefaults.DetailedErrorsKey);
|
DetailedErrors = ParseBool(configuration, WebHostDefaults.DetailedErrorsKey);
|
||||||
CaptureStartupErrors = ParseBool(configuration, WebHostDefaults.CaptureStartupErrorsKey);
|
CaptureStartupErrors = ParseBool(configuration, WebHostDefaults.CaptureStartupErrorsKey);
|
||||||
Environment = configuration[WebHostDefaults.EnvironmentKey];
|
Environment = configuration[WebHostDefaults.EnvironmentKey];
|
||||||
ServerFactoryAssembly = configuration[WebHostDefaults.ServerKey];
|
ServerAssembly = configuration[WebHostDefaults.ServerKey];
|
||||||
WebRoot = configuration[WebHostDefaults.WebRootKey];
|
WebRoot = configuration[WebHostDefaults.WebRootKey];
|
||||||
ContentRootPath = configuration[WebHostDefaults.ContentRootKey];
|
ContentRootPath = configuration[WebHostDefaults.ContentRootKey];
|
||||||
}
|
}
|
||||||
|
|
@ -36,7 +36,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal
|
||||||
|
|
||||||
public string Environment { get; set; }
|
public string Environment { get; set; }
|
||||||
|
|
||||||
public string ServerFactoryAssembly { get; set; }
|
public string ServerAssembly { get; set; }
|
||||||
|
|
||||||
public string WebRoot { get; set; }
|
public string WebRoot { get; set; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Hosting.Server.Features
|
||||||
|
{
|
||||||
|
public class ServerAddressesFeature : IServerAddressesFeature
|
||||||
|
{
|
||||||
|
public ICollection<string> Addresses { get; } = new List<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -222,11 +222,11 @@ namespace Microsoft.AspNetCore.Hosting
|
||||||
services.AddSingleton(defaultPlatformServices.Application);
|
services.AddSingleton(defaultPlatformServices.Application);
|
||||||
services.AddSingleton(defaultPlatformServices.Runtime);
|
services.AddSingleton(defaultPlatformServices.Runtime);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(_options.ServerFactoryAssembly))
|
if (!string.IsNullOrEmpty(_options.ServerAssembly))
|
||||||
{
|
{
|
||||||
// Add the server factory
|
// Add the server
|
||||||
var serverFactoryType = ServerLoader.ResolveServerFactoryType(_options.ServerFactoryAssembly);
|
var serverType = ServerLoader.ResolveServerType(_options.ServerAssembly);
|
||||||
services.AddSingleton(typeof(IServerFactory), serverFactoryType);
|
services.AddSingleton(typeof(IServer), serverType);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var configureServices in _configureServicesDelegates)
|
foreach (var configureServices in _configureServicesDelegates)
|
||||||
|
|
|
||||||
|
|
@ -107,27 +107,6 @@ namespace Microsoft.AspNetCore.Hosting
|
||||||
return hostBuilder.UseSetting(WebHostDefaults.ServerKey, assemblyName);
|
return hostBuilder.UseSetting(WebHostDefaults.ServerKey, assemblyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Specify the <see cref="IServerFactory"/> to be used by the web host.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hostBuilder">The <see cref="IWebHostBuilder"/> to configure.</param>
|
|
||||||
/// <param name="factory">The <see cref="IServerFactory"/> to be used.</param>
|
|
||||||
/// <returns>The <see cref="IWebHostBuilder"/>.</returns>
|
|
||||||
public static IWebHostBuilder UseServer(this IWebHostBuilder hostBuilder, IServerFactory factory)
|
|
||||||
{
|
|
||||||
if (factory == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(factory));
|
|
||||||
}
|
|
||||||
|
|
||||||
return hostBuilder.ConfigureServices(services =>
|
|
||||||
{
|
|
||||||
// It would be nicer if this was transient but we need to pass in the
|
|
||||||
// factory instance directly
|
|
||||||
services.AddSingleton(factory);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specify the server to be used by the web host.
|
/// Specify the server to be used by the web host.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -141,9 +120,12 @@ namespace Microsoft.AspNetCore.Hosting
|
||||||
throw new ArgumentNullException(nameof(server));
|
throw new ArgumentNullException(nameof(server));
|
||||||
}
|
}
|
||||||
|
|
||||||
// It would be nicer if this was transient but we need to pass in the
|
return hostBuilder.ConfigureServices(services =>
|
||||||
// server instance directly
|
{
|
||||||
return hostBuilder.UseServer(new ServerFactory(server));
|
// It would be nicer if this was transient but we need to pass in the
|
||||||
|
// factory instance directly
|
||||||
|
services.AddSingleton(server);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -222,17 +204,5 @@ namespace Microsoft.AspNetCore.Hosting
|
||||||
host.Start();
|
host.Start();
|
||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ServerFactory : IServerFactory
|
|
||||||
{
|
|
||||||
private readonly IServer _server;
|
|
||||||
|
|
||||||
public ServerFactory(IServer server)
|
|
||||||
{
|
|
||||||
_server = server;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IServer CreateServer(IConfiguration configuration) => _server;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Microsoft.AspNetCore.Server.Features;
|
using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Hosting
|
namespace Microsoft.AspNetCore.Hosting
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.Hosting.Tests
|
||||||
var config = new WebHostOptions(new ConfigurationBuilder().AddInMemoryCollection(parameters).Build());
|
var config = new WebHostOptions(new ConfigurationBuilder().AddInMemoryCollection(parameters).Build());
|
||||||
|
|
||||||
Assert.Equal("wwwroot", config.WebRoot);
|
Assert.Equal("wwwroot", config.WebRoot);
|
||||||
Assert.Equal("Microsoft.AspNetCore.Server.Kestrel", config.ServerFactoryAssembly);
|
Assert.Equal("Microsoft.AspNetCore.Server.Kestrel", config.ServerAssembly);
|
||||||
Assert.Equal("MyProjectReference", config.Application);
|
Assert.Equal("MyProjectReference", config.Application);
|
||||||
Assert.Equal("Development", config.Environment);
|
Assert.Equal("Development", config.Environment);
|
||||||
Assert.True(config.CaptureStartupErrors);
|
Assert.True(config.CaptureStartupErrors);
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,12 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting.Fakes;
|
using Microsoft.AspNetCore.Hosting.Fakes;
|
||||||
|
using Microsoft.AspNetCore.Hosting.Internal;
|
||||||
using Microsoft.AspNetCore.Hosting.Server;
|
using Microsoft.AspNetCore.Hosting.Server;
|
||||||
|
using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||||
using Microsoft.AspNetCore.Hosting.Startup;
|
using Microsoft.AspNetCore.Hosting.Startup;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Server.Features;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
@ -24,11 +25,10 @@ using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Hosting
|
namespace Microsoft.AspNetCore.Hosting
|
||||||
{
|
{
|
||||||
public class WebHostTests : IServerFactory
|
public class WebHostTests : IServer
|
||||||
{
|
{
|
||||||
private readonly IList<StartInstance> _startInstances = new List<StartInstance>();
|
private readonly IList<StartInstance> _startInstances = new List<StartInstance>();
|
||||||
private IFeatureCollection _featuresSupportedByThisHost = NewFeatureCollection();
|
private IFeatureCollection _featuresSupportedByThisHost = NewFeatureCollection();
|
||||||
private IFeatureCollection _instanceFeaturesSupportedByThisHost;
|
|
||||||
|
|
||||||
public IFeatureCollection Features
|
public IFeatureCollection Features
|
||||||
{
|
{
|
||||||
|
|
@ -41,14 +41,6 @@ namespace Microsoft.AspNetCore.Hosting
|
||||||
features[feature.Key] = feature.Value;
|
features[feature.Key] = feature.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_instanceFeaturesSupportedByThisHost != null)
|
|
||||||
{
|
|
||||||
foreach (var feature in _instanceFeaturesSupportedByThisHost)
|
|
||||||
{
|
|
||||||
features[feature.Key] = feature.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return features;
|
return features;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -57,8 +49,9 @@ namespace Microsoft.AspNetCore.Hosting
|
||||||
{
|
{
|
||||||
var stub = new StubFeatures();
|
var stub = new StubFeatures();
|
||||||
var features = new FeatureCollection();
|
var features = new FeatureCollection();
|
||||||
features[typeof(IHttpRequestFeature)] = stub;
|
features.Set<IHttpRequestFeature>(stub);
|
||||||
features[typeof(IHttpResponseFeature)] = stub;
|
features.Set<IHttpResponseFeature>(stub);
|
||||||
|
features.Set<IServerAddressesFeature>(new ServerAddressesFeature());
|
||||||
return features;
|
return features;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,7 +59,7 @@ namespace Microsoft.AspNetCore.Hosting
|
||||||
public void WebHostThrowsWithNoServer()
|
public void WebHostThrowsWithNoServer()
|
||||||
{
|
{
|
||||||
var ex = Assert.Throws<InvalidOperationException>(() => CreateBuilder().Build().Start());
|
var ex = Assert.Throws<InvalidOperationException>(() => CreateBuilder().Build().Start());
|
||||||
Assert.Equal("No service for type 'Microsoft.AspNetCore.Hosting.Server.IServerFactory' has been registered.", ex.Message);
|
Assert.Equal("No service for type 'Microsoft.AspNetCore.Hosting.Server.IServer' has been registered.", ex.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -138,7 +131,7 @@ namespace Microsoft.AspNetCore.Hosting
|
||||||
|
|
||||||
host.Dispose();
|
host.Dispose();
|
||||||
|
|
||||||
Assert.Equal(1, _startInstances[0].DisposeCalls);
|
Assert.Equal(2, _startInstances[0].DisposeCalls); // Once as the server, once from the DI Container
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -166,7 +159,7 @@ namespace Microsoft.AspNetCore.Hosting
|
||||||
// Wait on the host to shutdown
|
// Wait on the host to shutdown
|
||||||
lifetime.ApplicationStopped.WaitHandle.WaitOne();
|
lifetime.ApplicationStopped.WaitHandle.WaitOne();
|
||||||
|
|
||||||
Assert.Equal(1, _startInstances[0].DisposeCalls);
|
Assert.Equal(2, _startInstances[0].DisposeCalls); // Once as the server, once from the DI Container
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -493,13 +486,6 @@ namespace Microsoft.AspNetCore.Hosting
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IServer CreateServer(IConfiguration configuration)
|
|
||||||
{
|
|
||||||
_instanceFeaturesSupportedByThisHost = new FeatureCollection();
|
|
||||||
_instanceFeaturesSupportedByThisHost.Set<IServerAddressesFeature>(new ServerAddressesFeature());
|
|
||||||
return new FakeServer(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class StartInstance : IDisposable
|
private class StartInstance : IDisposable
|
||||||
{
|
{
|
||||||
public int DisposeCalls { get; set; }
|
public int DisposeCalls { get; set; }
|
||||||
|
|
@ -566,11 +552,6 @@ namespace Microsoft.AspNetCore.Hosting
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ServerAddressesFeature : IServerAddressesFeature
|
|
||||||
{
|
|
||||||
public ICollection<string> Addresses { get; } = new List<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class AllMessagesAreNeeded : ILoggerProvider, ILogger
|
private class AllMessagesAreNeeded : ILoggerProvider, ILogger
|
||||||
{
|
{
|
||||||
public bool IsEnabled(LogLevel logLevel) => true;
|
public bool IsEnabled(LogLevel logLevel) => true;
|
||||||
|
|
@ -671,24 +652,5 @@ namespace Microsoft.AspNetCore.Hosting
|
||||||
{
|
{
|
||||||
public string TraceIdentifier { get; set; }
|
public string TraceIdentifier { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FakeServer : IServer
|
|
||||||
{
|
|
||||||
private readonly WebHostTests _webHostTests;
|
|
||||||
|
|
||||||
public FakeServer(WebHostTests webHostTests)
|
|
||||||
{
|
|
||||||
_webHostTests = webHostTests;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IFeatureCollection Features => _webHostTests.Features;
|
|
||||||
|
|
||||||
public void Dispose() => _webHostTests.Dispose();
|
|
||||||
|
|
||||||
public void Start<TContext>(IHttpApplication<TContext> application)
|
|
||||||
{
|
|
||||||
_webHostTests.Start<TContext>(application);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue