diff --git a/docs/workflow/trimming/feature-switches.md b/docs/workflow/trimming/feature-switches.md
index 00deee4a125af..40971d1fdb9df 100644
--- a/docs/workflow/trimming/feature-switches.md
+++ b/docs/workflow/trimming/feature-switches.md
@@ -15,6 +15,7 @@ configurations but their defaults might vary as any SDK can set the defaults dif
| InvariantGlobalization | System.Globalization.Invariant | All globalization specific code and data is trimmed when set to true |
| UseSystemResourceKeys | System.Resources.UseSystemResourceKeys | Any localizable resources for system assemblies is trimmed when set to true |
| HttpActivityPropagationSupport | System.Net.Http.EnableActivityPropagation | Any dependency related to diagnostics support for System.Net.Http is trimmed when set to false |
+| HttpNativeHandler | System.Net.Http.UseNativeHttpHandler | HttpClient uses by default platform native implementation of HttpMessageHandler if set to true. |
| StartupHookSupport | System.StartupHookProvider.IsSupported | Startup hooks are disabled when set to false. Startup hook related functionality can be trimmed. |
| TBD | System.Threading.ThreadPool.EnableDispatchAutoreleasePool | When set to true, creates an NSAutoreleasePool around each thread pool work item on applicable platforms. |
| CustomResourceTypesSupport | System.Resources.ResourceManager.AllowCustomResourceTypes | Use of custom resource types is disabled when set to false. ResourceManager code paths that use reflection for custom types can be trimmed. |
diff --git a/src/libraries/System.Net.Http/src/ILLink/ILLink.Substitutions.xml b/src/libraries/System.Net.Http/src/ILLink/ILLink.Substitutions.xml
index 5e70f6fbb5d7d..314469c96d777 100644
--- a/src/libraries/System.Net.Http/src/ILLink/ILLink.Substitutions.xml
+++ b/src/libraries/System.Net.Http/src/ILLink/ILLink.Substitutions.xml
@@ -3,5 +3,8 @@
+
+
+
diff --git a/src/libraries/System.Net.Http/src/ILLink/ILLink.Suppressions.xml b/src/libraries/System.Net.Http/src/ILLink/ILLink.Suppressions.xml
new file mode 100644
index 0000000000000..b84fc3ee1c1e5
--- /dev/null
+++ b/src/libraries/System.Net.Http/src/ILLink/ILLink.Suppressions.xml
@@ -0,0 +1,11 @@
+
+
+
+
+ ILLink
+ IL2075
+ member
+ M:System.Net.Http.HttpClient.CreateDefaultHandler()
+
+
+
diff --git a/src/libraries/System.Net.Http/src/System.Net.Http.csproj b/src/libraries/System.Net.Http/src/System.Net.Http.csproj
index 43afb449b58aa..201d0acd63e5d 100644
--- a/src/libraries/System.Net.Http/src/System.Net.Http.csproj
+++ b/src/libraries/System.Net.Http/src/System.Net.Http.csproj
@@ -3,7 +3,7 @@
win
true
$(DefineConstants);HTTP_DLL
- $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-FreeBSD;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent)-Browser;$(NetCoreAppCurrent)-illumos;$(NetCoreAppCurrent)-Solaris
+ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-FreeBSD;$(NetCoreAppCurrent)-MacCatalyst;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent)-Browser;$(NetCoreAppCurrent)-illumos;$(NetCoreAppCurrent)-Solaris;$(NetCoreAppCurrent)-Android
enable
@@ -37,6 +37,10 @@
+
+
+
+
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.CreateDefaultHandler.Android.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.CreateDefaultHandler.Android.cs
new file mode 100644
index 0000000000000..f770bbe22a2ac
--- /dev/null
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.CreateDefaultHandler.Android.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Reflection;
+
+namespace System.Net.Http
+{
+ public partial class HttpClient
+ {
+ private static MethodInfo? handlerMethod;
+
+ private static HttpMessageHandler CreateDefaultHandler()
+ {
+ // Default is to use the Android native handler
+ if (!IsNativeHandlerEnabled())
+ {
+ return new HttpClientHandler();
+ }
+
+ if (handlerMethod == null)
+ {
+ Type? androidEnv = Type.GetType("Android.Runtime.AndroidEnvironment, Mono.Android");
+ handlerMethod = androidEnv!.GetMethod("GetHttpMessageHandler", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
+ }
+
+ return (HttpMessageHandler)handlerMethod!.Invoke(null, null)!;
+ }
+ }
+}
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.CreateDefaultHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.CreateDefaultHandler.cs
new file mode 100644
index 0000000000000..b1327d9cd0fde
--- /dev/null
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.CreateDefaultHandler.cs
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Net.Http
+{
+ public partial class HttpClient
+ {
+ private static HttpMessageHandler CreateDefaultHandler()
+ {
+ return new HttpClientHandler();
+ }
+ }
+}
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.CreateDefaultHandler.iOS.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.CreateDefaultHandler.iOS.cs
new file mode 100644
index 0000000000000..03f4f945c9f27
--- /dev/null
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.CreateDefaultHandler.iOS.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Reflection;
+
+namespace System.Net.Http
+{
+ public partial class HttpClient
+ {
+ private static MethodInfo? handlerMethod;
+
+ private static HttpMessageHandler CreateDefaultHandler()
+ {
+ // Default is to use the iOS native handler
+ if (!IsNativeHandlerEnabled())
+ {
+ return new HttpClientHandler();
+ }
+
+ if (handlerMethod == null)
+ {
+ Type? runtimeOptions = Type.GetType("ObjCRuntime.RuntimeOptions, Xamarin.iOS");
+ handlerMethod = runtimeOptions!.GetMethod("GetHttpMessageHandler", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
+ }
+
+ return (HttpMessageHandler)handlerMethod!.Invoke(null, null)!;
+ }
+ }
+}
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.CreateDefaultHandler.tvOS.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.CreateDefaultHandler.tvOS.cs
new file mode 100644
index 0000000000000..e2dfbe0ffc107
--- /dev/null
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.CreateDefaultHandler.tvOS.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Reflection;
+
+namespace System.Net.Http
+{
+ public partial class HttpClient
+ {
+ private static MethodInfo? handlerMethod;
+
+ private static HttpMessageHandler CreateDefaultHandler()
+ {
+ // Default is to use the tvOS native handler
+ if (!IsNativeHandlerEnabled())
+ {
+ return new HttpClientHandler();
+ }
+
+ if (handlerMethod == null)
+ {
+ Type? runtimeOptions = Type.GetType("ObjCRuntime.RuntimeOptions, Xamarin.TVOS");
+ handlerMethod = runtimeOptions!.GetMethod("GetHttpMessageHandler", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
+ }
+
+ return (HttpMessageHandler)handlerMethod!.Invoke(null, null)!;
+ }
+ }
+}
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs
index 4506b484ed88b..b4456b65c31f3 100644
--- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs
@@ -11,7 +11,7 @@
namespace System.Net.Http
{
- public class HttpClient : HttpMessageInvoker
+ public partial class HttpClient : HttpMessageInvoker
{
#region Fields
@@ -127,7 +127,7 @@ public long MaxResponseContentBufferSize
#region Constructors
- public HttpClient() : this(new HttpClientHandler())
+ public HttpClient() : this(CreateDefaultHandler())
{
}
@@ -813,6 +813,16 @@ private static void CheckBaseAddress(Uri? baseAddress, string parameterName)
}
}
+ private static bool IsNativeHandlerEnabled()
+ {
+ if (!AppContext.TryGetSwitch("System.Net.Http.UseNativeHttpHandler", out bool isEnabled))
+ {
+ return false;
+ }
+
+ return isEnabled;
+ }
+
private Uri? CreateUri(string? uri) =>
string.IsNullOrEmpty(uri) ? null : new Uri(uri, UriKind.RelativeOrAbsolute);
diff --git a/src/libraries/System.Net.Http/tests/UnitTests/System.Net.Http.Unit.Tests.csproj b/src/libraries/System.Net.Http/tests/UnitTests/System.Net.Http.Unit.Tests.csproj
index 5a79894a9d9e1..30aeeab7d2b8d 100644
--- a/src/libraries/System.Net.Http/tests/UnitTests/System.Net.Http.Unit.Tests.csproj
+++ b/src/libraries/System.Net.Http/tests/UnitTests/System.Net.Http.Unit.Tests.csproj
@@ -3,7 +3,7 @@
../../src/Resources/Strings.resx
true
true
- $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS
+ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-MacCatalyst;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent)-Android
annotations
@@ -190,6 +190,12 @@
Link="ProductionCode\System\Net\Http\Headers\WarningHeaderValue.cs" />
+
+