Merge branch 'release' into dev

This commit is contained in:
Chris R 2016-04-15 16:10:01 -07:00
commit 9cb3345511
10 changed files with 154 additions and 133 deletions

View File

@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
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.AspNetCore.Hosting.Server.Features;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Server; using Microsoft.Net.Http.Server;
@ -94,7 +94,7 @@ namespace HotAddSample
var host = new WebHostBuilder() var host = new WebHostBuilder()
.UseDefaultHostingConfiguration(args) .UseDefaultHostingConfiguration(args)
.UseStartup<Startup>() .UseStartup<Startup>()
.UseServer("Microsoft.AspNetCore.Server.WebListener") .UseWebListener()
.Build(); .Build();
host.Run(); host.Run();

View File

@ -15,9 +15,6 @@ namespace SelfHostServer
{ {
public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory) public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory)
{ {
var listener = app.ServerFeatures.Get<WebListener>();
listener.AuthenticationManager.AuthenticationSchemes = AuthenticationSchemes.AllowAnonymous;
loggerfactory.AddConsole(LogLevel.Debug); loggerfactory.AddConsole(LogLevel.Debug);
app.Run(async context => app.Run(async context =>
@ -43,7 +40,10 @@ namespace SelfHostServer
var host = new WebHostBuilder() var host = new WebHostBuilder()
.UseDefaultHostingConfiguration(args) .UseDefaultHostingConfiguration(args)
.UseStartup<Startup>() .UseStartup<Startup>()
.UseServer("Microsoft.AspNetCore.Server.WebListener") .UseWebListener(options =>
{
options.Listener.AuthenticationManager.AuthenticationSchemes = AuthenticationSchemes.AllowAnonymous;
})
.Build(); .Build();
host.Run(); host.Run();

View File

@ -0,0 +1,38 @@
// Copyright (c) Microsoft Open Technologies, Inc.
// All Rights Reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
// NON-INFRINGEMENT.
// See the Apache 2 License for the specific language governing
// permissions and limitations under the License.
using System;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Server.WebListener.Internal
{
public class WebListenerOptionsSetup : IConfigureOptions<WebListenerOptions>
{
private ILoggerFactory _loggerFactory;
public WebListenerOptionsSetup(ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
}
public void Configure(WebListenerOptions options)
{
options.Listener = new Microsoft.Net.Http.Server.WebListener(_loggerFactory);
}
}
}

View File

@ -21,14 +21,15 @@ using System.Diagnostics.Contracts;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Features;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Server; using Microsoft.Net.Http.Server;
namespace Microsoft.AspNetCore.Server.WebListener namespace Microsoft.AspNetCore.Server.WebListener
{ {
internal class MessagePump : IServer public class MessagePump : IServer
{ {
private static readonly int DefaultMaxAccepts = 5 * Environment.ProcessorCount; private static readonly int DefaultMaxAccepts = 5 * Environment.ProcessorCount;
@ -44,25 +45,32 @@ namespace Microsoft.AspNetCore.Server.WebListener
private bool _stopping; private bool _stopping;
private int _outstandingRequests; private int _outstandingRequests;
private ManualResetEvent _shutdownSignal; private ManualResetEvent _shutdownSignal;
internal MessagePump(Microsoft.Net.Http.Server.WebListener listener, ILoggerFactory loggerFactory, IFeatureCollection features) private readonly ServerAddressesFeature _serverAddresses;
public MessagePump(IOptions<WebListenerOptions> options, ILoggerFactory loggerFactory)
{ {
if (features == null) if (options == null)
{ {
throw new ArgumentNullException(nameof(features)); throw new ArgumentNullException(nameof(options));
}
if (loggerFactory == null)
{
throw new ArgumentNullException(nameof(loggerFactory));
} }
Contract.Assert(listener != null); _listener = options.Value?.Listener ?? new Microsoft.Net.Http.Server.WebListener(loggerFactory);
_listener = listener;
_logger = LogHelper.CreateLogger(loggerFactory, typeof(MessagePump)); _logger = LogHelper.CreateLogger(loggerFactory, typeof(MessagePump));
Features = features; Features = new FeatureCollection();
_serverAddresses = new ServerAddressesFeature();
Features.Set<IServerAddressesFeature>(_serverAddresses);
_processRequest = new Action<object>(ProcessRequestAsync); _processRequest = new Action<object>(ProcessRequestAsync);
_maxAccepts = DefaultMaxAccepts; _maxAccepts = DefaultMaxAccepts;
_shutdownSignal = new ManualResetEvent(false); _shutdownSignal = new ManualResetEvent(false);
} }
internal Microsoft.Net.Http.Server.WebListener Listener public Microsoft.Net.Http.Server.WebListener Listener
{ {
get { return _listener; } get { return _listener; }
} }
@ -94,13 +102,7 @@ namespace Microsoft.AspNetCore.Server.WebListener
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
} }
var addressesFeature = Features.Get<IServerAddressesFeature>(); ParseAddresses(_serverAddresses.Addresses, Listener);
if (addressesFeature == null)
{
throw new InvalidOperationException($"{nameof(IServerAddressesFeature)} is missing.");
}
ParseAddresses(addressesFeature.Addresses, Listener);
// Can't call Start twice // Can't call Start twice
Contract.Assert(_application == null); Contract.Assert(_application == null);

View File

@ -1,89 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc.
// All Rights Reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
// NON-INFRINGEMENT.
// See the Apache 2 License for the specific language governing
// permissions and limitations under the License.
// -----------------------------------------------------------------------
// <copyright file="ServerFactory.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
// Copyright 2011-2012 Katana contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Features;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Server.WebListener
{
/// <summary>
/// Implements the setup process for this server.
/// </summary>
public class ServerFactory : IServerFactory
{
private ILoggerFactory _loggerFactory;
public ServerFactory(ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
}
/// <summary>
/// Creates a configurable instance of the server.
/// </summary>
/// <param name="configuration"></param>
/// <returns>The server. Invoke Dispose to shut down.</returns>
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposed by caller")]
public IServer CreateServer(IConfiguration configuration)
{
Microsoft.Net.Http.Server.WebListener listener = new Microsoft.Net.Http.Server.WebListener(_loggerFactory);
var serverFeatures = new FeatureCollection();
serverFeatures.Set(listener);
serverFeatures.Set(SplitAddresses(configuration));
return new MessagePump(listener, _loggerFactory, serverFeatures);
}
private IServerAddressesFeature SplitAddresses(IConfiguration config)
{
var addressesFeature = new ServerAddressesFeature();
if (config != null && !string.IsNullOrEmpty(config["server.urls"]))
{
var urls = config["server.urls"];
foreach (var value in urls.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
{
addressesFeature.Addresses.Add(value);
}
}
return addressesFeature;
}
}
}

View File

@ -0,0 +1,69 @@
// Copyright (c) Microsoft Open Technologies, Inc.
// All Rights Reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
// NON-INFRINGEMENT.
// See the Apache 2 License for the specific language governing
// permissions and limitations under the License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Server.WebListener;
using Microsoft.AspNetCore.Server.WebListener.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Hosting
{
public static class WebHostBuilderWebListenerExtensions
{
/// <summary>
/// Specify WebListener as the server to be used by the web host.
/// </summary>
/// <param name="hostBuilder">
/// The Microsoft.AspNetCore.Hosting.IWebHostBuilder to configure.
/// </param>
/// <returns>
/// The Microsoft.AspNetCore.Hosting.IWebHostBuilder.
/// </returns>
public static IWebHostBuilder UseWebListener(this IWebHostBuilder hostBuilder)
{
return hostBuilder.ConfigureServices(services => services.AddSingleton<IServer, MessagePump>());
}
/// <summary>
/// Specify WebListener as the server to be used by the web host.
/// </summary>
/// <param name="hostBuilder">
/// The Microsoft.AspNetCore.Hosting.IWebHostBuilder to configure.
/// </param>
/// <param name="options">
/// A callback to configure WebListener options.
/// </param>
/// <returns>
/// The Microsoft.AspNetCore.Hosting.IWebHostBuilder.
/// </returns>
public static IWebHostBuilder UseWebListener(this IWebHostBuilder hostBuilder, Action<WebListenerOptions> options)
{
hostBuilder.ConfigureServices(services =>
{
services.AddTransient<IConfigureOptions<WebListenerOptions>, WebListenerOptionsSetup>();
services.Configure(options);
});
return hostBuilder.UseWebListener();
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Open Technologies, Inc. // Copyright (c) Microsoft Open Technologies, Inc.
// All Rights Reserved // All Rights Reserved
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
@ -15,13 +15,15 @@
// See the Apache 2 License for the specific language governing // See the Apache 2 License for the specific language governing
// permissions and limitations under the License. // permissions and limitations under the License.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNetCore.Server.Features; using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.Server.WebListener namespace Microsoft.AspNetCore.Server.WebListener
{ {
internal class ServerAddressesFeature : IServerAddressesFeature public class WebListenerOptions
{ {
public ICollection<string> Addresses { get; } = new List<string>(); public Microsoft.Net.Http.Server.WebListener Listener { get; set; } = new Microsoft.Net.Http.Server.WebListener();
} }
} }

View File

@ -24,6 +24,8 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Server; using Microsoft.Net.Http.Server;
using Xunit; using Xunit;
@ -187,13 +189,11 @@ namespace Microsoft.AspNetCore.Server.WebListener
var dynamicServer = Utilities.CreateHttpServerReturnRoot("/", out root, app); var dynamicServer = Utilities.CreateHttpServerReturnRoot("/", out root, app);
dynamicServer.Dispose(); dynamicServer.Dispose();
var rootUri = new Uri(root); var rootUri = new Uri(root);
var factory = new ServerFactory(loggerFactory: null); var server = new MessagePump(Options.Create(new WebListenerOptions()), new LoggerFactory());
var server = factory.CreateServer(configuration: null);
var listener = server.Features.Get<Microsoft.Net.Http.Server.WebListener>();
foreach (string path in new[] { "/", "/11", "/2/3", "/2", "/11/2" }) foreach (string path in new[] { "/", "/11", "/2/3", "/2", "/11/2" })
{ {
listener.UrlPrefixes.Add(UrlPrefix.Create(rootUri.Scheme, rootUri.Host, rootUri.Port, path)); server.Listener.UrlPrefixes.Add(UrlPrefix.Create(rootUri.Scheme, rootUri.Host, rootUri.Port, path));
} }
server.Start(new DummyApplication(app)); server.Start(new DummyApplication(app));

View File

@ -26,6 +26,8 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Server; using Microsoft.Net.Http.Server;
using Xunit; using Xunit;
@ -253,11 +255,9 @@ namespace Microsoft.AspNetCore.Server.WebListener
string address; string address;
using (Utilities.CreateHttpServer(out address, httpContext => Task.FromResult(0))) { } using (Utilities.CreateHttpServer(out address, httpContext => Task.FromResult(0))) { }
var factory = new ServerFactory(loggerFactory: null); var server = new MessagePump(Options.Create(new WebListenerOptions()), new LoggerFactory());
var server = factory.CreateServer(configuration: null); server.Listener.UrlPrefixes.Add(UrlPrefix.Create(address));
var listener = server.Features.Get<Microsoft.Net.Http.Server.WebListener>(); server.Listener.SetRequestQueueLimit(1001);
listener.UrlPrefixes.Add(UrlPrefix.Create(address));
listener.SetRequestQueueLimit(1001);
using (server) using (server)
{ {

View File

@ -17,8 +17,10 @@
using System; using System;
using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Features; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Server; using Microsoft.Net.Http.Server;
namespace Microsoft.AspNetCore.Server.WebListener namespace Microsoft.AspNetCore.Server.WebListener
@ -53,7 +55,6 @@ namespace Microsoft.AspNetCore.Server.WebListener
internal static IServer CreateDynamicHttpServer(string basePath, AuthenticationSchemes authType, out string root, out string baseAddress, RequestDelegate app) internal static IServer CreateDynamicHttpServer(string basePath, AuthenticationSchemes authType, out string root, out string baseAddress, RequestDelegate app)
{ {
var factory = new ServerFactory(loggerFactory: null);
lock (PortLock) lock (PortLock)
{ {
while (NextPort < MaxPort) while (NextPort < MaxPort)
@ -64,10 +65,9 @@ namespace Microsoft.AspNetCore.Server.WebListener
root = prefix.Scheme + "://" + prefix.Host + ":" + prefix.Port; root = prefix.Scheme + "://" + prefix.Host + ":" + prefix.Port;
baseAddress = prefix.ToString(); baseAddress = prefix.ToString();
var server = factory.CreateServer(configuration: null); var server = new MessagePump(Options.Create(new WebListenerOptions()), new LoggerFactory());
var listener = server.Features.Get<Microsoft.Net.Http.Server.WebListener>(); server.Features.Get<IServerAddressesFeature>().Addresses.Add(baseAddress);
listener.UrlPrefixes.Add(prefix); server.Listener.AuthenticationManager.AuthenticationSchemes = authType;
listener.AuthenticationManager.AuthenticationSchemes = authType;
try try
{ {
server.Start(new DummyApplication(app)); server.Start(new DummyApplication(app));
@ -89,8 +89,7 @@ namespace Microsoft.AspNetCore.Server.WebListener
internal static IServer CreateServer(string scheme, string host, int port, string path, RequestDelegate app) internal static IServer CreateServer(string scheme, string host, int port, string path, RequestDelegate app)
{ {
var factory = new ServerFactory(loggerFactory: null); var server = new MessagePump(Options.Create(new WebListenerOptions()), new LoggerFactory());
var server = factory.CreateServer(configuration: null);
server.Features.Get<IServerAddressesFeature>().Addresses.Add(UrlPrefix.Create(scheme, host, port, path).ToString()); server.Features.Get<IServerAddressesFeature>().Addresses.Add(UrlPrefix.Create(scheme, host, port, path).ToString());
server.Start(new DummyApplication(app)); server.Start(new DummyApplication(app));
return server; return server;