From 91a1d34474231dfc85026747ca6d884b9d75fc4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Sat, 12 Apr 2025 21:01:59 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E5=A2=9E=E5=8A=A0CustomContext?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- define/consts.go | 12 +++ define/context.go | 23 +++++ go.mod | 3 +- go.sum | 4 + request/wrapper.go | 15 ++- router/context.go | 62 ++++++++++++ router/handler.go | 15 ++- router/option.go | 4 +- router/register.go | 213 ---------------------------------------- router/register_test.go | 48 --------- router/server.go | 17 ++-- 11 files changed, 138 insertions(+), 278 deletions(-) create mode 100644 define/consts.go create mode 100644 define/context.go create mode 100644 router/context.go delete mode 100644 router/register.go delete mode 100644 router/register_test.go diff --git a/define/consts.go b/define/consts.go new file mode 100644 index 0000000..6c69649 --- /dev/null +++ b/define/consts.go @@ -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 +) diff --git a/define/context.go b/define/context.go new file mode 100644 index 0000000..727b872 --- /dev/null +++ b/define/context.go @@ -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 +} diff --git a/go.mod b/go.mod index 6c62651..2c8a209 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( git.zhangdeman.cn/zhangdeman/logger v0.0.0-20241125083316-eab7bab9d7ad git.zhangdeman.cn/zhangdeman/network v0.0.0-20230925112156-f0eb86dd2442 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/go-playground/validator/v10 v10.26.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/easymap v0.0.0-20241101082529-28a6c68e38a4 // 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/websocket v0.0.0-20241125101541-c5ea194c9c1e // indirect github.com/BurntSushi/toml v1.5.0 // indirect diff --git a/go.sum b/go.sum index 398342d..54c25ca 100644 --- a/go.sum +++ b/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/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/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/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/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/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/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= diff --git a/request/wrapper.go b/request/wrapper.go index 4749e94..2af2218 100644 --- a/request/wrapper.go +++ b/request/wrapper.go @@ -8,12 +8,14 @@ package request 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" "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 ( @@ -292,3 +294,8 @@ func (wh *wrapperHandle) GetLogicAfterResponse(ctx *gin.Context) *define.LogicAf // 就这么写, key值如果被其他人覆盖成非法值, 此处会直接panic return l.(*define.LogicAfterResponse) } + +// GetCustomContext 获取自定义context +func (wh *wrapperHandle) GetCustomContext(ctx *gin.Context) *define.Context { + return router.NewContext(ctx) +} diff --git a/router/context.go b/router/context.go new file mode 100644 index 0000000..df262c6 --- /dev/null +++ b/router/context.go @@ -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 +} diff --git a/router/handler.go b/router/handler.go index f0a28dc..29ed326 100644 --- a/router/handler.go +++ b/router/handler.go @@ -8,13 +8,15 @@ package router import ( + "errors" + "reflect" + "sync" + "git.zhangdeman.cn/zhangdeman/exception" "git.zhangdeman.cn/zhangdeman/gin/define" "git.zhangdeman.cn/zhangdeman/gin/request" "git.zhangdeman.cn/zhangdeman/gin/response" "github.com/gin-gonic/gin" - "reflect" - "sync" ) // RequestHandler 获取请求处理方法 @@ -58,7 +60,12 @@ func RequestHandler(uriCfg UriConfig) gin.HandlerFunc { ctx.Set(define.LogicAfterResponseKey, logicAfterResponse) defer func() { go func() { - defer recover() + // 执行响应之后的相关逻辑 + defer func() { + if r := recover(); r != nil { + + } + }() if isSuccess { for _, itemFunc := range logicAfterResponse.SuccessHookFuncList { if nil != itemFunc { @@ -87,7 +94,7 @@ func RequestHandler(uriCfg UriConfig) gin.HandlerFunc { return } // 请求失败 - if e, ok = resList[1].Interface().(exception.IException); ok { + if ok = errors.As(resList[1].Interface().(error), &e); ok { // 本身就是exception.IException } else if err, ok = resList[1].Interface().(error); ok { e = exception.NewFromError(-1, err) diff --git a/router/option.go b/router/option.go index 784e844..d7c3b93 100644 --- a/router/option.go +++ b/router/option.go @@ -8,10 +8,11 @@ package router import ( + "strings" + apiDocDefine "git.zhangdeman.cn/gateway/api-doc/define" "git.zhangdeman.cn/zhangdeman/gin/middleware" "github.com/gin-gonic/gin" - "strings" ) type SetServerOptionFunc func(so *serverOption) @@ -29,7 +30,6 @@ type serverOption struct { serverInfo *apiDocDefine.Info // 服务器信息 serverList []*apiDocDefine.ServerItem // 服务器环境列表 enablePprof bool // 启用pprof - enableRequestInit bool // 初始化请求,生成trace_id 设置请求时间等 enableCors bool // 启动跨域支持 loggerCfg *middleware.AccessConfig // 日志配置 } diff --git a/router/register.go b/router/register.go deleted file mode 100644 index 515d63a..0000000 --- a/router/register.go +++ /dev/null @@ -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...) -} diff --git a/router/register_test.go b/router/register_test.go deleted file mode 100644 index ca43da2..0000000 --- a/router/register_test.go +++ /dev/null @@ -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() -} diff --git a/router/server.go b/router/server.go index c32542b..911f872 100644 --- a/router/server.go +++ b/router/server.go @@ -9,13 +9,14 @@ package router import ( "fmt" + "net/http" + "strings" + apiDoc "git.zhangdeman.cn/gateway/api-doc" "git.zhangdeman.cn/zhangdeman/consts" "git.zhangdeman.cn/zhangdeman/gin/middleware" "git.zhangdeman.cn/zhangdeman/gin/middleware/request_cors" "github.com/gin-contrib/pprof" - "net/http" - "strings" apiDocDefine "git.zhangdeman.cn/gateway/api-doc/define" "github.com/gin-gonic/gin" @@ -70,10 +71,14 @@ func NewServer(port int, optionList ...SetServerOptionFunc) *server { } option := newServerOption(port, optionList...) globalMiddlewareList := make([]gin.HandlerFunc, 0) - if option.enableRequestInit { - // 初始化请求中间件 - globalMiddlewareList = append(globalMiddlewareList, middleware.InitRequest()) - } + // CustomContext 必须在第一个, 并且进行初始化 + globalMiddlewareList = append( + globalMiddlewareList, + func(ctx *gin.Context) { + // 初始化上下文以及基础信息 + _ = NewContext(ctx) + }, + ) if nil != option.loggerCfg { // 请求日志记录中间件 globalMiddlewareList = append(globalMiddlewareList, middleware.LogRequest(option.loggerCfg)) -- 2.36.6 From 5df4fbab16d310eb40da3adb3be1ffad2c7eb52f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Sat, 12 Apr 2025 21:24:02 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=BE=AA=E7=8E=AF?= =?UTF-8?q?=E5=BC=95=E7=94=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- define/context.go | 45 +++++++++++++++++++++++++++++++++ request/wrapper.go | 3 +-- router/context.go | 62 ---------------------------------------------- router/option.go | 11 -------- router/server.go | 4 ++- 5 files changed, 49 insertions(+), 76 deletions(-) delete mode 100644 router/context.go diff --git a/define/context.go b/define/context.go index 727b872..e013557 100644 --- a/define/context.go +++ b/define/context.go @@ -8,8 +8,13 @@ package define import ( + "fmt" + "strings" "time" + networkUtil "git.zhangdeman.cn/zhangdeman/network/util" + "git.zhangdeman.cn/zhangdeman/wrapper" + "git.zhangdeman.cn/zhangdeman/trace" "github.com/gin-gonic/gin" ) @@ -21,3 +26,43 @@ type Context struct { RequestID string RequestTime time.Time } + +// NewContext 创建context +func NewContext(ginCtx *gin.Context) *Context { + existCtx, exist := ginCtx.Get(CustomContextKey) + if exist && existCtx != nil { + if c, ok := existCtx.(*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 := &Context{ + Gin: ginCtx, + Trace: trace.NewRuntime(traceID, 1), + TraceID: traceID, + RequestID: getRequestID(ginCtx, traceID), + RequestTime: time.Now(), + } + httpHandleConfig := GetHttpHandleConfig() + ginCtx.Set(CustomContextKey, ctx) + ginCtx.Set(httpHandleConfig.TraceIDField, traceID) + ginCtx.Set(httpHandleConfig.RequestIDField, ctx.RequestID) + ginCtx.Set(httpHandleConfig.StartRequestTimeField, ctx.RequestTime.UnixMilli()) + return ctx +} diff --git a/request/wrapper.go b/request/wrapper.go index 2af2218..3c51751 100644 --- a/request/wrapper.go +++ b/request/wrapper.go @@ -13,7 +13,6 @@ import ( "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" ) @@ -297,5 +296,5 @@ func (wh *wrapperHandle) GetLogicAfterResponse(ctx *gin.Context) *define.LogicAf // GetCustomContext 获取自定义context func (wh *wrapperHandle) GetCustomContext(ctx *gin.Context) *define.Context { - return router.NewContext(ctx) + return define.NewContext(ctx) } diff --git a/router/context.go b/router/context.go deleted file mode 100644 index df262c6..0000000 --- a/router/context.go +++ /dev/null @@ -1,62 +0,0 @@ -// 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 -} diff --git a/router/option.go b/router/option.go index d7c3b93..babf1af 100644 --- a/router/option.go +++ b/router/option.go @@ -126,17 +126,6 @@ func WithPprofEnable() SetServerOptionFunc { } } -// WithEnableRequestInit 全局配置初始化 -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 14:56 2025/2/22 -func WithEnableRequestInit() SetServerOptionFunc { - return func(so *serverOption) { - so.enableRequestInit = true - } -} - // WithEnableCors 启用全局跨域 // // Author : go_developer@163.com<白茶清欢> diff --git a/router/server.go b/router/server.go index 911f872..18e8008 100644 --- a/router/server.go +++ b/router/server.go @@ -12,6 +12,8 @@ import ( "net/http" "strings" + "git.zhangdeman.cn/zhangdeman/gin/define" + apiDoc "git.zhangdeman.cn/gateway/api-doc" "git.zhangdeman.cn/zhangdeman/consts" "git.zhangdeman.cn/zhangdeman/gin/middleware" @@ -76,7 +78,7 @@ func NewServer(port int, optionList ...SetServerOptionFunc) *server { globalMiddlewareList, func(ctx *gin.Context) { // 初始化上下文以及基础信息 - _ = NewContext(ctx) + _ = define.NewContext(ctx) }, ) if nil != option.loggerCfg { -- 2.36.6 From a7fed88714755217605fcf4dd38f8d35c8e27248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Sat, 12 Apr 2025 21:31:47 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8E=B7=E5=8F=96trace?= =?UTF-8?q?=E5=AE=9E=E4=BE=8B=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- request/wrapper.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/request/wrapper.go b/request/wrapper.go index 3c51751..c5acda8 100644 --- a/request/wrapper.go +++ b/request/wrapper.go @@ -11,6 +11,8 @@ import ( "strings" "sync" + "git.zhangdeman.cn/zhangdeman/trace" + "git.zhangdeman.cn/zhangdeman/gin/define" "git.zhangdeman.cn/zhangdeman/gin/request/parse_body" "git.zhangdeman.cn/zhangdeman/wrapper" @@ -298,3 +300,8 @@ func (wh *wrapperHandle) GetLogicAfterResponse(ctx *gin.Context) *define.LogicAf func (wh *wrapperHandle) GetCustomContext(ctx *gin.Context) *define.Context { return define.NewContext(ctx) } + +// GetTraceInstance 获取trace实例 +func (wh *wrapperHandle) GetTraceInstance(ctx *gin.Context) *trace.Runtime { + return define.NewContext(ctx).Trace +} -- 2.36.6 From e0d5e9c94b633181299a788f43d2b44a33abb001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Sat, 12 Apr 2025 21:52:07 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E5=85=A5=E5=8F=A3?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E9=A6=96=E4=B8=AA=E5=8F=82=E6=95=B0=E6=94=AF?= =?UTF-8?q?=E6=8C=81custom=20context?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- define/context.go | 4 ++-- router/controller.go | 6 ++++-- router/define.go | 2 ++ router/handler.go | 8 +++++++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/define/context.go b/define/context.go index e013557..fe3cb4c 100644 --- a/define/context.go +++ b/define/context.go @@ -20,7 +20,7 @@ import ( ) type Context struct { - Gin *gin.Context // 继承 gin context + Context *gin.Context // 继承 gin context Trace *trace.Runtime // trace 实例 TraceID string RequestID string @@ -53,7 +53,7 @@ func NewContext(ginCtx *gin.Context) *Context { return traceID } ctx := &Context{ - Gin: ginCtx, + Context: ginCtx, Trace: trace.NewRuntime(traceID, 1), TraceID: traceID, RequestID: getRequestID(ginCtx, traceID), diff --git a/router/controller.go b/router/controller.go index c352744..7750d8f 100644 --- a/router/controller.go +++ b/router/controller.go @@ -69,8 +69,9 @@ func (c controller) methodConfig(reflectMethod reflect.Method) (cfg UriConfig, n needRegister = false return } - // 第一个参数必须是 *gin.Context - if methodType.In(1).String() != GinContextType { + // 第一个参数必须是 *gin.Context 或者 *define.Context + paramOne := methodType.In(1).String() + if paramOne != GinContextType && paramOne != CustomContextType { needRegister = false return } @@ -106,6 +107,7 @@ func (c controller) methodConfig(reflectMethod reflect.Method) (cfg UriConfig, n } } // 解析meta信息 + cfg.CtxType = paramOne cfg.Path = metaField.Tag.Get(TagNamePath) cfg.RequestMethod = metaField.Tag.Get(TagNameMethod) cfg.Desc = metaField.Tag.Get(TagNameDesc) diff --git a/router/define.go b/router/define.go index bc49eb7..4a1aad1 100644 --- a/router/define.go +++ b/router/define.go @@ -15,6 +15,7 @@ const ( PrefixFuncName = "RouterPrefix" // 路由前缀函数名称 MiddlewareFuncName = "RouterMiddleware" // 路由中间件函数名称 GinContextType = "*gin.Context" // gin context 类型名称 + CustomContextType = "*define.Context" // custom context 类型名称 ErrorType = "error" // error类型 ErrorInterfaceFuncName = "Error" // error接口需要实现的方法名称 ) @@ -41,6 +42,7 @@ type UriConfig struct { TagList []string `json:"tag_list"` // 接口分组 Desc string `json:"desc"` // 接口描述 OutputStrict bool `json:"output_strict"` // 接口是否为严格模式 : 不配置,可返回任意类型, 配置, 必须返回结构体或者map + CtxType string `json:"ctx_type"` // ctx参数类型 FormDataType reflect.Type `json:"-"` // 表单数据类型 ResultDataType reflect.Type `json:"-"` // 返回值数据类型 ApiStructValue reflect.Value `json:"-"` // 逻辑函数所属结构体取值 diff --git a/router/handler.go b/router/handler.go index 29ed326..4689e9c 100644 --- a/router/handler.go +++ b/router/handler.go @@ -86,7 +86,13 @@ func RequestHandler(uriCfg UriConfig) gin.HandlerFunc { if uriCfg.FormDataType.Kind() != reflect.Ptr { inputValue = inputValue.Elem() } - resList := uriCfg.ApiLogicFunc.Func.Call([]reflect.Value{uriCfg.ApiStructValue, reflect.ValueOf(ctx), inputValue}) + var firstParam reflect.Value + if uriCfg.CtxType == define.CustomContextKey { + firstParam = reflect.ValueOf(ctx.MustGet(define.CustomContextKey)) + } else { + firstParam = reflect.ValueOf(ctx) + } + resList := uriCfg.ApiLogicFunc.Func.Call([]reflect.Value{uriCfg.ApiStructValue, firstParam, inputValue}) if resList[1].IsNil() { // 请求成功 isSuccess = true -- 2.36.6 From 54a8fa91c7256132d108e902daffef3b523e9b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Sat, 12 Apr 2025 22:10:48 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20custom=20context=20?= =?UTF-8?q?=E5=88=A4=E6=96=AD=E7=9A=84BUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- router/handler.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/router/handler.go b/router/handler.go index 4689e9c..db29c72 100644 --- a/router/handler.go +++ b/router/handler.go @@ -87,8 +87,9 @@ func RequestHandler(uriCfg UriConfig) gin.HandlerFunc { inputValue = inputValue.Elem() } var firstParam reflect.Value - if uriCfg.CtxType == define.CustomContextKey { - firstParam = reflect.ValueOf(ctx.MustGet(define.CustomContextKey)) + if uriCfg.CtxType == CustomContextType { + customCtx := ctx.MustGet(define.CustomContextKey) + firstParam = reflect.ValueOf(customCtx) } else { firstParam = reflect.ValueOf(ctx) } -- 2.36.6