如何在grpc的状态错误对象的详细信息中发送Custom proto
How to send Custom proto in Details of grpc's status error object
我正在尝试在我的 grpc 调用的错误响应中发送自定义 Proto。按照this,应该是可以的。
这是代码。
st := status.Newf(codes.NotFound, "user %s doesn't exist", req.Name)
desc := "The username Doesn't exist, please give a valid username"
customProtoError := &data.Error{
Message: "Check username",
Code: 1404,
Type: "Service",
DetailedMessage: desc,
}
st, err := st.WithDetails(customProtoError)
if err != nil {
panic(fmt.Sprintf("Unexpected error attaching metadata: %v", err))
}
我已经为这些 GRPC API 提供了 grpc 和 http 处理程序。
HTTP 服务器中使用的 Marshaler 是 github.com/gogo/gateway
mux := runtime.NewServeMux(
runtime.WithMarshalerOption(JSONContentType, &gateway.JSONPb{}))
HTTP and GRPC 服务器的配置可在此处获得。
当我尝试使用 HTTP 调用访问 API 时,这是我得到的响应。
HTTP 错误:
{
"error": "user kishore1 doesn't exist",
"code": 5,
"message": "user kishore1 doesn't exist",
"details": [
{
"type_url": "type.googleapis.com/data.Error",
"value": "Cg5DaGVjayB1c2VybmFtZRD8ChoHU2t5ZmxvdyI4VGhlIHVzZXJuYW1lIERvZXNuJ3QgZXhpc3QsIHBsZWFzZSBnaXZlIGEgdmFsaWQgdXNlcm5hbWU="
}
]
}
type_url
随 google 一起提供,因为它在 JSON 的 golang proto code. But this says Any
中的硬编码将被反序列化为嵌入式消息。
Grpc 客户端代码:
resp, err := client.GetUser(ctx, req)
if err != nil {
st := status.Convert(err)
for _, detail := range st.Details() {
switch t := detail.(type) {
case *pb.Error:
fmt.Println("Oops! Your request was rejected by the server.")
...
default:
fmt.Println("Error Received - ", detail, reflect.TypeOf(detail))
}
}
Grpc 错误:
Error Received - proto: not found *errors.prefixError
知道是什么原因造成的吗? HTTP 不会反序列化为嵌入式消息,GRPC 会给出 proto.NotFound
这可能是因为 gogo proto 是网关吗?我什至用 googleapis proto errdetails.BadRequest
尝试了同样的方法,但还是一样。
花了大约一天时间,我才发现问题是由于版本不兼容造成的。
所以这就是使用 gogo proto 时对我有用的方法。
对于 GRPC 错误,我不得不升级我的 grpc-gateway 版本并使用 gogo/status
而不是 grpc/status
github.com/gogo/status v1.1.0
github.com/grpc-ecosystem/grpc-gateway v1.14.5
对于 HTTP 错误,我不得不降级 golang/protobuf
github.com/golang/protobuf v1.3.2
我正在尝试在我的 grpc 调用的错误响应中发送自定义 Proto。按照this,应该是可以的。
这是代码。
st := status.Newf(codes.NotFound, "user %s doesn't exist", req.Name)
desc := "The username Doesn't exist, please give a valid username"
customProtoError := &data.Error{
Message: "Check username",
Code: 1404,
Type: "Service",
DetailedMessage: desc,
}
st, err := st.WithDetails(customProtoError)
if err != nil {
panic(fmt.Sprintf("Unexpected error attaching metadata: %v", err))
}
我已经为这些 GRPC API 提供了 grpc 和 http 处理程序。
HTTP 服务器中使用的 Marshaler 是 github.com/gogo/gateway
mux := runtime.NewServeMux(
runtime.WithMarshalerOption(JSONContentType, &gateway.JSONPb{}))
HTTP and GRPC 服务器的配置可在此处获得。 当我尝试使用 HTTP 调用访问 API 时,这是我得到的响应。
HTTP 错误:
{
"error": "user kishore1 doesn't exist",
"code": 5,
"message": "user kishore1 doesn't exist",
"details": [
{
"type_url": "type.googleapis.com/data.Error",
"value": "Cg5DaGVjayB1c2VybmFtZRD8ChoHU2t5ZmxvdyI4VGhlIHVzZXJuYW1lIERvZXNuJ3QgZXhpc3QsIHBsZWFzZSBnaXZlIGEgdmFsaWQgdXNlcm5hbWU="
}
]
}
type_url
随 google 一起提供,因为它在 JSON 的 golang proto code. But this says Any
中的硬编码将被反序列化为嵌入式消息。
Grpc 客户端代码:
resp, err := client.GetUser(ctx, req)
if err != nil {
st := status.Convert(err)
for _, detail := range st.Details() {
switch t := detail.(type) {
case *pb.Error:
fmt.Println("Oops! Your request was rejected by the server.")
...
default:
fmt.Println("Error Received - ", detail, reflect.TypeOf(detail))
}
}
Grpc 错误:
Error Received - proto: not found *errors.prefixError
知道是什么原因造成的吗? HTTP 不会反序列化为嵌入式消息,GRPC 会给出 proto.NotFound
这可能是因为 gogo proto 是网关吗?我什至用 googleapis proto errdetails.BadRequest
尝试了同样的方法,但还是一样。
花了大约一天时间,我才发现问题是由于版本不兼容造成的。 所以这就是使用 gogo proto 时对我有用的方法。
对于 GRPC 错误,我不得不升级我的 grpc-gateway 版本并使用 gogo/status
而不是 grpc/status
github.com/gogo/status v1.1.0
github.com/grpc-ecosystem/grpc-gateway v1.14.5
对于 HTTP 错误,我不得不降级 golang/protobuf
github.com/golang/protobuf v1.3.2