hertz icon indicating copy to clipboard operation
hertz copied to clipboard

A collison between hertz customed type binding and 'required' tag check

Open iksars opened this issue 2 years ago • 1 comments

Describe the Question I use hertz thrift code generation for my project and I meet a problem about binding param of customed Type. I mark the customed type with "required" tag and "api.header=' X-Authorization-TokenPayload'" tag in the thrift file. Then I inject the customed bindConfig into hertz server . When there is a filed named 'X-Authorization-TokenPayload' in request header, it works well. However , when there is not a filed named that, I hope that hertz can throw a bind error but actually it doesn't. It seems that "required" tag can't work because of customed bind func. Is it a bug? If not, how can I solve it? (hz version v0.6.5)

idl define:

struct CreateUploadTaskReq {
    1: required base.TokenPayload TokenPayload (api.header="X-Authorization-TokenPayload");   
    2: .....  
}

customed bindconfig:

func bindTokenPayloadConfig() *binding.BindConfig {
	bindConfig := &binding.BindConfig{}
	bindConfig.MustRegTypeUnmarshal(reflect.TypeOf(base.TokenPayload{}), func(req *protocol.Request, params param.Params, text string) (reflect.Value, error) {
		hlog.Info("tokenpayload", "text:", text)
		if text == "" {
			return reflect.ValueOf(base.TokenPayload{}), errors.New("tokenpayload is required but not found")
		}
		val := base.TokenPayload{}
		if err := json.Unmarshal([]byte(text), &val); err != nil {
			return reflect.ValueOf(base.TokenPayload{}), err
		}
		return reflect.ValueOf(val), nil
	})
	return bindConfig
}

iksars avatar Nov 26 '23 03:11 iksars

The previous idea was that a custom binding would allow the user to do all the actions for that field, but it seems like Required shouldn't be done by the user. So I'll put the Required validation into hertz. I'll mention a pr.

FGYFFFF avatar Nov 27 '23 03:11 FGYFFFF

type ExchangeOauth2CodeReq struct {
	// 标记
	State string `thrift:"State,1,required" validate:"required"`
	// code
	Code string `thrift:"Code,2,required" validate:"required"`
}

func Ping(c context.Context, ctx *app.RequestContext) {
	req := idl_plugin.ExchangeOauth2CodeReq{}
	err := ctx.BindAndValidate(&req)
	if err != nil {
		ResponseErr(ctx, fmt.Errorf("BindAndValidate error: %w", err))
		return
	}
	ctx.JSON(http.StatusOK, req)
}

curl "127.0.0.1:6789/ping" -d '{"State":"xxx", "Code":"xxx"}' -H "content-type: application/json" -H "State: abc"
// {"State":"abc","Code":"xxx"}

hertz 的 validate:"required" tag 会自动绑定 header 的同名字段, 并覆盖到 body 里面, 这个问题会影响接口安全, 导致body 内容被覆盖

archever avatar Jul 17 '24 07:07 archever

curl "127.0.0.1:6789/open/api/v1/ping?State=abc" -d '{"State":"xxx", "Code":"xxx"}' -H "content-type: application/json" 
// {"State":"abc","Code":"xxx"}

query 里面也会覆盖掉

archever avatar Jul 17 '24 07:07 archever