Allow more than one IConnectionListenerFactory (#17383)
This commit is contained in:
parent
cf116a7815
commit
b81c1a7954
|
|
@ -559,7 +559,8 @@ For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?l
|
|||
</data>
|
||||
<data name="HttpParserTlsOverHttpError" xml:space="preserve">
|
||||
<value>Detected a TLS handshake to an endpoint that does not have TLS enabled.</value>
|
||||
</data> <data name="BadDeveloperCertificateState" xml:space="preserve">
|
||||
</data>
|
||||
<data name="BadDeveloperCertificateState" xml:space="preserve">
|
||||
<value>The ASP.NET Core developer certificate is in an invalid state. To fix this issue, run the following commands 'dotnet dev-certs https --clean' and 'dotnet dev-certs https' to remove all existing ASP.NET Core development certificates and create a new untrusted developer certificate. On macOS or Windows, use 'dotnet dev-certs https --trust' to trust the new certificate.</value>
|
||||
</data>
|
||||
<data name="QPackErrorIndexOutOfRange" xml:space="preserve">
|
||||
|
|
@ -574,4 +575,10 @@ For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?l
|
|||
<data name="QPackStringLengthTooLarge" xml:space="preserve">
|
||||
<value>Decoded string length of {length} octets is greater than the configured maximum length of {maxStringLength} octets.</value>
|
||||
</data>
|
||||
<data name="QuicTransportNotFound" xml:space="preserve">
|
||||
<value>Quic transport not found when using HTTP/3.</value>
|
||||
</data>
|
||||
<data name="TransportNotFound" xml:space="preserve">
|
||||
<value>Unable to resolve service for type 'Microsoft.AspNetCore.Connections.IConnectionListenerFactory' while attempting to activate 'Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer'.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
|
|||
{
|
||||
private readonly List<(IConnectionListener, Task)> _transports = new List<(IConnectionListener, Task)>();
|
||||
private readonly IServerAddressesFeature _serverAddresses;
|
||||
private readonly IEnumerable<IConnectionListenerFactory> _transportFactories;
|
||||
private readonly List<IConnectionListenerFactory> _transportFactories;
|
||||
|
||||
private bool _hasStarted;
|
||||
private int _stopping;
|
||||
|
|
@ -42,7 +42,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
|
|||
throw new ArgumentNullException(nameof(transportFactories));
|
||||
}
|
||||
|
||||
_transportFactories = transportFactories;
|
||||
_transportFactories = transportFactories.ToList();
|
||||
|
||||
if (_transportFactories.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException(CoreStrings.TransportNotFound);
|
||||
}
|
||||
|
||||
ServiceContext = serviceContext;
|
||||
|
||||
Features = new FeatureCollection();
|
||||
|
|
@ -143,19 +149,19 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
|
|||
{
|
||||
if (transportFactory is IMultiplexedConnectionListenerFactory)
|
||||
{
|
||||
// Don't break early. Always use the last registered factory.
|
||||
factory = transportFactory;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (factory == null)
|
||||
{
|
||||
throw new Exception("Quic transport not found when using HTTP/3");
|
||||
throw new InvalidOperationException(CoreStrings.QuicTransportNotFound);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
factory = _transportFactories.Single();
|
||||
factory = _transportFactories.Last();
|
||||
}
|
||||
|
||||
var transport = await factory.BindAsync(options.EndPoint).ConfigureAwait(false);
|
||||
|
|
|
|||
|
|
@ -204,22 +204,45 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
var mockLoggerFactory = new Mock<ILoggerFactory>();
|
||||
var mockLogger = new Mock<ILogger>();
|
||||
mockLoggerFactory.Setup(m => m.CreateLogger(It.IsAny<string>())).Returns(mockLogger.Object);
|
||||
new KestrelServer(Options.Create<KestrelServerOptions>(null), Mock.Of<IEnumerable<IConnectionListenerFactory>>(), mockLoggerFactory.Object);
|
||||
new KestrelServer(Options.Create<KestrelServerOptions>(null), new List<IConnectionListenerFactory>() { new MockTransportFactory() }, mockLoggerFactory.Object);
|
||||
mockLoggerFactory.Verify(factory => factory.CreateLogger("Microsoft.AspNetCore.Server.Kestrel"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StartWithNoTransportFactoryThrows()
|
||||
public void ConstructorWithNullTransportFactoriesThrows()
|
||||
{
|
||||
var mockLoggerFactory = new Mock<ILoggerFactory>();
|
||||
var mockLogger = new Mock<ILogger>();
|
||||
mockLoggerFactory.Setup(m => m.CreateLogger(It.IsAny<string>())).Returns(mockLogger.Object);
|
||||
var exception = Assert.Throws<ArgumentNullException>(() =>
|
||||
new KestrelServer(Options.Create<KestrelServerOptions>(null), null, mockLoggerFactory.Object));
|
||||
new KestrelServer(
|
||||
Options.Create<KestrelServerOptions>(null),
|
||||
null,
|
||||
new LoggerFactory(new[] { new KestrelTestLoggerProvider() })));
|
||||
|
||||
Assert.Equal("transportFactories", exception.ParamName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorWithNoTransportFactoriesThrows()
|
||||
{
|
||||
var exception = Assert.Throws<InvalidOperationException>(() =>
|
||||
new KestrelServer(
|
||||
Options.Create<KestrelServerOptions>(null),
|
||||
new List<IConnectionListenerFactory>(),
|
||||
new LoggerFactory(new[] { new KestrelTestLoggerProvider() })));
|
||||
|
||||
Assert.Equal(CoreStrings.TransportNotFound, exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StartWithMultipleTransportFactoriesDoesNotThrow()
|
||||
{
|
||||
using var server = new KestrelServer(
|
||||
Options.Create(CreateServerOptions()),
|
||||
new List<IConnectionListenerFactory>() { new ThrowingTransportFactory(), new MockTransportFactory() },
|
||||
new LoggerFactory(new[] { new KestrelTestLoggerProvider() }));
|
||||
|
||||
StartDummyApplication(server);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StopAsyncCallsCompleteWhenFirstCallCompletes()
|
||||
{
|
||||
|
|
@ -456,5 +479,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
return new ValueTask<IConnectionListener>(mock.Object);
|
||||
}
|
||||
}
|
||||
|
||||
private class ThrowingTransportFactory : IConnectionListenerFactory
|
||||
{
|
||||
public ValueTask<IConnectionListener> BindAsync(EndPoint endpoint, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue