Warn instead of throw when ignoring IServerAddressesFeature
- Throwing could be too much when IServerAddressesFeature URLs come from VS - Listen on 127.0.0.1:5000 by default https://github.com/aspnet/Hosting/issues/917
This commit is contained in:
parent
20e02e8fd6
commit
f32058c5c3
|
|
@ -36,6 +36,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{0EF2AC
|
|||
ProjectSection(SolutionItems) = preProject
|
||||
test\shared\DummyApplication.cs = test\shared\DummyApplication.cs
|
||||
test\shared\HttpClientSlim.cs = test\shared\HttpClientSlim.cs
|
||||
test\shared\KestrelTestLoggerFactory.cs = test\shared\KestrelTestLoggerFactory.cs
|
||||
test\shared\LifetimeNotImplemented.cs = test\shared\LifetimeNotImplemented.cs
|
||||
test\shared\MockConnection.cs = test\shared\MockConnection.cs
|
||||
test\shared\MockFrameControl.cs = test\shared\MockFrameControl.cs
|
||||
|
|
|
|||
|
|
@ -34,33 +34,34 @@ namespace SampleApp
|
|||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var hostBuilder = new WebHostBuilder().UseKestrel(options =>
|
||||
{
|
||||
options.Listen(IPAddress.Loopback, 5000, listenOptions =>
|
||||
var host = new WebHostBuilder()
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
// Uncomment the following to enable Nagle's algorithm for this endpoint.
|
||||
//listenOptions.NoDelay = false;
|
||||
options.Listen(IPAddress.Loopback, 5000, listenOptions =>
|
||||
{
|
||||
// Uncomment the following to enable Nagle's algorithm for this endpoint.
|
||||
//listenOptions.NoDelay = false;
|
||||
|
||||
listenOptions.UseConnectionLogging();
|
||||
});
|
||||
options.Listen(IPAddress.Loopback, 5001, listenOptions =>
|
||||
{
|
||||
listenOptions.UseHttps("testCert.pfx", "testPassword");
|
||||
listenOptions.UseConnectionLogging();
|
||||
});
|
||||
listenOptions.UseConnectionLogging();
|
||||
});
|
||||
options.Listen(IPAddress.Loopback, 5001, listenOptions =>
|
||||
{
|
||||
listenOptions.UseHttps("testCert.pfx", "testPassword");
|
||||
listenOptions.UseConnectionLogging();
|
||||
});
|
||||
|
||||
options.UseSystemd();
|
||||
options.UseSystemd();
|
||||
|
||||
// The following section should be used to demo sockets
|
||||
//options.ListenUnixSocket("/tmp/kestrel-test.sock");
|
||||
// The following section should be used to demo sockets
|
||||
//options.ListenUnixSocket("/tmp/kestrel-test.sock");
|
||||
|
||||
// Uncomment the following line to change the default number of libuv threads for all endpoints.
|
||||
//options.ThreadCount = 4;
|
||||
})
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>();
|
||||
// Uncomment the following line to change the default number of libuv threads for all endpoints.
|
||||
//options.ThreadCount = 4;
|
||||
})
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.Build();
|
||||
|
||||
var host = hostBuilder.Build();
|
||||
host.Run();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +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.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
|
||||
{
|
||||
internal class Constants
|
||||
internal static class Constants
|
||||
{
|
||||
public const int ListenBacklog = 128;
|
||||
|
||||
|
|
@ -14,6 +14,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
|
|||
public static readonly int? ECONNRESET = GetECONNRESET();
|
||||
public static readonly int? EADDRINUSE = GetEADDRINUSE();
|
||||
|
||||
/// <summary>
|
||||
/// The IPEndPoint Kestrel will bind to if nothing else is specified.
|
||||
/// </summary>
|
||||
public static readonly IPEndPoint DefaultIPEndPoint = new IPEndPoint(IPAddress.Loopback, 5000);
|
||||
|
||||
/// <summary>
|
||||
/// Prefix of host name used to specify Unix sockets in the configuration.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -112,22 +112,24 @@ namespace Microsoft.AspNetCore.Server.Kestrel
|
|||
}
|
||||
|
||||
engine.Start(threadCount);
|
||||
var atLeastOneListener = false;
|
||||
|
||||
var listenOptions = Options.ListenOptions;
|
||||
var hasListenOptions = listenOptions.Any();
|
||||
var hasServerAddresses = _serverAddresses.Addresses.Any();
|
||||
|
||||
if (listenOptions.Any())
|
||||
if (hasListenOptions && hasServerAddresses)
|
||||
{
|
||||
var addresses = _serverAddresses.Addresses;
|
||||
if (addresses.SingleOrDefault() != "http://localhost:5000")
|
||||
{
|
||||
var joined = string.Join(", ", addresses);
|
||||
throw new NotSupportedException($"Specifying address(es) '{joined}' is incompatible with also configuring endpoint(s) in UseKestrel.");
|
||||
}
|
||||
var joined = string.Join(", ", _serverAddresses.Addresses);
|
||||
_logger.LogWarning($"Overriding address(es) '{joined}'. Binding to endpoints defined in {nameof(WebHostBuilderKestrelExtensions.UseKestrel)}() instead.");
|
||||
|
||||
_serverAddresses.Addresses.Clear();
|
||||
}
|
||||
else
|
||||
else if (!hasListenOptions && !hasServerAddresses)
|
||||
{
|
||||
_logger.LogDebug($"No listening endpoints were configured. Binding to {Constants.DefaultIPEndPoint} by default.");
|
||||
listenOptions.Add(new ListenOptions(Constants.DefaultIPEndPoint));
|
||||
}
|
||||
else if (!hasListenOptions)
|
||||
{
|
||||
// If no endpoints are configured directly using KestrelServerOptions, use those configured via the IServerAddressesFeature.
|
||||
var copiedAddresses = _serverAddresses.Addresses.ToArray();
|
||||
|
|
@ -155,7 +157,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel
|
|||
// If StartLocalhost doesn't throw, there is at least one listener.
|
||||
// The port cannot change for "localhost".
|
||||
_serverAddresses.Addresses.Add(parsedAddress.ToString());
|
||||
atLeastOneListener = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -172,8 +173,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel
|
|||
|
||||
foreach (var endPoint in listenOptions)
|
||||
{
|
||||
atLeastOneListener = true;
|
||||
|
||||
try
|
||||
{
|
||||
_disposables.Push(engine.CreateServer(endPoint));
|
||||
|
|
@ -191,11 +190,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel
|
|||
// If requested port was "0", replace with assigned dynamic port.
|
||||
_serverAddresses.Addresses.Add(endPoint.ToString());
|
||||
}
|
||||
|
||||
if (!atLeastOneListener)
|
||||
{
|
||||
throw new InvalidOperationException("No recognized listening addresses were configured.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ using Microsoft.AspNetCore.Http;
|
|||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Microsoft.AspNetCore.Testing.xunit;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -126,6 +128,35 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
}
|
||||
}
|
||||
|
||||
[ConditionalFact(Skip = "Waiting on https://github.com/aspnet/Hosting/issues/917")]
|
||||
[PortSupportedCondition(5000)]
|
||||
public async Task DefaultsToPort5000()
|
||||
{
|
||||
var testLogger = new TestApplicationErrorLogger();
|
||||
|
||||
var hostBuilder = new WebHostBuilder()
|
||||
.UseKestrel()
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddSingleton<ILoggerFactory>(new KestrelTestLoggerFactory(testLogger));
|
||||
})
|
||||
.Configure(ConfigureEchoAddress);
|
||||
|
||||
using (var host = hostBuilder.Build())
|
||||
{
|
||||
host.Start();
|
||||
|
||||
var debugLog = testLogger.Messages.Single(log => log.LogLevel == LogLevel.Debug);
|
||||
Assert.True(debugLog.Message.Contains("default"));
|
||||
|
||||
foreach (var testUrl in new[] { "http://127.0.0.1:5000", "http://localhost:5000" })
|
||||
{
|
||||
var response = await HttpClientSlim.GetStringAsync(testUrl);
|
||||
Assert.Equal(new Uri(testUrl).ToString(), response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ThrowsWhenBindingToIPv4AddressInUse()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Hosting.Server;
|
||||
using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||
using Microsoft.AspNetCore.Server.Kestrel;
|
||||
|
|
@ -43,16 +45,26 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
Assert.Equal(1, testLogger.CriticalErrorsLogged);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StartWithEmptyAddressesThrows()
|
||||
[Theory]
|
||||
[InlineData("http://localhost:5000")]
|
||||
[InlineData("The value of the string shouldn't matter.")]
|
||||
[InlineData(null)]
|
||||
public void StartWarnsWhenIgnoringIServerAddressesFeature(string ignoredAddress)
|
||||
{
|
||||
var testLogger = new TestApplicationErrorLogger();
|
||||
var server = CreateServer(new KestrelServerOptions(), testLogger);
|
||||
var kestrelOptions = new KestrelServerOptions();
|
||||
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => StartDummyApplication(server));
|
||||
// Directly configuring an endpoint using Listen causes the IServerAddressesFeature to be ignored.
|
||||
kestrelOptions.Listen(IPAddress.Loopback, 0);
|
||||
|
||||
Assert.Equal("No recognized listening addresses were configured.", exception.Message);
|
||||
Assert.Equal(1, testLogger.CriticalErrorsLogged);
|
||||
using (var server = CreateServer(kestrelOptions, testLogger))
|
||||
{
|
||||
server.Features.Get<IServerAddressesFeature>().Addresses.Add(ignoredAddress);
|
||||
StartDummyApplication(server);
|
||||
|
||||
var warning = testLogger.Messages.Single(log => log.LogLevel == LogLevel.Warning);
|
||||
Assert.True(warning.Message.Contains("Overriding"));
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -87,37 +99,12 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
{
|
||||
var lifetime = new LifetimeNotImplemented();
|
||||
|
||||
return new KestrelServer(Options.Create(options), lifetime, new TestLoggerFactory(testLogger));
|
||||
return new KestrelServer(Options.Create(options), lifetime, new KestrelTestLoggerFactory(testLogger));
|
||||
}
|
||||
|
||||
private static void StartDummyApplication(IServer server)
|
||||
{
|
||||
server.Start(new DummyApplication(context => TaskCache.CompletedTask));
|
||||
}
|
||||
|
||||
private class TestLoggerFactory : ILoggerFactory
|
||||
{
|
||||
private readonly ILogger _testLogger;
|
||||
|
||||
public TestLoggerFactory(ILogger testLogger)
|
||||
{
|
||||
_testLogger = testLogger;
|
||||
}
|
||||
|
||||
public ILogger CreateLogger(string categoryName)
|
||||
{
|
||||
return _testLogger;
|
||||
}
|
||||
|
||||
public void AddProvider(ILoggerProvider provider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
// 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 Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Testing
|
||||
{
|
||||
public class KestrelTestLoggerFactory : ILoggerFactory
|
||||
{
|
||||
private readonly ILogger _testLogger;
|
||||
|
||||
public KestrelTestLoggerFactory(ILogger testLogger)
|
||||
{
|
||||
_testLogger = testLogger;
|
||||
}
|
||||
|
||||
public ILogger CreateLogger(string categoryName)
|
||||
{
|
||||
return _testLogger;
|
||||
}
|
||||
|
||||
public void AddProvider(ILoggerProvider provider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -38,7 +38,13 @@ namespace Microsoft.AspNetCore.Testing
|
|||
Console.WriteLine($"Log {logLevel}[{eventId}]: {formatter(state, exception)} {exception?.Message}");
|
||||
#endif
|
||||
|
||||
Messages.Add(new LogMessage { LogLevel = logLevel, EventId = eventId, Exception = exception });
|
||||
Messages.Add(new LogMessage
|
||||
{
|
||||
LogLevel = logLevel,
|
||||
EventId = eventId,
|
||||
Exception = exception,
|
||||
Message = formatter(state, exception)
|
||||
});
|
||||
}
|
||||
|
||||
public class LogMessage
|
||||
|
|
@ -46,6 +52,7 @@ namespace Microsoft.AspNetCore.Testing
|
|||
public LogLevel LogLevel { get; set; }
|
||||
public EventId EventId { get; set; }
|
||||
public Exception Exception { get; set; }
|
||||
public string Message { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue