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:在传输层验证请求/有效负载的主要内容,如果未能解决你的问题,请参考以下文章