1 Star 2 Fork 3

kristas/booting-go

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
controller_inject_plugin.go 4.91 KB
一键复制 编辑 原始数据 按行查看 历史
kristas 提交于 2021-04-02 18:53 . feat: add filter function
package iris_restful_plugin
import (
"fmt"
"gitee.com/kristas/booting-go/framework/common/tool/reflectx"
"gitee.com/kristas/booting-go/framework/common/util/lang"
"gitee.com/kristas/booting-go/framework/common/util/list"
"gitee.com/kristas/booting-go/framework/core/bean"
. "gitee.com/kristas/booting-go/framework/core/bean_factory"
"gitee.com/kristas/booting-go/framework/web"
"gitee.com/kristas/booting-go/framework/web/web_processor"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/context"
"reflect"
"sync"
)
var (
Path = "path"
Query = "query"
Body = "body"
Header = "header"
Form = "form"
Multipart = "multipart"
Context = "context"
)
var (
methodDefine = list.NewList("GET", "POST", "PUT", "PATCH", "DELETE")
sourceDefine = list.NewList(Path, Query, Body, Form, Header, Multipart, Context)
defaultSource = Query
irisApp *iris.Application
once sync.Once
methodMappingPattern = "%s_" // like field named FindEmployee mapping to method FindEmployee_()
)
type valueGetter func(context.Context) interface{}
type Param struct {
name string
source string
typ reflect.Type
}
func (r Param) String() string {
return fmt.Sprintf("Param:{name:%s, source:%s, type: %s}", r.name, r.source, r.typ.String())
}
func RestfulPlugin(b bean.Bean) {
once.Do(func() {
irisApp = GetBean("iris_app").(*iris.Application)
})
reflectx.WalkStructField(b, func(field reflect.StructField, value reflect.Value) {
if isRouteAPI(field) {
if method, ok := reflect.TypeOf(b).MethodByName(methodName(field)); ok {
httpMethod, url := findHttpMethodAndUrl(field)
paramMap := buildParam(field.Tag.Get("param"), method.Type)
getters := buildValueGetter(method, paramMap)
methodVal := reflect.ValueOf(b).MethodByName(methodName(field))
handleIrisApi(httpMethod, url, getters, methodVal)
}
}
})
}
func isRouteAPI(field reflect.StructField) bool {
var api web.API
if field.Type == reflect.TypeOf(api) {
return true
}
return false
}
func findHttpMethodAndUrl(field reflect.StructField) (string, string) {
method, ok := methodDefine.Find(func(item interface{}) bool {
_, ok := field.Tag.Lookup(item.(string))
return ok
})
if ok {
return method.(string), field.Tag.Get(method.(string))
}
panic("legal url not found in " + field.Name)
}
func handleIrisApi(httpMethod, url string, getters []valueGetter, methodVal reflect.Value) {
irisApp.Handle(httpMethod, url, func(c context.Context) {
err := web_processor.StartFilterChan(c.ResponseWriter(), c.Request())
if err != nil {
c.JSON(err.Error())
return
}
values := getValuesFromContext(c, getters)
resultValue := methodVal.Call(values)
result := transferValue2Interface(resultValue)
handleResult(c, result)
c.Next()
})
}
func getValuesFromContext(c context.Context, getters []valueGetter) []reflect.Value {
var in []reflect.Value
for i := range getters {
in = append(in, reflect.ValueOf(getters[i](c)))
}
return in
}
func transferValue2Interface(values []reflect.Value) []interface{} {
var result []interface{}
for i := range values {
result = append(result, values[i].Interface())
}
return result
}
func handleResult(c context.Context, r []interface{}) {
switch len(r) {
case 0:
c.JSON(nil)
return
case 1:
formatResult(c, r[0])
return
default:
formatResult(c, r)
}
}
func formatResult(c context.Context, r interface{}) {
var (
json web.Json
html web.Html
)
switch reflect.TypeOf(r) {
case reflect.TypeOf(json):
c.JSON(r.(web.Json).GetResponse())
case reflect.TypeOf(html):
c.HTML(r.(web.Html).GetResponse().(string))
default:
c.JSON(r)
}
}
func buildValueGetter(method reflect.Method, params []Param) []valueGetter {
m := method.Type
var getters []valueGetter
for i := 0; i < m.NumIn()-1; i++ {
in := m.In(i + 1)
getter := getValueGetter(in.Kind(), params[i])
getters = append(getters, getter)
}
return getters
}
func buildParam(param string, method reflect.Type) []Param {
var paramQueue = make([]Param, 0)
paramStr := lang.NewString(param).RemovePrefix("[").RemoveSuffix("]").
ReplaceAll(" ,", ",").ReplaceAll(", ", ",")
if paramStr.String() == "" {
return paramQueue
}
paramArr := paramStr.ReplaceAll(" ", ",").Split(",")
params := lang.TransferSliceToSimple(paramArr)
var scope = defaultSource
for i := len(params) - 1; i >= 0; i-- {
e := params[i]
if sourceDefine.Contains(e) {
scope = e
} else {
paramQueue = append(paramQueue, Param{
name: e,
source: scope,
})
}
}
reverseParam(paramQueue)
for i := 0; i < method.NumIn()-1; i++ {
in := method.In(i + 1)
paramQueue[i].typ = in
}
return paramQueue
}
func reverseParam(param []Param) {
for i := range param {
if i == len(param)/2 {
break
}
param[i], param[len(param)-1-i] = param[len(param)-1-i], param[i]
}
}
func methodName(field reflect.StructField) string {
return fmt.Sprintf(methodMappingPattern, field.Name)
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/kristas/booting-go.git
git@gitee.com:kristas/booting-go.git
kristas
booting-go
booting-go
v1.1.5

搜索帮助