github.com/artisanhe/tools@v1.0.1-0.20210607022958-19a8fef2eb04/httplib/trans_to_req.go (about)

     1  package httplib
     2  
     3  import (
     4  	"go/ast"
     5  	"reflect"
     6  
     7  	"github.com/gin-gonic/gin"
     8  	"github.com/sirupsen/logrus"
     9  
    10  	"github.com/artisanhe/tools/courier/transport_http/transform"
    11  	"github.com/artisanhe/tools/reflectx"
    12  )
    13  
    14  type Request interface {
    15  	Handle(c *gin.Context)
    16  }
    17  
    18  func TypeOfRequest(request Request) reflect.Type {
    19  	requestInterface := reflect.Indirect(reflect.ValueOf(request)).Interface()
    20  	return reflect.Indirect(reflect.ValueOf(requestInterface)).Type()
    21  }
    22  
    23  func TransToReq(c *gin.Context, reqModel interface{}) error {
    24  	reflectValue := reflect.ValueOf(reqModel)
    25  	return TransToReqByReflectValue(c, reflectValue)
    26  }
    27  
    28  func TransToReqByReflectValue(c *gin.Context, rv reflect.Value) error {
    29  	group := transform.ParameterGroupFromReflectValue(rv)
    30  	return transform.MarshalParameters(group, &ParameterValuesGetter{
    31  		ParameterValuesGetter: transform.NewParameterValuesGetter(c.Request),
    32  		Group: group,
    33  		C:     c,
    34  	})
    35  }
    36  
    37  type ParameterValuesGetter struct {
    38  	*transform.ParameterValuesGetter
    39  	Group *transform.ParameterGroup
    40  	C     *gin.Context
    41  }
    42  
    43  func (getter *ParameterValuesGetter) Initial() error {
    44  	if getter.Group.Context.Len() > 0 {
    45  		for _, parameterMeta := range getter.Group.Context {
    46  			contextValue, contextExists := getter.C.Get(parameterMeta.Name)
    47  			if !contextExists {
    48  				logrus.Panicf("read req %s context failed!", parameterMeta.Name)
    49  			}
    50  			reflectx.SetValue(parameterMeta.Value, parameterMeta.Field.Type, contextValue)
    51  		}
    52  	}
    53  	return getter.ParameterValuesGetter.Initial()
    54  }
    55  
    56  func (getter *ParameterValuesGetter) Param(name string) string {
    57  	return getter.C.Param(name)
    58  }
    59  
    60  func checkRequestTypeSettings(tpe reflect.Type) {
    61  	for tpe.Kind() == reflect.Ptr {
    62  		tpe = tpe.Elem()
    63  	}
    64  
    65  	for i := 0; i < tpe.NumField(); i++ {
    66  		field := tpe.Field(i)
    67  		if !ast.IsExported(field.Name) {
    68  			continue
    69  		}
    70  
    71  		if field.Anonymous {
    72  			checkRequestTypeSettings(field.Type)
    73  			continue
    74  		}
    75  
    76  		_, exists := field.Tag.Lookup("in")
    77  		if !exists {
    78  			logrus.Panicf("missing tag `in` on struct field `%s.%s[%s]`", tpe.PkgPath(), tpe.Name(), field.Name)
    79  		}
    80  	}
    81  }
    82  
    83  func FromRequest(request Request) gin.HandlerFunc {
    84  	requestType := TypeOfRequest(request)
    85  	checkRequestTypeSettings(requestType)
    86  
    87  	return func(c *gin.Context) {
    88  		requestReflectValue := reflect.New(requestType)
    89  
    90  		err := TransToReqByReflectValue(c, requestReflectValue)
    91  
    92  		if err != nil {
    93  			WriteError(c, err)
    94  			c.Abort()
    95  			return
    96  		}
    97  
    98  		requestReflectValue.Interface().(Request).Handle(c)
    99  	}
   100  }