From aac4eebd799f39b7849b0cd1f01f7d813da63d09 Mon Sep 17 00:00:00 2001 From: John Luo Date: Mon, 27 Feb 2017 19:40:38 -0800 Subject: [PATCH] Direct address configuration #297 --- .../Properties/launchSettings.json | 3 +- samples/SelfHostServer/Startup.cs | 1 + .../Constants.cs | 1 + .../HttpSysOptions.cs | 2 - .../LogHelper.cs | 24 +++++++ .../MessagePump.cs | 67 ++++++++++++------- .../DummyApplication.cs | 3 + .../MessagePumpTests.cs | 61 +++++++++++++++++ .../ServerTests.cs | 2 +- 9 files changed, 133 insertions(+), 31 deletions(-) create mode 100644 test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/MessagePumpTests.cs diff --git a/samples/SelfHostServer/Properties/launchSettings.json b/samples/SelfHostServer/Properties/launchSettings.json index f2eaeff38b..54fa816762 100644 --- a/samples/SelfHostServer/Properties/launchSettings.json +++ b/samples/SelfHostServer/Properties/launchSettings.json @@ -3,9 +3,8 @@ "SelfHostServer": { "commandName": "Project", "launchBrowser": true, - "launchUrl": "http://localhost:8080/", + "launchUrl": "http://localhost:5000/", "environmentVariables": { - "ASPNETCORE_URLS": "http://localhost:8080/", "ASPNETCORE_ENVIRONMENT": "Development" } } diff --git a/samples/SelfHostServer/Startup.cs b/samples/SelfHostServer/Startup.cs index 4d2726587c..f6c0381b23 100644 --- a/samples/SelfHostServer/Startup.cs +++ b/samples/SelfHostServer/Startup.cs @@ -37,6 +37,7 @@ namespace SelfHostServer .UseStartup() .UseHttpSys(options => { + options.UrlPrefixes.Add("http://localhost:5000"); options.Authentication.Schemes = AuthenticationSchemes.None; options.Authentication.AllowAnonymous = true; }) diff --git a/src/Microsoft.AspNetCore.Server.HttpSys/Constants.cs b/src/Microsoft.AspNetCore.Server.HttpSys/Constants.cs index 83a80676fb..d7b5382d18 100644 --- a/src/Microsoft.AspNetCore.Server.HttpSys/Constants.cs +++ b/src/Microsoft.AspNetCore.Server.HttpSys/Constants.cs @@ -13,6 +13,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys internal const string Close = "close"; internal const string Zero = "0"; internal const string SchemeDelimiter = "://"; + internal const string DefaultServerAddress = "http://localhost:5000"; internal static Version V1_0 = new Version(1, 0); internal static Version V1_1 = new Version(1, 1); diff --git a/src/Microsoft.AspNetCore.Server.HttpSys/HttpSysOptions.cs b/src/Microsoft.AspNetCore.Server.HttpSys/HttpSysOptions.cs index fe0c6d1d64..8b00e14e6a 100644 --- a/src/Microsoft.AspNetCore.Server.HttpSys/HttpSysOptions.cs +++ b/src/Microsoft.AspNetCore.Server.HttpSys/HttpSysOptions.cs @@ -2,8 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Server.HttpSys { diff --git a/src/Microsoft.AspNetCore.Server.HttpSys/LogHelper.cs b/src/Microsoft.AspNetCore.Server.HttpSys/LogHelper.cs index 6442e0842b..8c977074bf 100644 --- a/src/Microsoft.AspNetCore.Server.HttpSys/LogHelper.cs +++ b/src/Microsoft.AspNetCore.Server.HttpSys/LogHelper.cs @@ -31,6 +31,30 @@ namespace Microsoft.AspNetCore.Server.HttpSys } } + internal static void LogWarning(ILogger logger, string data) + { + if (logger == null) + { + Debug.WriteLine(data); + } + else + { + logger.LogWarning(data); + } + } + + internal static void LogDebug(ILogger logger, string data) + { + if (logger == null) + { + Debug.WriteLine(data); + } + else + { + logger.LogDebug(data); + } + } + internal static void LogDebug(ILogger logger, string location, string data) { if (logger == null) diff --git a/src/Microsoft.AspNetCore.Server.HttpSys/MessagePump.cs b/src/Microsoft.AspNetCore.Server.HttpSys/MessagePump.cs index 23921561c7..6fd6d3051a 100644 --- a/src/Microsoft.AspNetCore.Server.HttpSys/MessagePump.cs +++ b/src/Microsoft.AspNetCore.Server.HttpSys/MessagePump.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server.Features; using Microsoft.AspNetCore.Http.Features; @@ -16,8 +17,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys { internal class MessagePump : IServer { - private readonly HttpSysListener _listener; private readonly ILogger _logger; + private readonly HttpSysOptions _options; private IHttpApplication _application; @@ -42,23 +43,20 @@ namespace Microsoft.AspNetCore.Server.HttpSys throw new ArgumentNullException(nameof(loggerFactory)); } - var optionsInstance = options.Value; - _listener = new HttpSysListener(optionsInstance, loggerFactory); + _options = options.Value; + Listener = new HttpSysListener(_options, loggerFactory); _logger = LogHelper.CreateLogger(loggerFactory, typeof(MessagePump)); Features = new FeatureCollection(); _serverAddresses = new ServerAddressesFeature(); Features.Set(_serverAddresses); _processRequest = new Action(ProcessRequestAsync); - _maxAccepts = optionsInstance.MaxAccepts; - EnableResponseCaching = optionsInstance.EnableResponseCaching; + _maxAccepts = _options.MaxAccepts; + EnableResponseCaching = _options.EnableResponseCaching; _shutdownSignal = new ManualResetEvent(false); } - internal HttpSysListener Listener - { - get { return _listener; } - } + internal HttpSysListener Listener { get; } internal bool EnableResponseCaching { get; set; } @@ -71,7 +69,37 @@ namespace Microsoft.AspNetCore.Server.HttpSys throw new ArgumentNullException(nameof(application)); } - ParseAddresses(_serverAddresses.Addresses, Listener); + var serverAdressesPresent = _serverAddresses.Addresses.Count > 0; + + if (_options.UrlPrefixes.Count > 0) + { + if (serverAdressesPresent) + { + LogHelper.LogWarning(_logger, $"Overriding address(es) '{string.Join(", ", _serverAddresses.Addresses)}'. " + + $"Binding to endpoints added to {nameof(HttpSysOptions.UrlPrefixes)} instead."); + + _serverAddresses.Addresses.Clear(); + + foreach (var prefix in _options.UrlPrefixes) + { + _serverAddresses.Addresses.Add(prefix.FullPrefix); + } + } + } + else if (serverAdressesPresent) + { + foreach (var value in _serverAddresses.Addresses) + { + Listener.Options.UrlPrefixes.Add(value); + } + } + else + { + LogHelper.LogDebug(_logger, $"No listening endpoints were configured. Binding to {Constants.DefaultServerAddress} by default."); + + _serverAddresses.Addresses.Add(Constants.DefaultServerAddress); + Listener.Options.UrlPrefixes.Add(Constants.DefaultServerAddress); + } // Can't call Start twice Contract.Assert(_application == null); @@ -80,12 +108,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys _application = new ApplicationWrapper(application); - if (_listener.Options.UrlPrefixes.Count == 0) - { - throw new InvalidOperationException("No address prefixes were defined."); - } - - _listener.Start(); + Listener.Start(); ActivateRequestProcessingLimits(); } @@ -111,7 +134,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys RequestContext requestContext; try { - requestContext = await _listener.AcceptAsync().SupressContext(); + requestContext = await Listener.AcceptAsync().SupressContext(); } catch (Exception exception) { @@ -206,14 +229,6 @@ namespace Microsoft.AspNetCore.Server.HttpSys context.Dispose(); } - private void ParseAddresses(ICollection addresses, HttpSysListener listener) - { - foreach (var value in addresses) - { - listener.Options.UrlPrefixes.Add(UrlPrefix.Create(value)); - } - } - public void Dispose() { _stopping = true; @@ -232,7 +247,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys } } // All requests are finished - _listener.Dispose(); + Listener.Dispose(); } private class ApplicationWrapper : IHttpApplication diff --git a/test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/DummyApplication.cs b/test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/DummyApplication.cs index de88885137..4d1f273e4a 100644 --- a/test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/DummyApplication.cs +++ b/test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/DummyApplication.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; +using Microsoft.Extensions.Internal; namespace Microsoft.AspNetCore.Server.HttpSys { @@ -13,6 +14,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys { private readonly RequestDelegate _requestDelegate; + public DummyApplication() : this(context => TaskCache.CompletedTask) { } + public DummyApplication(RequestDelegate requestDelegate) { _requestDelegate = requestDelegate; diff --git a/test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/MessagePumpTests.cs b/test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/MessagePumpTests.cs new file mode 100644 index 0000000000..ccbc964607 --- /dev/null +++ b/test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/MessagePumpTests.cs @@ -0,0 +1,61 @@ +// 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.Linq; +using Microsoft.AspNetCore.Hosting.Server.Features; +using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Xunit; + +namespace Microsoft.AspNetCore.Server.HttpSys +{ + public class MessagePumpTests + { + [ConditionalTheory] + [InlineData("http://localhost:11001/")] + [InlineData("invalid address")] + [InlineData("")] + [InlineData(null)] + public void OverridingIServerAdressesFeatureWithDirectConfiguration_WarnsOnStart(string serverAddress) + { + var overrideAddress = "http://localhost:11002/"; + + using (var server = new MessagePump(Options.Create(new HttpSysOptions()), new LoggerFactory())) + { + var serverAddressesFeature = server.Features.Get(); + serverAddressesFeature.Addresses.Add(serverAddress); + server.Listener.Options.UrlPrefixes.Add(overrideAddress); + + server.Start(new DummyApplication()); + + Assert.Equal(overrideAddress, serverAddressesFeature.Addresses.Single()); + } + } + + [ConditionalFact] + public void UseIServerAdressesFeature_WhenNoDirectConfiguration() + { + var serverAddress = "http://localhost:11001/"; + + using (var server = new MessagePump(Options.Create(new HttpSysOptions()), new LoggerFactory())) + { + var serverAddressesFeature = server.Features.Get(); + serverAddressesFeature.Addresses.Add(serverAddress); + + server.Start(new DummyApplication()); + } + } + + [ConditionalFact] + public void UseDefaultAddress_WhenNoServerAddressAndNoDirectConfiguration() + { + using (var server = new MessagePump(Options.Create(new HttpSysOptions()), new LoggerFactory())) + { + server.Start(new DummyApplication()); + + Assert.Equal(Constants.DefaultServerAddress, server.Features.Get().Addresses.Single()); + } + } + } +} diff --git a/test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/ServerTests.cs b/test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/ServerTests.cs index 2ae94400fa..2a6017a3b0 100644 --- a/test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/ServerTests.cs +++ b/test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/ServerTests.cs @@ -271,7 +271,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys using (server) { - server.Start(new DummyApplication(httpContext => Task.FromResult(0))); + server.Start(new DummyApplication()); string response = await SendRequestAsync(address); Assert.Equal(string.Empty, response); }