Cysharp / YetAnotherHttpHandler

YetAnotherHttpHandler brings the power of HTTP/2 (and gRPC) to Unity and .NET Standard.
MIT License
350 stars 31 forks source link

[GRPC Python Server + Unity Client] HttpRequestException: Unsupported HTTP version #61

Closed ApocalyVec closed 6 months ago

ApocalyVec commented 6 months ago

Hi @mayuki

Many thanks for putting this together! It's incredible!

I'm trying to call python grpc calls from Unity. I was trying a bunch of things before I hit upon your repo which made things a lot easier. But I'm running into some problems using the HTTPHandler.

I followed the installation instructions with a fresh Unity project. I'm running into an issue with the following snippet:

        using var handler = new YetAnotherHttpHandler();
        using var channel = GrpcChannel.ForAddress(host, new GrpcChannelOptions() { HttpHandler = handler, Credentials = ChannelCredentials.Insecure});
        var greeter = new Greeter.GreeterClient(channel);
        var reply = greeter.SayHello(new HelloRequest { Name = "Alice" });

The last line gives an HttpRequestException:

HttpRequestException: request has unsupported HTTP version
Cysharp.Net.Http.ResponseContext.GetResponseAsync () (at ./Library/PackageCache/com.cysharp.yetanotherhttphandler@37998fea90/ResponseContext.cs:165)

My python grpc server is the helloworld example from https://grpc.io/docs/languages/python/quickstart/ without any modification. The server I'm running is this file: https://github.com/grpc/grpc/blob/master/examples/python/helloworld/greeter_server.py

Unity version: 2022.3.19f1 Python version: 3.11

Here's my Unity project, you can try it and reproduce the error: https://github.com/mengyuanwu1/GRPC-Test

Here's the full stack trace when the "unsupported HTTP version" is thrown from Unity side:

HttpRequestException: request has unsupported HTTP version
Cysharp.Net.Http.ResponseContext.GetResponseAsync () (at ./Library/PackageCache/com.cysharp.yetanotherhttphandler@37998fea90/ResponseContext.cs:165)
Cysharp.Net.Http.NativeHttpHandlerCore.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) (at ./Library/PackageCache/com.cysharp.yetanotherhttphandler@37998fea90/NativeHttpHandlerCore.cs:180)
Cysharp.Net.Http.YetAnotherHttpHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) (at ./Library/PackageCache/com.cysharp.yetanotherhttphandler@37998fea90/YetAnotherHttpHandler.cs:160)
Grpc.Net.Client.Internal.GrpcCall`2[TRequest,TResponse].RunCall (System.Net.Http.HttpRequestMessage request, System.Nullable`1[T] timeout) (at <c5934a35c2984bb2a85b6b44e1e1b051>:0)
Rethrow as RpcException: Status(StatusCode="Internal", Detail="Error starting gRPC call. HttpRequestException: request has unsupported HTTP version", DebugException="System.Net.Http.HttpRequestException: request has unsupported HTTP version")
Grpc.Net.Client.Internal.HttpClientCallInvoker.BlockingUnaryCall[TRequest,TResponse] (Grpc.Core.Method`2[TRequest,TResponse] method, System.String host, Grpc.Core.CallOptions options, TRequest request) (at <c5934a35c2984bb2a85b6b44e1e1b051>:0)
Grpc.Core.Interceptors.InterceptingCallInvoker.<BlockingUnaryCall>b__3_0[TRequest,TResponse] (TRequest req, Grpc.Core.Interceptors.ClientInterceptorContext`2[TRequest,TResponse] ctx) (at <9dfa77fee0fb42299bfdf37b7b76f40a>:0)
Grpc.Core.ClientBase+ClientBaseConfiguration+ClientBaseConfigurationInterceptor.BlockingUnaryCall[TRequest,TResponse] (TRequest request, Grpc.Core.Interceptors.ClientInterceptorContext`2[TRequest,TResponse] context, Grpc.Core.Interceptors.Interceptor+BlockingUnaryCallContinuation`2[TRequest,TResponse] continuation) (at <9dfa77fee0fb42299bfdf37b7b76f40a>:0)
Grpc.Core.Interceptors.InterceptingCallInvoker.BlockingUnaryCall[TRequest,TResponse] (Grpc.Core.Method`2[TRequest,TResponse] method, System.String host, Grpc.Core.CallOptions options, TRequest request) (at <9dfa77fee0fb42299bfdf37b7b76f40a>:0)
Helloworld.Greeter+GreeterClient.SayHello (Helloworld.HelloRequest request, Grpc.Core.CallOptions options) (at Assets/Scripts/HelloworldGrpc.cs:194)
Helloworld.Greeter+GreeterClient.SayHello (Helloworld.HelloRequest request, Grpc.Core.Metadata headers, System.Nullable`1[T] deadline, System.Threading.CancellationToken cancellationToken) (at Assets/Scripts/HelloworldGrpc.cs:183)
Calls.OnCallRPC () (at Assets/Calls.cs:57)
UnityEngine.Events.InvokableCall.Invoke () (at /Users/bokken/build/output/unity/unity/Runtime/Export/UnityEvent/UnityEvent.cs:178)
UnityEngine.Events.UnityEvent.Invoke () (at /Users/bokken/build/output/unity/unity/artifacts/generated/UnityEvent/UnityEvent_0.cs:57)
UnityEngine.UI.Button.Press () (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:70)
UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:114)
UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:57)
UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents+EventFunction`1[T1] functor) (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:272)
UnityEngine.EventSystems.EventSystem:Update() (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:530)
mayuki commented 6 months ago

If the server is non-HTTPS, you need to enforce HTTP/2. https://github.com/Cysharp/YetAnotherHttpHandler?tab=readme-ov-file#using-http2-over-cleartext-h2c

ApocalyVec commented 6 months ago

@mayuki Thank you! After forcing the handler to use Http2Only. Everything works now. Thank you so much for the quick response!

handler = new YetAnotherHttpHandler(){Http2Only = true}; // GRPC requires HTTP/2