【问题标题】:How can I unpack the grpc status.details error in golang?如何解压 golang 中的 grpc status.details 错误?
【发布时间】:2020-09-05 14:38:47
【问题描述】:

我想为我的 REST API 使用 google.golang.org/grpc/status 错误模型,因为它说你可以:

Status 类型定义了适用于不同编程环境的逻辑错误模型,包括 REST API 和 RPC API。

但是我遇到了结构的details 部分的问题。我知道它是[]*anypb.Any 类型,但是,我不清楚如何将其转换为“解包”形式,以便我可以看到字段和描述属性,而不是base64 编码的value 字段。

我得到了什么:

{
    "code": 3,
    "message": "One or more fields are invalid",
    "details": [
        {
            "type_url": "type.googleapis.com/google.rpc.BadRequest.FieldViolation",
            "value": "CgVFbWFpbBIUSW52YWxpZCBlbWFpbCBmb3JtYXQ="
        },
        {
            "type_url": "type.googleapis.com/google.rpc.BadRequest.FieldViolation",
            "value": "CghQYXNzd29yZBIeTXVzdCBiZSBhdCBsZWFzdCAxMCBjaGFyYWN0ZXJz"
        }
    ]
}

我应该得到什么:

{
    "code": 3,
    "message": "One or more fields are invalid",
    "details": [
        {
            "type_url": "type.googleapis.com/google.rpc.BadRequest.FieldViolation",
            "field": "Email",
            "description": "Invalid email format"
        },
        {
            "type_url": "type.googleapis.com/google.rpc.BadRequest.FieldViolation",
            "field": "Password",
            "description": "Must be at least 10 characters"
        }
    ]
}

示例代码:

package main

import (
    "encoding/base64"
    "encoding/json"
    "fmt"
    "net/http"

    "github.com/go-chi/chi"
    "github.com/go-chi/chi/middleware"
    "google.golang.org/genproto/googleapis/rpc/errdetails"
    "google.golang.org/grpc/codes"
    "google.golang.org/grpc/status"
)


func main ()  {

    r := chi.NewRouter()
    r.Use(middleware.Logger)
    r.Get("/", func(w http.ResponseWriter, r *http.Request) {

        err := getError()
        st, _ := status.FromError(err)

        p:= st.Proto()

        w.Header().Set("content-type","application/json")
        err = json.NewEncoder(w).Encode(p)

        if err !=nil {
            fmt.Println("Error encoding", err)
        }

    })

    http.ListenAndServe(":3000", r)
}


func getError() error {

    st := status.New(codes.InvalidArgument, "One or more fields are invalid")

    f1 := &errdetails.BadRequest_FieldViolation{
        Field:                "Email",
        Description:          "Invalid email format",
    }

    f2 := &errdetails.BadRequest_FieldViolation{
        Field:                "Password",
        Description:          "Must be at least 10 characters",
    }

    st, _ = st.WithDetails(f1)
    st, _ = st.WithDetails(f2)

    return st.Err()
}


【问题讨论】:

    标签: go grpc grpc-go


    【解决方案1】:

    json 编码器并非 100% 兼容 protobuf。

    改用"google.golang.org/protobuf/encoding/protojson" 中的protojson.Marshal

    看到这个Playground

    虽然没有那么快。

    编辑回答更快替代方案的请求:

    可以利用自定义错误结构来保存所有必需的数据并手动解开 grpc 状态及其详细信息。请参阅此playground。在我的机器上,这节省了大约 15% 的时间。

    【讨论】:

    • 谢谢!这似乎行得通。您对可能更快的替代策略有什么想法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-15
    • 2018-11-05
    • 2018-01-09
    • 1970-01-01
    • 2016-01-25
    • 1970-01-01
    相关资源
    最近更新 更多