Gokit:在传输层验证请求/有效负载

Posted

技术标签:

【中文标题】Gokit:在传输层验证请求/有效负载【英文标题】:Gokit: Validate request/payload in transport layer 【发布时间】:2021-01-25 10:45:23 【问题描述】:

我正在使用 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 不是有效数字,则从此处返回 400 Bad Request 响应。

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

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

请求/有效负载仅应在传输层中验证并且仅在请求/有效负载有效时才应调用服务层的假设是否有效?如果是,在这个例子中怎么做?

【问题讨论】:

【参考方案1】:

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

您有一个错误返回变量。用它来表示有问题。在 go grpc 模块中有一个 status package 用于返回带有状态码的错误。如果您返回带有状态码的错误,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。在 Go 中,它们位于 codes package。

【讨论】:

您的回答使我找到了解决方案。我开始在 go-kit 中寻找“类似状态包的东西”,并找到了 ServerErrorEncoder 函数的解决方案。谢谢。【参考方案2】:

您可以使用返回服务器选项的 ServerErrorEncoder(可以在 github.com/go-kit/kit/transport/server.go 中找到)。 基本上在您的传输层中,除了 Decode 和 Encode 函数之外,您还可以定义一个 YourErrorEncoderFunc() 函数,如下所示。这将捕获传输层中引发的任何错误。 YourErrorEncoderFunc(_ context.Context, err error, 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 响应中抛出和错误,这将在传输层停止。

【讨论】:

以上是关于Gokit:在传输层验证请求/有效负载的主要内容,如果未能解决你的问题,请参考以下文章

Nginx作为负载均衡服务介绍

11.负载均衡nginx

四层负载均衡技术

HAproxy七层负载均衡四层/七层负载均衡

四层和七层负载均衡的特点及常用负载均衡NginxHaproxyLVS对比

[转] 四层和七层负载均衡的特点及常用负载均衡NginxHaproxyLVS对比