英文:
Can you use a HTTP2 request to successfully call a gRPC service?
问题
由于grpc建立在http2之上,您可以使用http请求直接调用grpc服务吗?
例如,如果您使用以下proto启动了一个grpc服务:
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
然后,发送一个curl请求到本地主机和端口号:
curl --http2 -H "Content-Type: application/grpc+proto" -d '{"name": "test"}' http://localhost:50051/io.grpc.examples.helloworld.Greeter/SayHello
这是否受支持?我收到以下错误:
io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2Exception: Unexpected HTTP/1.x request: POST /io.grpc.examples.helloworld.Greeter/SayHello
我不确定我是否调用错误,或者是否不可能这样做。除了使用curl,我还尝试使用Java的HttpClient,但出现了相同的错误。关于这个问题的任何信息都会受到欢迎,谢谢。
英文:
Since grpc is built on top of http2, can you use an http request to directly call a grpc service?
For example, if you start a grpc service with the following proto:
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
Then send a curl request to that service at localhost and the port number:
curl --http2 -H "Content-Type: application/grpc+proto" -d "{\"name\": \"test\"}" http://localhost:50051/io.grpc.examples.helloworld.Greeter/SayHello
Is this suppported? I get the following error:
io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2Exception: Unexpected HTTP/1.x request: POST /io.grpc.examples.helloworld.Greeter/SayHello
I'm not sure if I am making the call incorrectly, or if this isn't possible. Besides using curl, I've also tried using Java's HttpClient, which gave me the same error. Any info on this is appreciated, thanks
答案1
得分: 3
你可以这样做,但你需要遵循gRPC的消息帧格式,它是二进制的。此外,大多数gRPC服务器不支持JSON编码的消息。所以下面是一个protobuf版本的示例:
$ echo -en '\x00\x00\x00\x00\x06\x0a\x04test' | curl --http2-prior-knowledge --header "Content-Type: application/grpc" --header "TE: trailers" --data-binary @- http://localhost:50051/helloworld.Greeter/SayHello | xxd
00000000: 0000 0000 0c0a 0a48 656c 6c6f 2074 6573 .......Hello tes
00000010: 74 t
请求的分解如下:
\x00\x00\x00\x00\x06
。5字节的gRPC帧头。第一个00
是一个标志字节,没有设置标志位。最后四个字节是6字节的消息长度。\x0a\x04test
。protobuf消息。0a
包含字段类型和标签号。04
是随后字符串 "test" 的长度。
你可以看到响应也是二进制的gRPC和protobuf,与请求以相同的格式。
你看到的错误通过 --http2-prior-knowledge
修复了。它告诉curl不要使用明文的HTTP/1.1升级到HTTP/2,而是直接开始使用HTTP/2。RFC 9113废弃了HTTP/1.1升级方法,而采用了这种先验知识方法。
英文:
You can, but you need to follow gRPC's message framing format which is binary. Also, most grpc servers don't support JSON-encoded messages. So here's a protobuf version:
$ echo -en '\x00\x00\x00\x00\x06\x0a\x04test' | curl --http2-prior-knowledge --header "Content-Type: application/grpc" --header "TE: trailers" --data-binary @- http://localhost:50051/helloworld.Greeter/SayHello | xxd
00000000: 0000 0000 0c0a 0a48 656c 6c6f 2074 6573 .......Hello tes
00000010: 74 t
The request's break-down:
\x00\x00\x00\x00\x06
. 5 byte gRPC frame header. The first00
is a flag byte with no flags set. The last four bytes are the message length of 6 bytes.\x0a\x04test
. The protobuf message.0a
contains the field type and tag number. The04
is the length of the following string "test".
You can see how the response was also binary grpc and protobuf in the same format as the request.
The error you were seeing is fixed by --http2-prior-knowledge
. It tells curl not to use the plaintext HTTP/1.1 Upgrade to HTTP/2 and instead just start directly with HTTP/2. RFC 9113 deprecated the HTTP/1.1 Upgrade approach for HTTP/2 in favor of this prior knowledge approach.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论