package handler import ( "git.icechen.cn/monorepo/backend/app/brahma/api/murder/internal/error_process" "git.icechen.cn/monorepo/backend/app/brahma/api/murder/internal/model" "github.com/gofiber/fiber/v2" "github.com/google/uuid" "github.com/pkg/errors" "github.com/spf13/cast" "reflect" "strings" ) type pluginFunc func(interface{}) error func checkParam(body interface{}, ctx *fiber.Ctx, plugins ...pluginFunc) error { //第一次执行解析body,并且调用插件方法 if ctx != nil { err := ctx.BodyParser(body) if err != nil { return error_process.CommonErr(err) } for _, plugin := range plugins { if err = plugin(body); err != nil { return err } } } //step1 校验是否是指针 typ := reflect.TypeOf(body) val := reflect.ValueOf(body) if val.Kind().String() != reflect.Ptr.String() { return errors.New(error_process.NoPointError) } if val.IsNil() { return errors.New(error_process.NilPointError) } num := val.Elem().NumField() for i := 0; i < num; i++ { kind := val.Elem().Field(i).Kind().String() switch kind { case reflect.Ptr.String(): //显示指定某些指针跳过校验 if tag := typ.Elem().Field(i).Tag.Get("valid"); tag == "omitempty" { continue } //递归调用 if err := checkParam(val.Elem().Field(i).Interface(), nil); err != nil { return err } default: //非空值验证 if tag := typ.Elem().Field(i).Tag.Get("valid"); tag == "no_empty" { switch kind { case reflect.Ptr.String(): if val.Elem().Field(i).IsNil() == true { return error_process.EmptyValueErr(typ.Elem().Field(i).Tag.Get("json")) } case reflect.Slice.String(): if val.Elem().Field(i).IsNil() == true || val.Elem().Field(i).Len() == 0 { return error_process.EmptyValueErr(typ.Elem().Field(i).Tag.Get("json")) } default: if val.Elem().Field(i).IsZero() { return error_process.EmptyValueErr(typ.Elem().Field(i).Tag.Get("json")) } } } } //指定制验证 if values := typ.Elem().Field(i).Tag.Get("value"); values != "" { eles := make([]string, 0) if eles = strings.Split(values, "|"); len(eles) == 0 { continue } switch kind { case reflect.Int.String(): for _, v := range eles { if b := val.Elem().Field(i).Int(); b == cast.ToInt64(v) { //匹配到值定制跳出此次tag处理方法 goto LOOP } } return errors.New(error_process.IllegalValueError) default: return errors.New(error_process.BodyParserErr) } } LOOP: } return nil } //tag uuid 覆盖写 func tagUuidPlugin(body interface{}) error { if req, ok := body.(*TagReq); ok { if req.Tag == nil { return errors.New(error_process.BodyParserErr) } //if req.Tag.Uuid == "" { // req.Tag.Uuid = xid.New().String() //} return nil } return errors.New(error_process.BodyParserErr) } //category uuid 覆盖写 func categoryUuidPlugin(body interface{}) error { if req, ok := body.(*CategoryReq); ok { if req.Category == nil { return errors.New(error_process.BodyParserErr) } if req.Category.Uuid == "" { req.Category.Uuid = uuid.New().String() } return nil } return errors.New(error_process.BodyParserErr) } //script uuid 覆盖写 func scriptUuidPlugin(body interface{}) error { if req, ok := body.(*model.Scripts); ok { if req == nil { return errors.New(error_process.BodyParserErr) } if req.Uuid == "" { req.Uuid = uuid.New().String() } return nil } return errors.New(error_process.BodyParserErr) } func createTagParamCheck(body interface{}, ctx *fiber.Ctx) error { return checkParam(body, ctx, tagUuidPlugin) } func createCategoryParamCheck(body interface{}, ctx *fiber.Ctx) error { return checkParam(body, ctx, categoryUuidPlugin) } func createScriptParamCheck(body interface{}, ctx *fiber.Ctx) error { return checkParam(body, ctx, scriptUuidPlugin) }