使用 http Mux 请求正文验证
Posted
技术标签:
【中文标题】使用 http Mux 请求正文验证【英文标题】:Request body validation with http Mux 【发布时间】:2020-07-25 14:18:22 【问题描述】:我正在尝试使用 Go 和 Mux 构建 API。我正在尝试验证传入的请求。我尝试在 Struct 上使用标签并使用 Go Validator 对其进行验证。
这是我的结构
type Address struct
Street string `validate:"required"`
City string `validate:"required"`
Phone string `validate:"required"`
我的问题是
有一个POST
端点,所有字段都将通过并且验证不会失败。但是,还有另一个 PATCH
端点,并非 Address
结构的所有字段都会通过,因此验证失败。
例如。 API 可能会收到
"Street": "Dummy"
在这种情况下验证POST
和PATCH
请求的最佳方法是什么。
【问题讨论】:
【参考方案1】:在 PATCH 端点中使用具有不同(如果有)验证标签的不同类型。之后转换为地址:
// Same underlying type as Address, but no validation tags
var x struct
Street string
City string
Phone string
// Decode request into x, then:
addr := Address(x)
【讨论】:
谢谢。在这种情况下,如果我们添加一个新字段,那么我们必须在所有正确创建的类型中更改它。 是的。编译器会确保你不会忘记一个。【参考方案2】:改变我的答案
我已经对您的案例进行了测试并找到了解决方案,您必须使用struct level validation。这是我在您的案例中的功能:
func PostRequestValidation(sl validator.StructLevel)
address := sl.Current().Interface().(Address)
jsonMarshal, _ := json.Marshal(address)
var m map[string]interface
_ = json.Unmarshal(jsonMarshal, &m)
for key, val := range m
if len(fmt.Sprintf("%s", val)) == 0
sl.ReportError(val, key, key, "post", "")
func PutRequestValidation(sl validator.StructLevel)
address := sl.Current().Interface().(Address)
isValid := false
jsonMarshal, _ := json.Marshal(address)
var m map[string]interface
_ = json.Unmarshal(jsonMarshal, &m)
for _, val := range m
if len(fmt.Sprintf("%s", val)) > 0
isValid = true
if !isValid
sl.ReportError(address, "address", "Adress", "put", "")
您只需在每个验证请求上注册
// ON POST REQUEST
validate = validator.New()
validate.RegisterTagNameFunc(func(fld reflect.StructField) string
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
if name == "-"
return ""
return name
)
validate.RegisterStructValidation(PostRequestValidation, Address)
// ON PUT REQUEST
validate = validator.New()
validate.RegisterTagNameFunc(func(fld reflect.StructField) string
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
if name == "-"
return ""
return name
)
validate.RegisterStructValidation(PutRequestValidation, Address)
您可以从我的source code 复制以获得更详细的源代码。
【讨论】:
感谢您的指点。但是使用上述方法之一会使 POST 请求无效,因为在 POST 中我们需要所有字段。这里有什么建议吗? aha,所以如果你需要多个这样的条件,你可以使用 Or 运算符。以街道字符串validate:"required|required_without_all"
为例。替换每个字段的验证。我将根据此评论更新我的答案。您应该根据评论更新您的问题。
我已经更新了这个问题。现在说清楚了:) 这仍然不起作用 - or 条件无法正确评估。说PATCH
我不需要City
,但POST
需要City
。即使未提供 City
,使用 or 条件也可以验证 POST
有效负载。
嗨,我希望你可以根据你的需要修改我的代码,对不起我之前的回答,它具有误导性。如果您回答了这个问题,请不要忘记将此问题标记为已解决。【参考方案3】:
找到这个库 - govalidator。这允许根据要求为每个请求创建规则。对于 POST 请求,创建一组规则,所有字段均为必填项。对于 PATCH 请求,创建所有字段为可选的规则。
【讨论】:
以上是关于使用 http Mux 请求正文验证的主要内容,如果未能解决你的问题,请参考以下文章
使用 webargs 验证 AWS lambda 中的查询字符串参数和请求正文
如何在 NestJS 控制器处理程序的请求中获取“已验证的正文”和“已验证的用户”?