214 lines
6.9 KiB
Go
214 lines
6.9 KiB
Go
// Package router ...
|
|
//
|
|
// Description : router ...
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 2024-07-20 21:39
|
|
package router
|
|
|
|
import (
|
|
"fmt"
|
|
"git.zhangdeman.cn/zhangdeman/exception"
|
|
"git.zhangdeman.cn/zhangdeman/gin/middleware"
|
|
"git.zhangdeman.cn/zhangdeman/gin/request"
|
|
"git.zhangdeman.cn/zhangdeman/gin/response"
|
|
"git.zhangdeman.cn/zhangdeman/wrapper"
|
|
"github.com/gin-gonic/gin"
|
|
"net/http"
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
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) error {
|
|
for _, controller := range controllerList {
|
|
if nil == controller {
|
|
// 忽略空指针
|
|
continue
|
|
}
|
|
parseController(controller)
|
|
}
|
|
return 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(FieldNameMeta)
|
|
if !metaFieldExist {
|
|
return nil, nil
|
|
}
|
|
uriConfig := &UriConfig{
|
|
Path: strings.TrimRight(routerPrefix, "/") + "/" + strings.TrimLeft(metaField.Tag.Get(TagNamePath), "/"),
|
|
RequestMethod: strings.ToUpper(metaField.Tag.Get(TagNameMethod)),
|
|
TagList: strings.Split(metaField.Tag.Get(TagNameUriTag), "|"),
|
|
Desc: metaField.Tag.Get(TagNameDesc),
|
|
OutputStrict: wrapper.ArrayType([]string{"", "true"}).Has(strings.ToLower(metaField.Tag.Get(TagNameOutputStrict))) >= 0,
|
|
FormDataType: methodType.In(2).Elem(),
|
|
}
|
|
// 校验 FormDataType
|
|
for fieldIdx := 0; fieldIdx < uriConfig.FormDataType.NumField(); fieldIdx++ {
|
|
if uriConfig.FormDataType.Field(fieldIdx).Type.Kind() == reflect.Interface {
|
|
panic("request param set type `interface` is not allowed")
|
|
}
|
|
}
|
|
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, map[string]any{"business_data": businessData})
|
|
return
|
|
} else {
|
|
response.SendWithException(ctx, exception.NewFromError(-1, errData.Interface().(error)), map[string]any{"business_data": businessData})
|
|
return
|
|
}
|
|
}
|
|
middlewareList = append(middlewareList, handlerFunc)
|
|
middlewareList = append([]gin.HandlerFunc{
|
|
middleware.InitRequest(),
|
|
}, middlewareList...)
|
|
switch uriConfig.RequestMethod {
|
|
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.RequestMethod + " 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...)
|
|
}
|