Skip to content

Commit

Permalink
Don't warn about Android native handler with grpc-web (#2020)
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesNK authored Jan 18, 2023
1 parent 5ea586d commit 246864e
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 4 deletions.
6 changes: 4 additions & 2 deletions src/Grpc.Net.Client/GrpcChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -431,13 +431,15 @@ private HttpMessageInvoker CreateInternalHttpInvoker(HttpMessageHandler? handler
// in advanced gRPC scenarios. We want Android to use SocketsHttpHandler. Throw an error if:
// 1. Client is running on Android.
// 2. Channel is created with HttpClientHandler.
// 3. UseNativeHttpHandler switch is true.
// 3. Channel is not using GrpcWebHandler. grpc-web is compatible with the native handler.
// 4. UseNativeHttpHandler switch is true.
if (OperatingSystem.IsAndroid)
{
// GetHttpHandlerType recurses through DelegatingHandlers that may wrap the HttpClientHandler.
var httpClientHandler = HttpRequestHelpers.GetHttpHandlerType<HttpClientHandler>(handler);
var grpcWebHandler = HttpRequestHelpers.GetHttpHandlerType(handler, "Grpc.Net.Client.Web.GrpcWebHandler");

if (httpClientHandler != null && RuntimeHelpers.QueryRuntimeSettingSwitch("System.Net.Http.UseNativeHttpHandler", defaultValue: false))
if (httpClientHandler != null && grpcWebHandler == null && RuntimeHelpers.QueryRuntimeSettingSwitch("System.Net.Http.UseNativeHttpHandler", defaultValue: false))
{
throw new InvalidOperationException("The channel configuration isn't valid on Android devices. " +
"The channel is configured to use HttpClientHandler and Android's native HTTP/2 library. " +
Expand Down
1 change: 1 addition & 0 deletions test/Grpc.Net.Client.Tests/Grpc.Net.Client.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

<ItemGroup>
<ProjectReference Include="..\..\src\Grpc.Net.Client\Grpc.Net.Client.csproj" />
<ProjectReference Include="..\..\src\Grpc.Net.Client.Web\Grpc.Net.Client.Web.csproj" />

<PackageReference Include="Google.Protobuf" Version="$(GoogleProtobufPackageVersion)" />
<PackageReference Include="Grpc.Tools" Version="$(GrpcToolsPackageVersion)" PrivateAssets="All" />
Expand Down
43 changes: 41 additions & 2 deletions test/Grpc.Net.Client.Tests/GrpcChannelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
using Microsoft.Extensions.Logging.Testing;
using NUnit.Framework;
using Grpc.Net.Client.Internal;
using System.Net;
using Grpc.Net.Client.Web;
#if SUPPORT_LOAD_BALANCING
using Grpc.Net.Client.Balancer;
using Grpc.Net.Client.Balancer.Internal;
Expand Down Expand Up @@ -402,7 +402,7 @@ public async Task Dispose_CalledWhileActiveCalls_ActiveCallsDisposed()
Assert.AreEqual(0, channel.ActiveCalls.Count);
}

[TestCase(null)]
[TestCase(true)]
[TestCase(false)]
public void HttpHandler_HttpClientHandlerOverNativeOnAndroid_ThrowError(bool useDelegatingHandlers)
{
Expand All @@ -415,6 +415,8 @@ public void HttpHandler_HttpClientHandlerOverNativeOnAndroid_ThrowError(bool use
services.AddSingleton<IOperatingSystem>(new TestOperatingSystem { IsAndroid = true });

HttpMessageHandler handler = new HttpClientHandler();

// Add an extra handler to verify that test successfully recurses down custom handlers.
if (useDelegatingHandlers)
{
handler = new TestDelegatingHandler(handler);
Expand Down Expand Up @@ -443,6 +445,43 @@ public void HttpHandler_HttpClientHandlerOverNativeOnAndroid_ThrowError(bool use
}
}

[TestCase(true)]
[TestCase(false)]
public void HttpHandler_HttpClientHandlerOverNativeOnAndroid_HasGrpcWebHandler_ThrowError(bool useDelegatingHandlers)
{
// Arrange
AppContext.SetSwitch("System.Net.Http.UseNativeHttpHandler", true);

try
{
var services = new ServiceCollection();
services.AddSingleton<IOperatingSystem>(new TestOperatingSystem { IsAndroid = true });

HttpMessageHandler handler = new HttpClientHandler();
handler = new GrpcWebHandler(handler);

// Add an extra handler to verify that test successfully recurses down custom handlers.
if (useDelegatingHandlers)
{
handler = new TestDelegatingHandler(handler);
}

var channel = GrpcChannel.ForAddress("https://localhost", new GrpcChannelOptions
{
HttpHandler = handler,
ServiceProvider = services.BuildServiceProvider()
});

// Assert
Assert.IsTrue(channel.OperatingSystem.IsAndroid);
}
finally
{
// Reset switch for other tests.
AppContext.SetSwitch("System.Net.Http.UseNativeHttpHandler", false);
}
}

private class TestDelegatingHandler : DelegatingHandler
{
public TestDelegatingHandler(HttpMessageHandler innerHandler) : base(innerHandler)
Expand Down

0 comments on commit 246864e

Please sign in to comment.