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" /> + +