github.com/profzone/eden-framework@v1.0.10/pkg/courier/transport_http/transform/parameter_group.go (about) 1 package transform 2 3 import ( 4 "go/ast" 5 "reflect" 6 "strings" 7 8 "github.com/sirupsen/logrus" 9 10 "github.com/profzone/eden-framework/pkg/courier/status_error" 11 "github.com/profzone/eden-framework/pkg/reflectx" 12 ) 13 14 func ParameterGroupFromValue(v interface{}) (m *ParameterGroup) { 15 return ParameterGroupFromReflectValue(reflect.ValueOf(v)) 16 } 17 18 func ParameterGroupFromReflectValue(rv reflect.Value) (group *ParameterGroup) { 19 rv = reflect.Indirect(rv) 20 MustStructValue("ParameterGroupFromReflectValue", rv) 21 group = &ParameterGroup{} 22 group.Value = rv 23 group.Scan() 24 return group 25 } 26 27 type ParameterGroup struct { 28 Parameters ParameterMap 29 Context ParameterMap 30 FormData ParameterMap 31 Body *ParameterMeta 32 Value reflect.Value 33 } 34 35 func (m *ParameterGroup) ValidateNoBodyByHook() (bool, status_error.ErrorFields) { 36 rv := m.Value 37 tpe := rv.Type() 38 39 errFields := status_error.ErrorFields{} 40 41 for i := 0; i < rv.NumMethod(); i++ { 42 method := rv.Method(i) 43 validateMethod := tpe.Method(i) 44 validatePrefix := "Validate" 45 fieldName := strings.TrimPrefix(validateMethod.Name, validatePrefix) 46 if validatePrefix+fieldName == validateMethod.Name { 47 if parameterMeta, ok := m.Parameters.Get(fieldName); ok { 48 if validateFn, ok := method.Interface().(func() string); ok { 49 msg := validateFn() 50 if msg != "" { 51 errFields = append(errFields, status_error.NewErrorField(parameterMeta.In, parameterMeta.Name, msg)) 52 } 53 54 } 55 } 56 } 57 } 58 59 return len(errFields) == 0, errFields 60 } 61 62 func (m *ParameterGroup) Scan() { 63 m.Parameters = ParameterMap{} 64 m.FormData = ParameterMap{} 65 m.Context = ParameterMap{} 66 m.scan(m.Value) 67 } 68 69 func (m *ParameterGroup) scanFormData(field *reflect.StructField, rv reflect.Value, tagInFlags map[string]bool) { 70 indirectRv := reflect.Indirect(rv) 71 72 tpe := reflectx.IndirectType(field.Type) 73 74 if indirectRv.Kind() != reflect.Struct { 75 if _, hasTagIn, tagInFlags := GetTagIn(field); hasTagIn { 76 m.FormData.Add(NewParameterMeta(field, rv, "formData", tagInFlags)) 77 } 78 return 79 } 80 81 for i := 0; i < tpe.NumField(); i++ { 82 f := tpe.Field(i) 83 84 if !ast.IsExported(f.Name) { 85 continue 86 } 87 88 fieldValue := indirectRv.Field(i) 89 90 if f.Anonymous { 91 m.scanFormData(&f, fieldValue, tagInFlags) 92 continue 93 } 94 95 m.FormData.Add(NewParameterMeta(&f, fieldValue, "formData", tagInFlags)) 96 } 97 } 98 99 func (m *ParameterGroup) scan(rv reflect.Value) { 100 rv = reflect.Indirect(rv) 101 102 if rv.Kind() != reflect.Struct { 103 return 104 } 105 106 tpe := rv.Type() 107 for i := 0; i < tpe.NumField(); i++ { 108 field := tpe.Field(i) 109 if !ast.IsExported(field.Name) { 110 continue 111 } 112 113 fieldValue := rv.Field(i) 114 tagIn, hasTagIn, tagInFlags := GetTagIn(&field) 115 116 if !hasTagIn { 117 if field.Anonymous { 118 m.scan(fieldValue) 119 continue 120 } 121 logrus.Panicf("%s.%s has no \"in\" tag", tpe.Name(), field.Name) 122 } 123 124 parameterMeta := NewParameterMeta(&field, fieldValue, tagIn, tagInFlags) 125 126 switch parameterMeta.In { 127 case "formData": 128 m.scanFormData(&field, fieldValue, tagInFlags) 129 case "body": 130 m.Body = parameterMeta 131 case "context": 132 // todo removed context 133 m.Context.Add(parameterMeta) 134 default: 135 m.Parameters.Add(parameterMeta) 136 } 137 } 138 }