Reputation: 1183
I am trying to query some local gRPC services running on HTTP. This is my net core 3.1 console app:
static async Task Main(string[] args)
{
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
using var channel = GrpcChannel.ForAddress("http://localhost:16050");
var client = new EventService.EventServiceClient(channel);
var reply1 = await client.GetTrackEventAsync(new GetTrackEventRequest { Name = "01Austra14" });
}
But it is throwing this error:
An exception of type 'Grpc.Core.RpcException' occurred in System.Private.CoreLib.dll but was not handled in user code: 'Status(StatusCode="Internal", Detail="Error starting gRPC call. HttpRequestException: An error occurred while sending the request. Http2ConnectionException: The HTTP/2 server sent invalid data on the connection. HTTP/2 error code 'PROTOCOL_ERROR' (0x1).", DebugException="System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.Http.Http2ConnectionException: The HTTP/2 server sent invalid data on the connection. HTTP/2 error code 'PROTOCOL_ERROR' (0x1).
Unfortunately at the moment we can't add an SSL certificate and we need to use plain HTTP for a while (the service app is not in production yet). Does anyone have an idea on what is happening here?
According to the documentation the AppContext.SetSwitch
call should be enough.
The server is an Asp Net Core 3.1 app. It is running on:
The server provides
Client is using the following packages
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.17.0" />
<PackageReference Include="Grpc.Net.Client" Version="2.37.0" />
<PackageReference Include="Grpc.Tools" Version="2.37.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
Upvotes: 10
Views: 9877
Reputation: 1063884
I can't be 100% sure this applies in your scenario (although the "Http1 and Http2" suggests: it will apply), but: I've seen this problem with a non-TLS endpoint that is attempting to serve both HTTP/1 and HTTP/2 traffic - it gets a little confused and tries to respond with HTTP/1 response to an HTTP/2 request (this doesn't happen with a TLS endpoint, due to the handshake working differently). In my case, the fix was to tell the server to only serve HTTP/2. This can be done in appSettings.json under the Kestrel
/ EndPoints
node, by specifying "Protocols": "Http2"
, or in Program.cs by specifying listenOptions.Protocols = HttpProtocols.Http2
in the ConfigureKestrel
call. When I want to serve HTTP/1 and HTTP/2 without TLS, I've always had to use different ports etc.
Upvotes: 6