gin handler wrapper

This commit is contained in:
w-mj 2023-04-03 16:48:31 +08:00
parent 5e02216d65
commit b50bd2c776
No known key found for this signature in database
GPG Key ID: 3A2CB5BE2F835897
2 changed files with 132 additions and 0 deletions

View File

@ -1,8 +1,14 @@
package utils
import (
"encoding/json"
"errors"
"fmt"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
"net/http"
"reflect"
"strconv"
)
func UnnamedPointer[T any](v T) *T {
@ -28,3 +34,104 @@ func GinErrorCheck(c *gin.Context, err error) bool {
}
return false
}
func setValue(data string, value reflect.Value) error {
switch value.Kind() {
case reflect.Bool:
break
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
v, err := strconv.ParseInt(data, 10, 64)
if err != nil {
return err
}
value.SetInt(int64(v))
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
v, err := strconv.ParseUint(data, 10, 64)
if err != nil {
return err
}
value.SetUint(v)
case reflect.Float32, reflect.Float64:
v, err := strconv.ParseFloat(data, 64)
if err != nil {
return err
}
value.SetFloat(v)
case reflect.Pointer:
return setValue(data, reflect.Indirect(value))
case reflect.String:
value.SetString(data)
case reflect.Struct:
err := json.Unmarshal([]byte(data), value.Pointer())
if err != nil {
return err
}
default:
log.Errorf("utils.setValue unsupported type %s", value.Type().Name())
return errors.New("unsupported type")
}
return nil
}
func routeWrapperHandler(handler any, names []string) func(ctx *gin.Context) {
return func(c *gin.Context) {
handlerFunc := reflect.ValueOf(handler)
handlerFuncType := handlerFunc.Type()
handlerFuncParamLen := handlerFuncType.NumIn()
if handlerFuncParamLen != len(names) {
panic("Handler func Param len != len(names)")
}
inputArgs := make([]reflect.Value, handlerFuncParamLen)
for i := 0; i < handlerFuncParamLen; i += 1 {
paraType := handlerFuncType.In(i)
var paraValue reflect.Value
if paraType.Kind() == reflect.Pointer {
paraValue = reflect.New(paraType.Elem())
} else {
paraValue = reflect.New(paraType)
}
v, ok := c.Get(names[i])
if ok {
paraValue.Set(reflect.ValueOf(v))
} else {
vs := c.Param(names[i])
if vs == "" {
vs = c.Query(names[i])
}
if vs != "" {
err := setValue(vs, paraValue)
if err != nil {
log.WithError(err).Error("Cannot set value")
continue
}
} else {
if paraValue.Kind() == reflect.Struct || (paraType.Kind() == reflect.Pointer && paraType.Elem().Kind() == reflect.Struct) {
err := c.BindJSON(paraValue.Interface())
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"ok": false,
"msg": fmt.Sprintf("Cannot BindJson %s: %s", paraType.Name(), err.Error())})
return
}
}
}
}
if paraType.Kind() == reflect.Pointer {
inputArgs[i] = paraValue
} else {
inputArgs[i] = paraValue.Elem()
}
}
out := handlerFunc.Call(inputArgs)
var ret = out[0].Interface()
if out[1].Interface() != nil {
var err = out[1].Interface().(error)
c.JSON(http.StatusInternalServerError, gin.H{"ok": false, "msg": err.Error()})
} else {
c.JSON(http.StatusOK, ret)
}
}
}
func RouteWrapper(r *gin.Engine, method string, route string, handler any, names []string) {
r.Handle(method, route, routeWrapperHandler(handler, names))
}

25
test/test_wrapper.go Normal file
View File

@ -0,0 +1,25 @@
package main
import (
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"k8s-manager/src/model"
"k8s-manager/src/utils"
)
func DataHandler(model model.DataModel, q1 string, q2 int) (map[string]any, error) {
s, _ := json.Marshal(model)
fmt.Println(string(s))
fmt.Printf("Call DataHandler %s %d\n", q1, q2)
return gin.H{"name": model.Name}, nil
}
func main() {
r := gin.Default()
utils.RouteWrapper(r, "GET", "/index", DataHandler, []string{"model", "q1", "q2"})
err := r.Run(":9000")
if err != nil {
fmt.Println(err)
}
}