Gokit:在传输层验证request/payload

Gokit: Validate request/payload in transport layer

我正在使用 go-kit 创建 RPC 端点。我正在创建这样的端点

httptransport.NewServer(
    endPoint.MakeGetBlogEndPoint(blogService),
    transport.DecodeGetBlogRequest,
    transport.EncodeGetBlogResponse

下面是我的 DecodeGetBlogRequest 函数

func DecodeGetBlogRequest(c context.Context, r *http.Request) (interface{}, error) {
        vars := mux.Vars(r)
        id, err := strconv.Atoi(vars["id"])
        if err != nil {
            return nil, err
        }
        req := endPoint.GetBlogRequest{
            ID: id,
        }
        return req, nil
    }

我想做的是验证这个函数中的 HTTP 请求,如果发现无效,只从这里发送一个带有有效错误代码的响应,而不将它传递给服务层。即,如果 ID 不是有效数字,return 400 Bad Request 来自此处的响应。

但是因为我在这个函数中没有 ResponseWriter 引用,所以我不知道该怎么做。

我正在关注 go-kit 文档中的这个示例 https://gokit.io/examples/stringsvc.html

request/payload 仅应在传输层中验证并且仅当 request/payload 有效时才应调用服务层是否是一个有效的假设?如果是,在本例中如何操作?

不能 100% 确定这是否也适用于 go-kit grpc:

您有一个错误 return 变量。用它来表示有问题。在 go grpc 模块中有一个 status package 到 return 错误状态代码。如果你 return 一个带有状态代码的错误,grpc 层将从错误中获取代码并将其发回。

例如:

func DecodeGetBlogRequest(c context.Context, r *http.Request) (interface{}, error) {
        vars := mux.Vars(r)
        id, err := strconv.Atoi(vars["id"])
        if err != nil {
            return nil, status.Error(codes.InvalidArgument, err.Error())
        }
        req := endPoint.GetBlogRequest{
            ID: id,
        }
        return req, nil
    }

另请注意,grpc 使用 different status codes. In Go they are located in the codes package

您可以使用 returns 服务器选项的 ServerErrorEncoder(可以在 github.com/go-kit/kit/transport/server.go 中找到)。 基本上在您的传输层中,除了 Decode 和 Encode 函数之外,您还可以定义一个 YourErrorEncoderFunc() 函数,如下所示。这将捕获传输层中抛出的任何错误。
YourErrorEncoderFunc(_ context.Context, 错误错误, w http.ResponseWriter).

您需要将此功能作为一个选项附加到您的端点注册中,例如:

ABCOpts := []httptransport.ServerOption{
            httptransport.ServerErrorEncoder(YourErrorEncoderFunc),
            }

r.Methods("GET").Path("/api/v1/abc/def").Handler(httptransport.NewServer(
    endpoints.GetDataEndpoint,
    DecodeGetRequest,
    EncodeGetResponse,
    ABCOpts...,
))

如果您的请求验证无效,这将在传输层停止,并根据您在 YourErrorEncoderFunc() 中编写的任何格式在 http 响应中抛出错误。