Allow more than one IConnectionListenerFactory (#17383)
This commit is contained in:
parent
cf116a7815
commit
b81c1a7954
|
|
@ -1,17 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
|
|
@ -26,36 +26,36 @@
|
|||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
|
|
@ -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>
|
||||
</root>
|
||||
<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