123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- package httper
- import (
- "encoding/base64"
- "encoding/json"
- "fmt"
- "reflect"
- "strconv"
- "strings"
- "github.com/astaxie/beego/context"
- "go.uber.org/zap"
- )
- var (
- Debug = false
- DebugLog *zap.Logger
- )
- func FillRequireParams(ctx *context.Context, param interface{}, logID string) {
- v := reflect.ValueOf(param)
- if v.Kind() == reflect.Ptr {
- v = v.Elem()
- }
- if v.Kind() != reflect.Struct {
- SystemError("query is not a struct")
- }
- numField := v.NumField()
- for i := 0; i < numField; i++ {
- fillParams(ctx, v.Type().Field(i), v.Field(i))
- }
- if Debug && DebugLog != nil {
- data, _ := json.Marshal(param)
- DebugLog.Debug(logID, zap.String("request", string(data)))
- }
- }
- func furtherFillRequireParams(ctx *context.Context, param interface{}) {
- v := reflect.ValueOf(param)
- if v.Kind() == reflect.Ptr {
- v = v.Elem()
- }
- if v.Kind() != reflect.Struct {
- SystemError("query is not a struct")
- }
- numField := v.NumField()
- for i := 0; i < numField; i++ {
- fillParams(ctx, v.Type().Field(i), v.Field(i))
- }
- }
- func fillParams(ctx *context.Context, field reflect.StructField, val reflect.Value) {
- //fmt.Println(ctx.Input.Context.Request.Header)
- switch field.Tag.Get("in") {
- case "header":
- fillHeaderParams(ctx, field, val)
- case "body":
- fillBodyParams(ctx, field, val)
- case "path":
- fillPathParams(ctx, field, val)
- case "query":
- fillQueryParams(ctx, field, val)
- default:
- if !val.IsValid() || !val.CanAddr() || !val.CanSet() {
- SystemError("value can not set")
- }
- furtherFillRequireParams(ctx, val.Addr().Interface())
- }
- }
- func fillBodyParams(ctx *context.Context, field reflect.StructField, val reflect.Value) {
- if !val.IsValid() || !val.CanAddr() || !val.CanSet() {
- SystemError("value can not set")
- }
- if val.Kind() == reflect.Ptr {
- val = val.Elem()
- }
- body := ctx.Input.RequestBody
- switch field.Tag.Get("decode") {
- case "base64":
- body, _ = base64.StdEncoding.DecodeString(string(body))
- }
- if err := json.Unmarshal(body, val.Addr().Interface()); err != nil {
- BadParamer(fmt.Sprintf("%s is not json error:%s", "body", err))
- }
- CheckBodyFiled(val.Addr().Interface())
- }
- func CheckBodyFiled(param interface{}, logID ...interface{}) {
- v := reflect.ValueOf(param)
- if v.Kind() == reflect.Ptr {
- v = v.Elem()
- }
- if v.Kind() != reflect.Struct {
- SystemError("body is not a struct")
- }
- numField := v.NumField()
- for i := 0; i < numField; i++ {
- if v.Field(i).Kind() == reflect.Struct { //递归检查
- CheckBodyFiled(v.Field(i).Addr().Interface())
- }
- field := v.Type().Field(i)
- val := v.Field(i)
- if reflect.DeepEqual(val.Interface(), reflect.Zero(val.Type()).Interface()) {
- if field.Tag.Get("required") == "true" {
- jsonTag := field.Tag.Get("json")
- if jsonTag == "" {
- jsonTag = field.Name
- }
- def := field.Tag.Get("default")
- fillValue(v.Field(i), def, true, jsonTag)
- }
- }
- }
- }
- func fillHeaderParams(ctx *context.Context, field reflect.StructField, val reflect.Value) {
- jsonTag := field.Tag.Get("json")
- if jsonTag == "" {
- // 没有json标记,取变量的名称
- jsonTag = field.Name
- }
- var v string
- if v = ctx.Input.Header(jsonTag); v == "" {
- // 尝试将第一个字母转换为大写 测试环境使用 beego Swagger的bug
- firstUpperJsonTag := strings.ToUpper(jsonTag[0:1]) + string(jsonTag[1:])
- if v = ctx.Input.Header(firstUpperJsonTag); v == "" {
- v = field.Tag.Get("default")
- }
- }
- required := field.Tag.Get("required") == "true"
- if v == "" && required {
- BadParamer(fmt.Sprintf("%s is not exists in header", jsonTag))
- }
- fillValue(val, v, required, jsonTag)
- }
- func fillPathParams(ctx *context.Context, field reflect.StructField, val reflect.Value) {
- jsonTag := field.Tag.Get("json")
- if jsonTag == "" {
- // 没有json标记,取变量的名称
- jsonTag = field.Name
- }
- var v string
- if v = ctx.Input.Param(fmt.Sprintf(":%s", jsonTag)); v == "" {
- v = field.Tag.Get("default")
- }
- required := field.Tag.Get("required") == "true"
- if v == "" && required {
- BadParamer(fmt.Sprintf("%s is not exists in path", jsonTag))
- }
- fillValue(val, v, required, jsonTag)
- }
- func fillQueryParams(ctx *context.Context, field reflect.StructField, val reflect.Value) {
- jsonTag := field.Tag.Get("json")
- if jsonTag == "" {
- // 没有json标记,取变量的名称
- jsonTag = field.Name
- }
- var v string
- if v = ctx.Input.Query(jsonTag); v == "" {
- v = field.Tag.Get("default")
- }
- required := field.Tag.Get("required") == "true"
- if v == "" && required {
- BadParamer(fmt.Sprintf("%s is not exists in query", jsonTag))
- }
- fillValue(val, v, required, jsonTag)
- }
- func fillValue(val reflect.Value, requestVal string, required bool, jsonTag string) {
- if val.Kind() == reflect.Ptr {
- val = val.Elem()
- }
- kind := val.Kind()
- switch {
- case kind == reflect.Uint || kind == reflect.Uint8 || kind == reflect.Uint16 || kind == reflect.Uint32 || kind == reflect.Uint64:
- if requestVal == "" && !required {
- requestVal = "0"
- }
- v, err := strconv.ParseUint(requestVal, 10, 64)
- if err != nil {
- BadParamer(fmt.Sprintf("%s is not uint", jsonTag))
- }
- if !val.IsValid() || !val.CanSet() {
- SystemError("value can not set")
- }
- val.SetUint(v)
- case kind == reflect.Int || kind == reflect.Int64:
- if requestVal == "" && !required {
- requestVal = "0"
- }
- v, err := strconv.ParseInt(requestVal, 10, 64)
- if err != nil {
- BadParamer(fmt.Sprintf("%s is not uint", jsonTag))
- }
- if !val.IsValid() || !val.CanSet() {
- SystemError("value can not set")
- }
- val.SetInt(v)
- case kind == reflect.Float64:
- if requestVal == "" && !required {
- requestVal = "0"
- }
- v, err := strconv.ParseFloat(requestVal, 64)
- if err != nil {
- BadParamer(fmt.Sprintf("%s is not uint", jsonTag))
- }
- if !val.IsValid() || !val.CanSet() {
- SystemError("value can not set")
- }
- val.SetFloat(v)
- case kind == reflect.String:
- val.SetString(requestVal)
- default:
- BadParamer("type is not support")
- }
- }
|