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

View File

@ -15,9 +15,6 @@ namespace SelfHostServer
{
public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory)
{
var listener = app.ServerFeatures.Get<WebListener>();
listener.AuthenticationManager.AuthenticationSchemes = AuthenticationSchemes.AllowAnonymous;
loggerfactory.AddConsole(LogLevel.Debug);
app.Run(async context =>
@ -43,7 +40,10 @@ namespace SelfHostServer
var host = new WebHostBuilder()
.UseDefaultHostingConfiguration(args)
.UseStartup<Startup>()
.UseServer("Microsoft.AspNetCore.Server.WebListener")
.UseWebListener(options =>
{
options.Listener.AuthenticationManager.AuthenticationSchemes = AuthenticationSchemes.AllowAnonymous;
})
.Build();
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.Tasks;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Features;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Server;
namespace Microsoft.AspNetCore.Server.WebListener
{
internal class MessagePump : IServer
public class MessagePump : IServer
{
private static readonly int DefaultMaxAccepts = 5 * Environment.ProcessorCount;
@ -44,25 +45,32 @@ namespace Microsoft.AspNetCore.Server.WebListener
private bool _stopping;
private int _outstandingRequests;
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 = listener;
_listener = options.Value?.Listener ?? new Microsoft.Net.Http.Server.WebListener(loggerFactory);
_logger = LogHelper.CreateLogger(loggerFactory, typeof(MessagePump));
Features = features;
Features = new FeatureCollection();
_serverAddresses = new ServerAddressesFeature();
Features.Set<IServerAddressesFeature>(_serverAddresses);
_processRequest = new Action<object>(ProcessRequestAsync);
_maxAccepts = DefaultMaxAccepts;
_shutdownSignal = new ManualResetEvent(false);
}
internal Microsoft.Net.Http.Server.WebListener Listener
public Microsoft.Net.Http.Server.WebListener Listener
{
get { return _listener; }
}
@ -94,13 +102,7 @@ namespace Microsoft.AspNetCore.Server.WebListener
throw new ArgumentNullException(nameof(application));
}
var addressesFeature = Features.Get<IServerAddressesFeature>();
if (addressesFeature == null)
{
throw new InvalidOperationException($"{nameof(IServerAddressesFeature)} is missing.");
}
ParseAddresses(addressesFeature.Addresses, Listener);
ParseAddresses(_serverAddresses.Addresses, Listener);
// Can't call Start twice
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
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -15,13 +15,15 @@
// See the Apache 2 License for the specific language governing
// permissions and limitations under the License.
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Server.Features;
using System.Linq;
using System.Threading.Tasks;
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.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Server;
using Xunit;
@ -187,13 +189,11 @@ namespace Microsoft.AspNetCore.Server.WebListener
var dynamicServer = Utilities.CreateHttpServerReturnRoot("/", out root, app);
dynamicServer.Dispose();
var rootUri = new Uri(root);
var factory = new ServerFactory(loggerFactory: null);
var server = factory.CreateServer(configuration: null);
var listener = server.Features.Get<Microsoft.Net.Http.Server.WebListener>();
var server = new MessagePump(Options.Create(new WebListenerOptions()), new LoggerFactory());
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));

View File

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

View File

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