From 0b5cb8a8b8370a74b6ccbdb9f790e939be788dd3 Mon Sep 17 00:00:00 2001 From: "Chris Ross (ASP.NET)" Date: Wed, 11 Apr 2018 11:57:46 -0700 Subject: [PATCH] Reload HostFilteringOptions on change --- src/Microsoft.AspNetCore/WebHost.cs | 17 +++++-- .../WebHostTests.cs | 51 +++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.AspNetCore/WebHost.cs b/src/Microsoft.AspNetCore/WebHost.cs index e9c21ed554..8c49d2eb23 100644 --- a/src/Microsoft.AspNetCore/WebHost.cs +++ b/src/Microsoft.AspNetCore/WebHost.cs @@ -5,12 +5,14 @@ using System; using System.IO; using System.Reflection; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.HostFiltering; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore { @@ -184,11 +186,20 @@ namespace Microsoft.AspNetCore }) .ConfigureServices((hostingContext, services) => { - var hosts = hostingContext.Configuration["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); - services.AddHostFiltering(options => + // Fallback + services.PostConfigure(options => { - options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { "*" }); + if (options.AllowedHosts == null || options.AllowedHosts.Count == 0) + { + // "AllowedHosts": "localhost;127.0.0.1;[::1]" + var hosts = hostingContext.Configuration["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + // Fall back to "*" to disable. + options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { "*" }); + } }); + // Change notification + services.AddSingleton>( + new ConfigurationChangeTokenSource(hostingContext.Configuration)); services.AddTransient(); }) diff --git a/test/Microsoft.AspNetCore.Tests/WebHostTests.cs b/test/Microsoft.AspNetCore.Tests/WebHostTests.cs index 27f98263f5..e076f0f19c 100644 --- a/test/Microsoft.AspNetCore.Tests/WebHostTests.cs +++ b/test/Microsoft.AspNetCore.Tests/WebHostTests.cs @@ -1,7 +1,13 @@ // 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.Threading; +using Microsoft.AspNetCore.HostFiltering; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Xunit; namespace Microsoft.AspNetCore.Tests @@ -14,5 +20,50 @@ namespace Microsoft.AspNetCore.Tests var builder = WebHost.CreateDefaultBuilder(new string[] { "--urls", "http://localhost:5001" }); Assert.Equal("http://localhost:5001", builder.GetSetting(WebHostDefaults.ServerUrlsKey)); } + + [Fact] + public void WebHostConfiguration_HostFilterOptionsAreReloadable() + { + var host = WebHost.CreateDefaultBuilder() + .Configure(app => { }) + .ConfigureAppConfiguration(configBuilder => + { + configBuilder.Add(new ReloadableMemorySource()); + }).Build(); + var config = host.Services.GetRequiredService(); + var monitor = host.Services.GetRequiredService>(); + var options = monitor.CurrentValue; + + Assert.Contains("*", options.AllowedHosts); + + var changed = new ManualResetEvent(false); + monitor.OnChange(newOptions => + { + changed.Set(); + }); + + config["AllowedHosts"] = "NewHost"; + + Assert.True(changed.WaitOne(TimeSpan.FromSeconds(10))); + options = monitor.CurrentValue; + Assert.Contains("NewHost", options.AllowedHosts); + } + + private class ReloadableMemorySource : IConfigurationSource + { + public IConfigurationProvider Build(IConfigurationBuilder builder) + { + return new ReloadableMemoryProvider(); + } + } + + private class ReloadableMemoryProvider : ConfigurationProvider + { + public override void Set(string key, string value) + { + base.Set(key, value); + OnReload(); + } + } } }