支持custom context #10
12
define/consts.go
Normal file
12
define/consts.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// Package define ...
|
||||||
|
//
|
||||||
|
// Description : define ...
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 2025-04-12 20:18
|
||||||
|
package define
|
||||||
|
|
||||||
|
const (
|
||||||
|
CustomContextKey = "_CUSTOM_CONTEXT" // 自定义context
|
||||||
|
)
|
23
define/context.go
Normal file
23
define/context.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Package define ...
|
||||||
|
//
|
||||||
|
// Description : define ...
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 2025-04-12 20:57
|
||||||
|
package define
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.zhangdeman.cn/zhangdeman/trace"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Context struct {
|
||||||
|
Gin *gin.Context // 继承 gin context
|
||||||
|
Trace *trace.Runtime // trace 实例
|
||||||
|
TraceID string
|
||||||
|
RequestID string
|
||||||
|
RequestTime time.Time
|
||||||
|
}
|
3
go.mod
3
go.mod
@ -11,7 +11,7 @@ require (
|
|||||||
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20241125083316-eab7bab9d7ad
|
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20241125083316-eab7bab9d7ad
|
||||||
git.zhangdeman.cn/zhangdeman/network v0.0.0-20230925112156-f0eb86dd2442
|
git.zhangdeman.cn/zhangdeman/network v0.0.0-20230925112156-f0eb86dd2442
|
||||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd
|
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd
|
||||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250124091620-c757e551a8c9
|
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740
|
||||||
github.com/gin-gonic/gin v1.10.0
|
github.com/gin-gonic/gin v1.10.0
|
||||||
github.com/go-playground/validator/v10 v10.26.0
|
github.com/go-playground/validator/v10 v10.26.0
|
||||||
github.com/mcuadros/go-defaults v1.2.0
|
github.com/mcuadros/go-defaults v1.2.0
|
||||||
@ -23,6 +23,7 @@ require (
|
|||||||
git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda // indirect
|
git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda // indirect
|
||||||
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4 // indirect
|
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4 // indirect
|
||||||
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 // indirect
|
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 // indirect
|
||||||
|
git.zhangdeman.cn/zhangdeman/trace v0.0.0-20250412104923-c1ecb1bfe8d5 // indirect
|
||||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e // indirect
|
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e // indirect
|
||||||
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20241125101541-c5ea194c9c1e // indirect
|
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20241125101541-c5ea194c9c1e // indirect
|
||||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||||
|
4
go.sum
4
go.sum
@ -24,12 +24,16 @@ git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 h1:gUDlQ
|
|||||||
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0/go.mod h1:VHb9qmhaPDAQDcS6vUiDCamYjZ4R5lD1XtVsh55KsMI=
|
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0/go.mod h1:VHb9qmhaPDAQDcS6vUiDCamYjZ4R5lD1XtVsh55KsMI=
|
||||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd h1:q7GG14qgXKB4MEXQFOe7/UYebsqMfPaSX80TcPdOosI=
|
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd h1:q7GG14qgXKB4MEXQFOe7/UYebsqMfPaSX80TcPdOosI=
|
||||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd/go.mod h1:+D6uPSljwHywjVY5WSBY4TRVMj26TN5f5cFGEYMldjs=
|
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd/go.mod h1:+D6uPSljwHywjVY5WSBY4TRVMj26TN5f5cFGEYMldjs=
|
||||||
|
git.zhangdeman.cn/zhangdeman/trace v0.0.0-20250412104923-c1ecb1bfe8d5 h1:dD1Q/MIrRmIhKqfYPH+y167ca9CKwTPuQt3c1hXWGJ8=
|
||||||
|
git.zhangdeman.cn/zhangdeman/trace v0.0.0-20250412104923-c1ecb1bfe8d5/go.mod h1:PB486NC82nuvn5yi+U2i48ogX/9EAETWAHd8O9TwY9k=
|
||||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e h1:Q973S6CcWr1ICZhFI1STFOJ+KUImCl2BaIXm6YppBqI=
|
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e h1:Q973S6CcWr1ICZhFI1STFOJ+KUImCl2BaIXm6YppBqI=
|
||||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI=
|
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI=
|
||||||
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20241125101541-c5ea194c9c1e h1:YE2Gi+M03UDImIpWa3I7jzSesyfu2RL8x/4ONs5v0oE=
|
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20241125101541-c5ea194c9c1e h1:YE2Gi+M03UDImIpWa3I7jzSesyfu2RL8x/4ONs5v0oE=
|
||||||
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20241125101541-c5ea194c9c1e/go.mod h1:L/7JugxKZL3JP9JP/XDvPAPz0FQXG1u181Su1+u/d1c=
|
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20241125101541-c5ea194c9c1e/go.mod h1:L/7JugxKZL3JP9JP/XDvPAPz0FQXG1u181Su1+u/d1c=
|
||||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250124091620-c757e551a8c9 h1:yF770WIDNwyiKL0nwmBGmjZvNCLXtHQL4xJyffPjTMU=
|
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250124091620-c757e551a8c9 h1:yF770WIDNwyiKL0nwmBGmjZvNCLXtHQL4xJyffPjTMU=
|
||||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250124091620-c757e551a8c9/go.mod h1:I76wxEsWq7KnMQ84elpwTjEqq4I49QFw60tp5h7iGBs=
|
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250124091620-c757e551a8c9/go.mod h1:I76wxEsWq7KnMQ84elpwTjEqq4I49QFw60tp5h7iGBs=
|
||||||
|
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740 h1:zPUoylfJTbc0EcxW+NEzOTBmoeFZ2I/rLFBnEzxb4Wk=
|
||||||
|
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740/go.mod h1:1ct92dbVc49pmXusA/iGfcQUJzcYmJ+cjAhgc3sDv1I=
|
||||||
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||||
|
@ -8,12 +8,14 @@
|
|||||||
package request
|
package request
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.zhangdeman.cn/zhangdeman/gin/define"
|
|
||||||
"git.zhangdeman.cn/zhangdeman/gin/request/parse_body"
|
|
||||||
"git.zhangdeman.cn/zhangdeman/wrapper"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"git.zhangdeman.cn/zhangdeman/gin/define"
|
||||||
|
"git.zhangdeman.cn/zhangdeman/gin/request/parse_body"
|
||||||
|
"git.zhangdeman.cn/zhangdeman/gin/router"
|
||||||
|
"git.zhangdeman.cn/zhangdeman/wrapper"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -292,3 +294,8 @@ func (wh *wrapperHandle) GetLogicAfterResponse(ctx *gin.Context) *define.LogicAf
|
|||||||
// 就这么写, key值如果被其他人覆盖成非法值, 此处会直接panic
|
// 就这么写, key值如果被其他人覆盖成非法值, 此处会直接panic
|
||||||
return l.(*define.LogicAfterResponse)
|
return l.(*define.LogicAfterResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCustomContext 获取自定义context
|
||||||
|
func (wh *wrapperHandle) GetCustomContext(ctx *gin.Context) *define.Context {
|
||||||
|
return router.NewContext(ctx)
|
||||||
|
}
|
||||||
|
62
router/context.go
Normal file
62
router/context.go
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// Package router ...
|
||||||
|
//
|
||||||
|
// Description : request ...
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 2025-04-12 18:44
|
||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
networkUtil "git.zhangdeman.cn/zhangdeman/network/util"
|
||||||
|
"git.zhangdeman.cn/zhangdeman/wrapper"
|
||||||
|
|
||||||
|
"git.zhangdeman.cn/zhangdeman/gin/define"
|
||||||
|
|
||||||
|
"git.zhangdeman.cn/zhangdeman/trace"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewContext 创建context
|
||||||
|
func NewContext(ginCtx *gin.Context) *define.Context {
|
||||||
|
existCtx, exist := ginCtx.Get(define.CustomContextKey)
|
||||||
|
if exist && existCtx != nil {
|
||||||
|
if c, ok := existCtx.(*define.Context); ok {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
traceID := fmt.Sprintf(
|
||||||
|
"%v-%v-%v-%v",
|
||||||
|
time.Now().UnixNano()/1e6,
|
||||||
|
strings.ReplaceAll(networkUtil.IP.GetHostIP(), ".", ""),
|
||||||
|
strings.ReplaceAll(networkUtil.IP.GetRemoteIP(ginCtx.Request), ".", ""),
|
||||||
|
wrapper.StringFromRandom(32, "").Md5().Value,
|
||||||
|
)
|
||||||
|
getRequestID := func(ctx *gin.Context, traceID string) string {
|
||||||
|
requestID := ctx.GetHeader("X-Forward-Request-Id")
|
||||||
|
if len(requestID) > 0 {
|
||||||
|
return requestID
|
||||||
|
}
|
||||||
|
if len(traceID) > 0 {
|
||||||
|
return traceID
|
||||||
|
}
|
||||||
|
return traceID
|
||||||
|
}
|
||||||
|
ctx := &define.Context{
|
||||||
|
Gin: ginCtx,
|
||||||
|
Trace: trace.NewRuntime(traceID, 1),
|
||||||
|
TraceID: traceID,
|
||||||
|
RequestID: getRequestID(ginCtx, traceID),
|
||||||
|
RequestTime: time.Now(),
|
||||||
|
}
|
||||||
|
httpHandleConfig := define.GetHttpHandleConfig()
|
||||||
|
ginCtx.Set(define.CustomContextKey, ctx)
|
||||||
|
ginCtx.Set(httpHandleConfig.TraceIDField, traceID)
|
||||||
|
ginCtx.Set(httpHandleConfig.RequestIDField, ctx.RequestID)
|
||||||
|
ginCtx.Set(httpHandleConfig.StartRequestTimeField, ctx.RequestTime.UnixMilli())
|
||||||
|
return ctx
|
||||||
|
}
|
@ -8,13 +8,15 @@
|
|||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"reflect"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"git.zhangdeman.cn/zhangdeman/exception"
|
"git.zhangdeman.cn/zhangdeman/exception"
|
||||||
"git.zhangdeman.cn/zhangdeman/gin/define"
|
"git.zhangdeman.cn/zhangdeman/gin/define"
|
||||||
"git.zhangdeman.cn/zhangdeman/gin/request"
|
"git.zhangdeman.cn/zhangdeman/gin/request"
|
||||||
"git.zhangdeman.cn/zhangdeman/gin/response"
|
"git.zhangdeman.cn/zhangdeman/gin/response"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"reflect"
|
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// RequestHandler 获取请求处理方法
|
// RequestHandler 获取请求处理方法
|
||||||
@ -58,7 +60,12 @@ func RequestHandler(uriCfg UriConfig) gin.HandlerFunc {
|
|||||||
ctx.Set(define.LogicAfterResponseKey, logicAfterResponse)
|
ctx.Set(define.LogicAfterResponseKey, logicAfterResponse)
|
||||||
defer func() {
|
defer func() {
|
||||||
go func() {
|
go func() {
|
||||||
defer recover()
|
// 执行响应之后的相关逻辑
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
|
||||||
|
}
|
||||||
|
}()
|
||||||
if isSuccess {
|
if isSuccess {
|
||||||
for _, itemFunc := range logicAfterResponse.SuccessHookFuncList {
|
for _, itemFunc := range logicAfterResponse.SuccessHookFuncList {
|
||||||
if nil != itemFunc {
|
if nil != itemFunc {
|
||||||
@ -87,7 +94,7 @@ func RequestHandler(uriCfg UriConfig) gin.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 请求失败
|
// 请求失败
|
||||||
if e, ok = resList[1].Interface().(exception.IException); ok {
|
if ok = errors.As(resList[1].Interface().(error), &e); ok {
|
||||||
// 本身就是exception.IException
|
// 本身就是exception.IException
|
||||||
} else if err, ok = resList[1].Interface().(error); ok {
|
} else if err, ok = resList[1].Interface().(error); ok {
|
||||||
e = exception.NewFromError(-1, err)
|
e = exception.NewFromError(-1, err)
|
||||||
|
@ -8,10 +8,11 @@
|
|||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
apiDocDefine "git.zhangdeman.cn/gateway/api-doc/define"
|
apiDocDefine "git.zhangdeman.cn/gateway/api-doc/define"
|
||||||
"git.zhangdeman.cn/zhangdeman/gin/middleware"
|
"git.zhangdeman.cn/zhangdeman/gin/middleware"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SetServerOptionFunc func(so *serverOption)
|
type SetServerOptionFunc func(so *serverOption)
|
||||||
@ -29,7 +30,6 @@ type serverOption struct {
|
|||||||
serverInfo *apiDocDefine.Info // 服务器信息
|
serverInfo *apiDocDefine.Info // 服务器信息
|
||||||
serverList []*apiDocDefine.ServerItem // 服务器环境列表
|
serverList []*apiDocDefine.ServerItem // 服务器环境列表
|
||||||
enablePprof bool // 启用pprof
|
enablePprof bool // 启用pprof
|
||||||
enableRequestInit bool // 初始化请求,生成trace_id 设置请求时间等
|
|
||||||
enableCors bool // 启动跨域支持
|
enableCors bool // 启动跨域支持
|
||||||
loggerCfg *middleware.AccessConfig // 日志配置
|
loggerCfg *middleware.AccessConfig // 日志配置
|
||||||
}
|
}
|
||||||
|
@ -1,213 +0,0 @@
|
|||||||
// 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 _, itemController := range controllerList {
|
|
||||||
if nil == itemController {
|
|
||||||
// 忽略空指针
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
parseController(itemController)
|
|
||||||
}
|
|
||||||
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...)
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
// Package router ...
|
|
||||||
//
|
|
||||||
// Description : router ...
|
|
||||||
//
|
|
||||||
// Author : go_developer@163.com<白茶清欢>
|
|
||||||
//
|
|
||||||
// Date : 2024-07-20 23:24
|
|
||||||
package router
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TestController struct{}
|
|
||||||
|
|
||||||
func (t TestController) Logic(ctx *gin.Context, formData *TestForm) (TestOut, error) {
|
|
||||||
return TestOut{
|
|
||||||
FormData: formData,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type TestOut struct {
|
|
||||||
Age int `json:"age" form:"age" binding:"min=20" err_msg:"年龄不能小于20"`
|
|
||||||
Name string `json:"name" form:"name"`
|
|
||||||
Test *Test `json:"test" form:"test"`
|
|
||||||
Num *int64 `json:"num" form:"num"`
|
|
||||||
FormData *TestForm `json:"form_data" form:"form_data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TestForm struct {
|
|
||||||
Meta `tag:"测试表单" path:"/a/b/c/d" desc:"测试接口" method:"GET"`
|
|
||||||
Age int `json:"age" form:"age" binding:"min=20" err_msg:"年龄不能小于20"`
|
|
||||||
Name string `json:"name" form:"name"`
|
|
||||||
Test *Test `json:"test" form:"test"`
|
|
||||||
Num *int64 `json:"num" form:"num"`
|
|
||||||
}
|
|
||||||
type Test struct {
|
|
||||||
L string `json:"l"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_parseController(t *testing.T) {
|
|
||||||
SetValidateErrTag("err_msg")
|
|
||||||
s := NewServer(8888, nil)
|
|
||||||
s.Group("test", nil, TestController{})
|
|
||||||
s.Start()
|
|
||||||
}
|
|
@ -9,13 +9,14 @@ package router
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
apiDoc "git.zhangdeman.cn/gateway/api-doc"
|
apiDoc "git.zhangdeman.cn/gateway/api-doc"
|
||||||
"git.zhangdeman.cn/zhangdeman/consts"
|
"git.zhangdeman.cn/zhangdeman/consts"
|
||||||
"git.zhangdeman.cn/zhangdeman/gin/middleware"
|
"git.zhangdeman.cn/zhangdeman/gin/middleware"
|
||||||
"git.zhangdeman.cn/zhangdeman/gin/middleware/request_cors"
|
"git.zhangdeman.cn/zhangdeman/gin/middleware/request_cors"
|
||||||
"github.com/gin-contrib/pprof"
|
"github.com/gin-contrib/pprof"
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
apiDocDefine "git.zhangdeman.cn/gateway/api-doc/define"
|
apiDocDefine "git.zhangdeman.cn/gateway/api-doc/define"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@ -70,10 +71,14 @@ func NewServer(port int, optionList ...SetServerOptionFunc) *server {
|
|||||||
}
|
}
|
||||||
option := newServerOption(port, optionList...)
|
option := newServerOption(port, optionList...)
|
||||||
globalMiddlewareList := make([]gin.HandlerFunc, 0)
|
globalMiddlewareList := make([]gin.HandlerFunc, 0)
|
||||||
if option.enableRequestInit {
|
// CustomContext 必须在第一个, 并且进行初始化
|
||||||
// 初始化请求中间件
|
globalMiddlewareList = append(
|
||||||
globalMiddlewareList = append(globalMiddlewareList, middleware.InitRequest())
|
globalMiddlewareList,
|
||||||
}
|
func(ctx *gin.Context) {
|
||||||
|
// 初始化上下文以及基础信息
|
||||||
|
_ = NewContext(ctx)
|
||||||
|
},
|
||||||
|
)
|
||||||
if nil != option.loggerCfg {
|
if nil != option.loggerCfg {
|
||||||
// 请求日志记录中间件
|
// 请求日志记录中间件
|
||||||
globalMiddlewareList = append(globalMiddlewareList, middleware.LogRequest(option.loggerCfg))
|
globalMiddlewareList = append(globalMiddlewareList, middleware.LogRequest(option.loggerCfg))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user