-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Include native underlying handler support in HttpClientHandler for iOS/tvOS/MacCatalyst and Android #55384
Include native underlying handler support in HttpClientHandler for iOS/tvOS/MacCatalyst and Android #55384
Conversation
… the reflection based underlying native handlers
…led unsupported attributes as only Send is impacted by the api compat bug
Note regarding the This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change. |
Tagging subscribers to this area: @dotnet/ncl Issue DetailsCompletes the plan for net6 laid out in https://github.com/dotnet/designs/blob/main/accepted/2020/mono-convergence/platform-specific-httpclient.md#the-plan-for-net-5 This change supports using either the native The behavior for Before this PR:
The change creates a handful of partial
Get and Set methods like
It is important to point out that the underlying handler has to be derived from Note, there will need to be additional changes to Xamarin Android once this change goes in and before they take on the new version. We will coordinate appropriately. /cc @dalexsoto @rolfbjarne @jonpryor @jonathanpeppers
|
{ | ||
get => throw new PlatformNotSupportedException(); | ||
set => throw new PlatformNotSupportedException(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be nice to have on Apple platforms. There's an underlying API with slightly different signature that is missing the X509Certificate2
wrapping and passes in the native Apple objects instead. In some earlier Xamarin issue/PR there was a code to do conversion between the two worlds. The reason it was not done directly was because of code size issues.
If this PR gets in then we should open a tracking issue to map this property (and possibly others too). Just putting it here as a reminder.
CancellationToken cancellationToken) | ||
{ | ||
throw new PlatformNotSupportedException(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should also be tracked in some issue. It's likely something that people will run into.
[UnsupportedOSPlatform("tvos")] | ||
[UnsupportedOSPlatform("maccatalyst")] | ||
public static Func<HttpRequestMessage, X509Certificate2?, X509Chain?, SslPolicyErrors, bool> DangerousAcceptAnyServerCertificateValidator => | ||
throw new PlatformNotSupportedException(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to run counter to the documentation:
Particularly in test scenarios, a common pattern use HttpClient to connect to a server with a certificate that shouldn't be validated, such as a self-signed certificate. You commonly do this with HttpClientHandler by setting the ServerCertificateCustomValidationCallback property to a delegate that always returns True; this indicates that the certificate has passed validation. However, not all implementations support this callback, and some throw PlatformNotSupportedException.
The DangerousAcceptAnyServerCertificateValidator property addresses this limitation. The delegate returned by the DangerousAcceptAnyServerCertificateValidator property can be assigned to the ServerCertificateCustomValidationCallback property, as the following example does:
handler.ServerCertificateCustomValidationCallback = httpClientHandler.DangerousAcceptAnyServerCertificateValidator;This gives HttpClientHandler implementations a known object reference identity that expresses the developer's intention. If the object stored in the DangerousAcceptAnyServerCertificateValidator property is reference equals to DangerousAcceptAnyServerCertificateValidator, the runtime is able to entirely disable validation on a platform that would otherwise throw a PlatformNotSupportedException.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may be able to pull something off w/ the native handlers. As for SocketsHttpHandler
(on Android at least), I don't think we'll be able to be able to support it. Maybe we'll be able to apply an ugly tweak, but as of right now it's not likely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The minimal implementation is to return static (...) => true
delegate here in DangerousAcceptAnyServerCertificateValidator
and then check for it by reference in ServerCertificateCustomValidationCallback
setter and not throw PlatformNotSupportedException
. At least that's how I read the documentation. It doesn't necessarily guarantee that the validation gets bypassed on platforms where that is not possible. I could be reading the documentation wrong though (and on second re-read I think I read it wrong 😩).
SockersHttpHandler
on Android may be tricky and I am aware of the limitations in SslStream
implementation. For something like NSUrlSessionHandler
it would be possible to expose DangerousAcceptAnyTrust
callback and assign it through reflection to TrustOverrideForUrl
.
src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.Android.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.cs
Outdated
Show resolved
Hide resolved
<type fullname="System.Net.Http.HttpClient"> | ||
<method signature="System.Boolean IsNativeHandlerEnabled()" body="stub" value="true" feature="System.Net.Http.UseNativeHttpHandler" featurevalue="true" /> | ||
<type fullname="System.Net.Http.HttpClientHandler"> | ||
<method signature="System.Boolean IsNativeHandlerEnabled()" body="stub" value="false" feature="System.Net.Http.UseNativeHttpHandler" featurevalue="false" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to substitute on both true and false values?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I've tested, the current xml does substitute on true and false values.
CC @spouliot |
Failures are infra related. |
Fixes: dotnet/java-interop#854 Changes: dotnet/installer@e8b3b6b...9c46371 % git diff --shortstat e8b3b6be...9c463710 103 files changed, 2301 insertions(+), 2757 deletions(-) Changes: dotnet/linker@a07cab7...460dd6d % git diff --shortstat a07cab7b...460dd6dd 84 files changed, 2403 insertions(+), 258 deletions(-) Changes: dotnet/runtime@02f70d0...96ce6b3 % git diff --shortstat 02f70d0b90...96ce6b3535 2586 files changed, 123677 insertions(+), 34433 deletions(-) Changes: dotnet/java-interop@a5ed891...4fb7c14 * dotnet/java-interop@4fb7c147: [build] set $(DisableImplicitNamespaceImports) by default (#859) * dotnet/java-interop@855ecfa3: [generator] Don't generate unexpected NRT types like `void?` (#856) * dotnet/java-interop@4a02bc32: Revert "[Xamarin.Android.Tools.Bytecode] hide nested types (#827)" (#855) * dotnet/java-interop@95c9b79d: [generator] Avoid 'error (…):' construct in diagnostic messages (#851) * dotnet/java-interop@7c4f7db0: [build] Bump to Mono with MSBuild 16.10 (#848) * dotnet/java-interop@0227cdae: [generator] Gracefully handle BindingGeneratorException. (#845) * dotnet/java-interop@ce1750fd: Add SECURITY.md (#846) Context: dotnet/runtime#55384 Context: dotnet/sdk#18639 Updates: * Microsoft.Dotnet.Sdk.Internal: from 6.0.100-preview.7.21327.2 to 6.0.100-rc.1.21369.3 * Microsoft.NET.ILLink.Tasks: from 6.0.100-preview.6.21322.1 to 6.0.100-preview.6.21366.2 * Microsoft.NETCore.App.Ref: from 6.0.0-preview.7.21326.8 to 6.0.0-rc.1.21368.1 dotnet/runtime#55384 broke how .NET 6 interacts with `AndroidClientHandler`. Fix this by introducing a new `Xamarin.Android.Net.AndroidMessageHandler` type for use on .NET 6, and update the .NET 6 `AndroidClientHandler` to delegate to `AndroidMessageHandler`. `AndroidMessageHandler` doesn't exist on Legacy. Update `.apkdesc` files: * `BuildReleaseArm64SimpleDotNet` is ~37KB smaller * `BuildReleaseArm64XFormsDotNet` is ~62KB larger. Update `tests/api-compatibility/api-compat-exclude-attributes.txt` so that `T:System.Runtime.CompilerServices.CompilerGeneratedAttribute` is ignored. `[CompilerGeneratedAttribute]` is emitted as part of C# 3 "auto-props": public T Property { get; set; } Converting this into a "real" property: T value; public T Property { get => value; set => this.value = value; } results in the `_CheckApiCompatibility` target complaining about an API break. We don't care; ignore `[CompilerGeneratedAttribute]`. Remove `$(SelfContained)` property: early on in .NET 5 (yes 5) development, the Xamarin.Android SDK needed to specify `$(SelfContained)` by default in order to produce `.apk` files. After we became a proper workload, setting the value became unnecessary. It also didn't actually do anything because dotnet/sdk overwrote the value. Starting in dotnet/sdk#18639, `Microsoft.NET.RuntimeIdentifierInference.targets` is now being imported *after* a workload, which meant that dotnet/sdk no longer overwrote our `$(SelfContained)` value, which broke things: error NETSDK1031: It is not supported to build or publish a self-contained application without specifying a RuntimeIdentifier. You must either specify a RuntimeIdentifier or set SelfContained to false. We can simply remove `$(SelfContained)` now, and rely on dotnet/sdk to set this value. Co-authored-by: Jonathan Peppers <jonathan.peppers@microsoft.com> Co-authored-by: Steve Pfister <steve.pfister@microsoft.com>
Fixes: dotnet/java-interop#854 Changes: dotnet/installer@e8b3b6b...808795c % git diff --shortstat e8b3b6be...808795cc 102 files changed, 2218 insertions(+), 2674 deletions(-) Changes: dotnet/linker@a07cab7...9ecf5bd % git diff --shortstat a07cab7b...9ecf5bd2 81 files changed, 2122 insertions(+), 246 deletions(-) Changes: dotnet/runtime@02f70d0...8d3afa3 % git diff --shortstat 02f70d0b...8d3afa3a 2518 files changed, 122843 insertions(+), 33676 deletions(-) Changes: dotnet/java-interop@a5ed891...4fb7c14 * dotnet/java-interop@4fb7c147: [build] set $(DisableImplicitNamespaceImports) by default (#859) * dotnet/java-interop@855ecfa3: [generator] Don't generate unexpected NRT types like `void?` (#856) * dotnet/java-interop@4a02bc32: Revert "[Xamarin.Android.Tools.Bytecode] hide nested types (#827)" (#855) * dotnet/java-interop@95c9b79d: [generator] Avoid 'error (…):' construct in diagnostic messages (#851) * dotnet/java-interop@7c4f7db0: [build] Bump to Mono with MSBuild 16.10 (#848) * dotnet/java-interop@0227cdae: [generator] Gracefully handle BindingGeneratorException. (#845) * dotnet/java-interop@ce1750fd: Add SECURITY.md (#846) Context: dotnet/runtime#55384 Context: dotnet/sdk#18639 Updates: * Microsoft.Dotnet.Sdk.Internal: from 6.0.100-preview.7.21327.2 to 6.0.100-preview.7.21369.5 * Microsoft.NET.ILLink.Tasks: from 6.0.100-preview.6.21322.1 to 6.0.100-preview.6.21365.1 * Microsoft.NETCore.App.Ref: from 6.0.0-preview.7.21326.8 to 6.0.0-preview.7.21368.2 dotnet/runtime#55384 broke how .NET 6 interacts with `AndroidClientHandler`. Fix this by introducing a new `Xamarin.Android.Net.AndroidMessageHandler` type for use on .NET 6, and update the .NET 6 `AndroidClientHandler` to delegate to `AndroidMessageHandler`. `AndroidMessageHandler` doesn't exist on Legacy. Update `.apkdesc` files: * `BuildReleaseArm64SimpleDotNet` is ~37KB smaller * `BuildReleaseArm64XFormsDotNet` is ~62KB larger. Update `tests/api-compatibility/api-compat-exclude-attributes.txt` so that `T:System.Runtime.CompilerServices.CompilerGeneratedAttribute` is ignored. `[CompilerGeneratedAttribute]` is emitted as part of C# 3 "auto-props": public T Property { get; set; } Converting this into a "real" property: T value; public T Property { get => value; set => this.value = value; } results in the `_CheckApiCompatibility` target complaining about an API break. We don't care; ignore `[CompilerGeneratedAttribute]`. Remove `$(SelfContained)` property: early on in .NET 5 (yes 5) development, the Xamarin.Android SDK needed to specify `$(SelfContained)` by default in order to produce `.apk` files. After we became a proper workload, setting the value became unnecessary. It also didn't actually do anything because dotnet/sdk overwrote the value. Starting in dotnet/sdk#18639, `Microsoft.NET.RuntimeIdentifierInference.targets` is now being imported *after* a workload, which meant that dotnet/sdk no longer overwrote our `$(SelfContained)` value, which broke things: error NETSDK1031: It is not supported to build or publish a self-contained application without specifying a RuntimeIdentifier. You must either specify a RuntimeIdentifier or set SelfContained to false. We can simply remove `$(SelfContained)` now, and rely on dotnet/sdk to set this value. Co-authored-by: Jonathan Peppers <jonathan.peppers@microsoft.com> Co-authored-by: Steve Pfister <steve.pfister@microsoft.com>
Completes the plan for net6 laid out in https://github.com/dotnet/designs/blob/main/accepted/2020/mono-convergence/platform-specific-httpclient.md#the-plan-for-net-5
This change supports using either the native
HttpMessageHandler
types that exist in the Xamarin repos (NSUrlSessionHandler
for iOS/tvOS/Catalyst andAndroidMessageHandler
for Android) orSocketsHttpHandler
as the underlying handler inHttpClientHandler
.The behavior for
new HttpClient()
was established earlier in net6, but did not go all the way. For example, if theSystem.Net.Http.UseNativeHttpHandler
feature switch was set to true, usingHttpClient
in different ways would lead to different underlying handlers.Before this PR:
The change creates a handful of partial
HttpClientHandler
files in order to split out the platform specific parts. As you review the PR, you'll notice a bunch ofif (IsSocketHandler)
blocks. The intent of these are to make use of the linker and get linked out once the linker knows which handler is the active one.Get and Set methods like
GetUseCookies
make it easier to tell the linker viaDynamicDependency
to preserve the reflection calls being made to the native underlying handler.It is important to point out that the underlying handler has to be derived from
HttpMessageHandler
. It cannot beHttpClientHandler
or you'll end up with a circular dependency.Note, there will need to be additional changes to Xamarin Android once this change goes in and before they take on the new version. We will coordinate appropriately.
/cc @dalexsoto @rolfbjarne @jonpryor @jonathanpeppers