简体   繁体   中英

.Net Core 3.1 gRPC client with unencrypted HTTP2 connection

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:

  • port http://*:16050
  • port https://*:16150. This replies correctly to the client but as explained above, can be used only locally at the moment

The server provides

  • Http1 and Http2
  • REST APIs and gRPC APIs on the same port

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>

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM