Error: The underlying HTTP transport must be a SocketsHttpHandler
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>
Thank you, as usual, I love using your packages. Great work always :)
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.
I did try that. The remote host refused the connection.
Can you paste a detailed exception message or stack trace?
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.