// Package router ... // // Description : router ... // // Author : go_developer@163.com<白茶清欢> // // Date : 2024-07-20 21:39 package router import ( "fmt" "net/http" "reflect" "strings" "git.zhangdeman.cn/zhangdeman/exception" "git.zhangdeman.cn/zhangdeman/gin/response" "git.zhangdeman.cn/zhangdeman/gin/request" "git.zhangdeman.cn/zhangdeman/wrapper" "github.com/gin-gonic/gin" ) var ( Debug = false // 是否开启DEBUG ginRouter = gin.Default() ) func init() { } // Register 注册路由 // // Author : go_developer@163.com<白茶清欢> // // Date : 21:40 2024/7/20 func Register(port int, controllerList ...any) { for _, controller := range controllerList { if nil == controller { // 忽略空指针 continue } parseController(controller) } ginRouter.Run(fmt.Sprintf(":%d", port)) } // parseController 解析controller // // Author : go_developer@163.com<白茶清欢> // // Date : 22:10 2024/7/20 func parseController(controller any) { controllerType := reflect.TypeOf(controller) controllerValue := reflect.ValueOf(controller) routerPrefix := "/" // 解析路由前缀函数 // routerPrefix 不能有任何入参, 并且只能有一个返回值, // 返回值类型为字符串, 为具体路由前缀 routerPrefixFunc, routerPrefixFuncExist := controllerType.MethodByName(PrefixFuncName) if routerPrefixFuncExist { routerPrefixFuncType := routerPrefixFunc.Type if routerPrefixFuncType.NumIn() == 1 && // 无任何入参, 正在没有如何入参情况下, 第一个参数是结构体指针 routerPrefixFuncType.NumOut() == 1 && // 只能有一个返回值 routerPrefixFuncType.Out(0).Kind() == reflect.String { // 返回值必须是字符串 routerPrefix = routerPrefixFunc.Func.Call([]reflect.Value{controllerValue})[0].String() } } // 请求组的中间件 middlewareList := make([]gin.HandlerFunc, 0) routerMiddlewareFunc, routerMiddlewareFuncExist := controllerType.MethodByName(MiddlewareFuncName) if routerMiddlewareFuncExist { routerMiddlewareFuncType := routerMiddlewareFunc.Type if routerMiddlewareFuncType.NumIn() == 1 && // 无需任何参数 routerMiddlewareFuncType.NumOut() == 1 && // 只能有一个返回值 routerMiddlewareFuncType.Out(0).String() == "[]gin.HandlerFunc" { // 返回值必须是gin.HandlerFunc res := routerMiddlewareFunc.Func.Call([]reflect.Value{controllerValue}) if !res[0].IsNil() { middlewareList = res[0].Interface().([]gin.HandlerFunc) } } } for funcIdx := 0; funcIdx < controllerType.NumMethod(); funcIdx++ { method := controllerType.Method(funcIdx) if method.Name == PrefixFuncName || method.Name == MiddlewareFuncName { continue } methodType := method.Type uriConfig, err := parseUriConfig(methodType, routerPrefix) if nil != err { debugLog("parseUriConfig error : %s -> %s", err.Error(), methodType.Kind().String()) } if nil == uriConfig { continue } registerUri(uriConfig, controllerValue.Method(funcIdx), middlewareList) } } // parseUriConfig 解析Uri配置 // // Author : go_developer@163.com<白茶清欢> // // Date : 16:40 2024/7/21 func parseUriConfig(methodType reflect.Type, routerPrefix string) (*UriConfig, error) { if methodType.NumIn() != 3 || // 结构体指针 + 两个参数 methodType.NumOut() != 2 { // 两个返回值 return nil, nil } // 接口logic共计两个参数. 两个返回值, 格式 : func(ctx *gin.Context, formData any[组合Meta]) (any[response], error) // 解析第一个参数是 *gin.Context if methodType.In(1).String() != "*gin.Context" { return nil, nil } // 解析第二个参数是组合Meta的form表单 formType := methodType.In(2) if formType.Kind() == reflect.Ptr { formType = methodType.In(2).Elem() } metaField, metaFieldExist := formType.FieldByName("Meta") if !metaFieldExist { return nil, nil } uriConfig := &UriConfig{ Path: strings.TrimRight(routerPrefix, "/") + "/" + strings.TrimLeft(metaField.Tag.Get(TagNamePath), "/"), Method: strings.ToUpper(metaField.Tag.Get(TagNameMethod)), TagList: strings.Split(metaField.Tag.Get(TagNameUriTag), "|"), Desc: metaField.Tag.Get(TagNameDesc), Strict: wrapper.ArrayType([]string{"", "true"}).Has(strings.ToLower(metaField.Tag.Get(TagNameStrict))) >= 0, FormDataType: methodType.In(2).Elem(), } return uriConfig, nil } // registerUri 注册路由 // // Author : go_developer@163.com<白茶清欢> // // Date : 18:00 2024/7/21 func registerUri(uriConfig *UriConfig, methodValue reflect.Value, middlewareList []gin.HandlerFunc) { if nil == middlewareList { middlewareList = make([]gin.HandlerFunc, 0) } handlerFunc := func(ctx *gin.Context) { formDataReceiver := reflect.New(uriConfig.FormDataType) if err := request.Form.Parse(ctx, formDataReceiver.Interface()); nil != err { panic(err) } returnValue := methodValue.Call([]reflect.Value{reflect.ValueOf(ctx), formDataReceiver}) businessData := returnValue[0].Interface() errData := returnValue[1] if errData.IsNil() { response.Success(ctx, businessData) return } err := errData.Interface() if e, ok := err.(exception.IException); ok { response.SendWithException(ctx, e, businessData) return } else { response.SendWithException(ctx, exception.NewFromError(-1, errData.Interface().(error)), businessData) return } } middlewareList = append(middlewareList, handlerFunc) switch uriConfig.Method { case http.MethodGet: ginRouter.GET(uriConfig.Path, middlewareList...) case http.MethodHead: ginRouter.HEAD(uriConfig.Path, middlewareList...) case http.MethodPost: ginRouter.PUT(uriConfig.Path, middlewareList...) case http.MethodPut: ginRouter.PUT(uriConfig.Path, middlewareList...) case http.MethodPatch: ginRouter.PATCH(uriConfig.Path, middlewareList...) case http.MethodDelete: ginRouter.DELETE(uriConfig.Path, middlewareList...) case http.MethodConnect: ginRouter.Handle(http.MethodConnect, uriConfig.Path, middlewareList...) case http.MethodOptions: ginRouter.OPTIONS(uriConfig.Path, middlewareList...) case http.MethodTrace: ginRouter.Handle(http.MethodTrace, uriConfig.Path, middlewareList...) case "ANY": ginRouter.Any(uriConfig.Path, middlewareList...) default: panic(uriConfig.Path + " : " + uriConfig.Method + " is not support") } } // debugLog ... // // Author : go_developer@163.com<白茶清欢> // // Date : 15:32 2024/7/21 func debugLog(format string, valList ...any) { if !Debug { return } fmt.Printf("[DEBUG] "+format+"\n", valList...) }