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  }