GrpcWebSocketBridge icon indicating copy to clipboard operation
GrpcWebSocketBridge copied to clipboard

Error: The underlying HTTP transport must be a SocketsHttpHandler

Open truegoodwill opened this issue 1 year ago • 4 comments

This exception is thrown when creating the channel:

System.InvalidOperationException: Channel is configured with an HTTP transport doesn't support client-side load balancing or connectivity state tracking. The underlying HTTP transport must be a SocketsHttpHandler with no SocketsHttpHandler.ConnectCallback configured. The HTTP transport must be configured on the channel using GrpcChannelOptions.HttpHandler.
   at Grpc.Net.Client.GrpcChannel.ValidateHttpHandlerSupportsConnectivity()
   at Grpc.Net.Client.GrpcChannel..ctor(Uri address, GrpcChannelOptions channelOptions)
   at Grpc.Net.Client.GrpcChannel.ForAddress(Uri address, GrpcChannelOptions channelOptions)
   at Grpc.Net.Client.GrpcChannel.ForAddress(String address, GrpcChannelOptions channelOptions)
   at Program.<Main>$(String[] args) in D:\FFT\Program.cs:line 24

Link to the source that is throwing the exception: https://github.com/grpc/grpc-dotnet/blob/master/src/Grpc.Net.Client/GrpcChannel.cs#L411

To reproduce use this Program.cs and .csproj

using Grpc.Core;
using Grpc.Net.Client;
using Grpc.Net.Client.Balancer;
using Grpc.Net.Client.Configuration;
using GrpcWebSocketBridge.Client;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;


var services = new ServiceCollection();
services.AddSingleton<ResolverFactory>(new WSSResolverFactory());

using var channel = GrpcChannel.ForAddress("wss://myserver.com:443", new GrpcChannelOptions
{
  HttpHandler = new GrpcWebSocketBridgeHandler(),
  ServiceProvider = services.BuildServiceProvider(),
  Credentials = ChannelCredentials.SecureSsl,
});

internal class WSSResolverFactory : ResolverFactory
{
  public override string Name => "wss";

  public override Resolver Create(ResolverOptions options)
  {
    return new WSSResolver(options.Address, options.DefaultPort, options.LoggerFactory);
  }
}

internal class WSSResolver : PollingResolver
{
  private readonly Uri _address;
  private readonly int _port;

  public WSSResolver(Uri address, int defaultPort, ILoggerFactory loggerFactory)
      : base(loggerFactory)
  {
    _address = address;
    _port = defaultPort;
  }

  protected override async Task ResolveAsync(CancellationToken cancellationToken)
  {
    var address = new BalancerAddress(_address.Host, _port);
    Listener(ResolverResult.ForResult(new[] { address }));
  }
}
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
		<OutputType>Exe</OutputType>
		<TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Google.Protobuf" Version="3.26.0" />
    <PackageReference Include="Grpc.Core" Version="2.46.6" />
    <PackageReference Include="Grpc.Net.Client" Version="2.61.0" />
    <PackageReference Include="Grpc.Tools" Version="2.62.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="GrpcWebSocketBridge.Client" Version="1.2.2" />
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
  </ItemGroup>
</Project>

truegoodwill avatar Mar 23 '24 02:03 truegoodwill

Thank you, as usual, I love using your packages. Great work always :)

truegoodwill avatar Mar 23 '24 03:03 truegoodwill

The exception seems to be thrown when the address passed to GrpcChannel is not http:// or https://. GrpcWebSocketBridge expects http/https scheme, so please specify https instead of wss.

mayuki avatar Apr 10 '24 07:04 mayuki

I did try that. The remote host refused the connection.

truegoodwill avatar Apr 10 '24 16:04 truegoodwill

Can you paste a detailed exception message or stack trace?

mayuki avatar Apr 11 '24 02:04 mayuki

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 30 days.

github-actions[bot] avatar Oct 09 '24 00:10 github-actions[bot]