diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs
index df08584b607616..40f865ea9b8605 100644
--- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs
@@ -93,7 +93,7 @@ internal sealed class HttpConnectionPool : IDisposable
private bool _http2Enabled;
private byte[]? _http2AltSvcOriginUri;
internal readonly byte[]? _http2EncodedAuthorityHostHeader;
- private readonly bool _http3Enabled;
+ private bool _http3Enabled;
private Http3Connection? _http3Connection;
private SemaphoreSlim? _http3ConnectionCreateLock;
internal readonly byte[]? _http3EncodedAuthorityHostHeader;
@@ -113,7 +113,7 @@ internal sealed class HttpConnectionPool : IDisposable
private readonly SslClientAuthenticationOptions? _sslOptionsHttp11;
private readonly SslClientAuthenticationOptions? _sslOptionsHttp2;
private readonly SslClientAuthenticationOptions? _sslOptionsHttp2Only;
- private readonly SslClientAuthenticationOptions? _sslOptionsHttp3;
+ private SslClientAuthenticationOptions? _sslOptionsHttp3;
/// Whether the pool has been used since the last time a cleanup occurred.
private bool _usedSinceLastCleanup = true;
@@ -146,7 +146,7 @@ public HttpConnectionPool(HttpConnectionPoolManager poolManager, HttpConnectionK
if (IsHttp3Supported())
{
- _http3Enabled = _poolManager.Settings._maxHttpVersion >= HttpVersion.Version30 && QuicConnection.IsSupported;
+ _http3Enabled = _poolManager.Settings._maxHttpVersion >= HttpVersion.Version30;
}
switch (kind)
@@ -288,15 +288,6 @@ public HttpConnectionPool(HttpConnectionPoolManager poolManager, HttpConnectionK
_http2EncodedAuthorityHostHeader = HPackEncoder.EncodeLiteralHeaderFieldWithoutIndexingToAllocatedArray(H2StaticTable.Authority, hostHeader);
_http3EncodedAuthorityHostHeader = QPackEncoder.EncodeLiteralHeaderFieldWithStaticNameReferenceToArray(H3StaticTable.Authority, hostHeader);
}
-
- if (IsHttp3Supported())
- {
- if (_http3Enabled)
- {
- _sslOptionsHttp3 = ConstructSslOptions(poolManager, sslHostName);
- _sslOptionsHttp3.ApplicationProtocols = s_http3ApplicationProtocols;
- }
- }
}
// Set up for PreAuthenticate. Access to this cache is guarded by a lock on the cache itself.
@@ -1047,7 +1038,23 @@ public async ValueTask SendWithVersionDetectionAndRetryAsyn
!request.IsExtendedConnectRequest)
{
Debug.Assert(async);
- response = await TrySendUsingHttp3Async(request, cancellationToken).ConfigureAwait(false);
+ if (QuicConnection.IsSupported)
+ {
+ if (_sslOptionsHttp3 == null)
+ {
+ // deferred creation. We use atomic exchange to be sure all threads point to single object to mimic ctor behavior.
+ SslClientAuthenticationOptions sslOptionsHttp3 = ConstructSslOptions(_poolManager, _sslOptionsHttp11!.TargetHost!);
+ sslOptionsHttp3.ApplicationProtocols = s_http3ApplicationProtocols;
+ Interlocked.CompareExchange(ref _sslOptionsHttp3, sslOptionsHttp3, null);
+ }
+
+ response = await TrySendUsingHttp3Async(request, cancellationToken).ConfigureAwait(false);
+ }
+ else
+ {
+ _altSvcEnabled = false;
+ _http3Enabled = false;
+ }
}
if (response is null)