Merge pull request '公共参数自动注入, 增加参数是否已赋值检测' (#18) from feature/upgrade_common_param into master
Reviewed-on: #18
This commit is contained in:
		@ -1,12 +0,0 @@
 | 
				
			|||||||
// Package define ...
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Description : define ...
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Author : go_developer@163.com<白茶清欢>
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Date : 2025-04-12 20:18
 | 
					 | 
				
			||||||
package define
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	CustomContextKey = "_CUSTOM_CONTEXT" // 自定义context
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
@ -1,68 +0,0 @@
 | 
				
			|||||||
// Package define ...
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Description : define ...
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Author : go_developer@163.com<白茶清欢>
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Date : 2025-04-12 20:57
 | 
					 | 
				
			||||||
package define
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	networkUtil "git.zhangdeman.cn/zhangdeman/network/util"
 | 
					 | 
				
			||||||
	"git.zhangdeman.cn/zhangdeman/wrapper/op_string"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"git.zhangdeman.cn/zhangdeman/trace"
 | 
					 | 
				
			||||||
	"github.com/gin-gonic/gin"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type Context struct {
 | 
					 | 
				
			||||||
	Context     *gin.Context   // 继承 gin context
 | 
					 | 
				
			||||||
	Trace       *trace.Runtime // trace 实例
 | 
					 | 
				
			||||||
	TraceID     string
 | 
					 | 
				
			||||||
	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), ".", ""),
 | 
					 | 
				
			||||||
		op_string.Md5(op_string.Random(32, "")),
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
	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{
 | 
					 | 
				
			||||||
		Context:     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
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -12,6 +12,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"git.zhangdeman.cn/zhangdeman/consts"
 | 
						"git.zhangdeman.cn/zhangdeman/consts"
 | 
				
			||||||
	"git.zhangdeman.cn/zhangdeman/wrapper/op_ternary"
 | 
						"git.zhangdeman.cn/zhangdeman/wrapper/op_ternary"
 | 
				
			||||||
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
@ -127,22 +128,18 @@ func GetHttpHandleConfig() *HttpHandleConfig {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	LogicAfterResponseKey = "__logic_after_response__"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type LogicAfterResponse struct {
 | 
					type LogicAfterResponse struct {
 | 
				
			||||||
	SuccessHookFuncList []func()      `json:"-"` // 请求最后需要执行的成功hook函数
 | 
						SuccessHookFuncList []func(ctx *gin.Context) `json:"-"` // 请求最后需要执行的成功hook函数
 | 
				
			||||||
	FailureHookFuncList []func()      `json:"-"` // 请求最后需要执行的失败hook函数
 | 
						FailureHookFuncList []func(ctx *gin.Context) `json:"-"` // 请求最后需要执行的失败hook函数
 | 
				
			||||||
	Lock                *sync.RWMutex            `json:"-"` // 逻辑锁
 | 
						Lock                *sync.RWMutex            `json:"-"` // 逻辑锁
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (logic *LogicAfterResponse) AddSuccessHook(f func()) {
 | 
					func (logic *LogicAfterResponse) AddSuccessHook(f func(ctx *gin.Context)) {
 | 
				
			||||||
	logic.Lock.Lock()
 | 
						logic.Lock.Lock()
 | 
				
			||||||
	defer logic.Lock.Unlock()
 | 
						defer logic.Lock.Unlock()
 | 
				
			||||||
	logic.SuccessHookFuncList = append(logic.SuccessHookFuncList, f)
 | 
						logic.SuccessHookFuncList = append(logic.SuccessHookFuncList, f)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
func (logic *LogicAfterResponse) AddFailureHook(f func()) {
 | 
					func (logic *LogicAfterResponse) AddFailureHook(f func(ctx *gin.Context)) {
 | 
				
			||||||
	logic.Lock.Lock()
 | 
						logic.Lock.Lock()
 | 
				
			||||||
	defer logic.Lock.Unlock()
 | 
						defer logic.Lock.Unlock()
 | 
				
			||||||
	logic.FailureHookFuncList = append(logic.FailureHookFuncList, f)
 | 
						logic.FailureHookFuncList = append(logic.FailureHookFuncList, f)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							@ -6,7 +6,7 @@ toolchain go1.24.2
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	git.zhangdeman.cn/zhangdeman/api-doc v1.0.3-0.20251013152001-868ee8955623
 | 
						git.zhangdeman.cn/zhangdeman/api-doc v1.0.3-0.20251013152001-868ee8955623
 | 
				
			||||||
	git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250916024308-d378e6c57772
 | 
						git.zhangdeman.cn/zhangdeman/consts v0.0.0-20251101092813-3dd9fb807f1c
 | 
				
			||||||
	git.zhangdeman.cn/zhangdeman/dynamic-struct v0.0.0-20251013092857-dcf591d4e8a8
 | 
						git.zhangdeman.cn/zhangdeman/dynamic-struct v0.0.0-20251013092857-dcf591d4e8a8
 | 
				
			||||||
	git.zhangdeman.cn/zhangdeman/exception v0.0.0-20250510123912-a0d52fc093ab
 | 
						git.zhangdeman.cn/zhangdeman/exception v0.0.0-20250510123912-a0d52fc093ab
 | 
				
			||||||
	git.zhangdeman.cn/zhangdeman/graceful v0.0.0-20250529070945-92833db6f3a4
 | 
						git.zhangdeman.cn/zhangdeman/graceful v0.0.0-20250529070945-92833db6f3a4
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										31
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								go.sum
									
									
									
									
									
								
							@ -1,11 +1,10 @@
 | 
				
			|||||||
git.zhangdeman.cn/zhangdeman/api-doc v1.0.3-0.20250930090005-69177ebcd195 h1:S1DqbZdJxKxzEbanmG2I/yycScml7dJbYR+VrXzeuo0=
 | 
					 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/api-doc v1.0.3-0.20250930090005-69177ebcd195/go.mod h1:tMqiqByNQ5WmFieruKEcEVJv0g2QqA5XSqV0S9WvOZU=
 | 
					 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/api-doc v1.0.3-0.20251013152001-868ee8955623 h1:QiqETEQx2PBv2fF3UwPS11dsbVDcF3WNCmRRA8zrqAk=
 | 
					git.zhangdeman.cn/zhangdeman/api-doc v1.0.3-0.20251013152001-868ee8955623 h1:QiqETEQx2PBv2fF3UwPS11dsbVDcF3WNCmRRA8zrqAk=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/api-doc v1.0.3-0.20251013152001-868ee8955623/go.mod h1:ryyMI2gPgotFD1lZC50p2vRyX8bf3MRwO9tos41z4WU=
 | 
					git.zhangdeman.cn/zhangdeman/api-doc v1.0.3-0.20251013152001-868ee8955623/go.mod h1:ryyMI2gPgotFD1lZC50p2vRyX8bf3MRwO9tos41z4WU=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250916024308-d378e6c57772 h1:Yo1ur3LnDF5s7F7tpJsNrdUSF8LwYKnN9TdQU32F3eU=
 | 
					git.zhangdeman.cn/zhangdeman/consts v0.0.0-20251101052451-27b111113aa3 h1:MQJCu5ZIDUYJSQ7rGZni4gsxgGmpXgWgNBHJzHSOvxw=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250916024308-d378e6c57772/go.mod h1:5p8CEKGBxi7qPtTXDI3HDmqKAfIm5i/aBWdrbkbdNjc=
 | 
					git.zhangdeman.cn/zhangdeman/consts v0.0.0-20251101052451-27b111113aa3/go.mod h1:5p8CEKGBxi7qPtTXDI3HDmqKAfIm5i/aBWdrbkbdNjc=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/dynamic-struct v0.0.0-20250429065800-fc340b9417cf h1:xCPM3U6i62UvLo9VNvDP45Ue3dPl7ratHu1rSEJRE2k=
 | 
					git.zhangdeman.cn/zhangdeman/consts v0.0.0-20251101092813-3dd9fb807f1c h1:H0Tlh7i5UtCLwwhPFEqIO7V+vydQ7YgMtPQI7iCxiSI=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/dynamic-struct v0.0.0-20250429065800-fc340b9417cf/go.mod h1:onY+qrB+Uwfuv75JlgHlGdkirAfYcINrvCashtVoBX0=
 | 
					git.zhangdeman.cn/zhangdeman/consts v0.0.0-20251101092813-3dd9fb807f1c/go.mod h1:5p8CEKGBxi7qPtTXDI3HDmqKAfIm5i/aBWdrbkbdNjc=
 | 
				
			||||||
 | 
					git.zhangdeman.cn/zhangdeman/dynamic-struct v0.0.0-20251013092857-dcf591d4e8a8 h1:Pw981jG3hH9ZHrB3s1xPpsZafgX3USuMAjnGi2GEP9Y=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/dynamic-struct v0.0.0-20251013092857-dcf591d4e8a8/go.mod h1:xtCw3om5DRrG30EfQd/lfQPXgptfK7l9oBSt4Kdhjok=
 | 
					git.zhangdeman.cn/zhangdeman/dynamic-struct v0.0.0-20251013092857-dcf591d4e8a8/go.mod h1:xtCw3om5DRrG30EfQd/lfQPXgptfK7l9oBSt4Kdhjok=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda h1:bMD6r9gjRy7cO+T4zRQVYAesgIblBdTnhzT1vN5wjvI=
 | 
					git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda h1:bMD6r9gjRy7cO+T4zRQVYAesgIblBdTnhzT1vN5wjvI=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda/go.mod h1:dT0rmHcJ9Z9IqWeMIt7YzR88nKkNV2V3dfG0j9Q6lK0=
 | 
					git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda/go.mod h1:dT0rmHcJ9Z9IqWeMIt7YzR88nKkNV2V3dfG0j9Q6lK0=
 | 
				
			||||||
@ -15,30 +14,20 @@ git.zhangdeman.cn/zhangdeman/exception v0.0.0-20250510123912-a0d52fc093ab h1:O0X
 | 
				
			|||||||
git.zhangdeman.cn/zhangdeman/exception v0.0.0-20250510123912-a0d52fc093ab/go.mod h1:Voc8J4ordx7nuMWpgACXXZULQy7ZIuBzcEIoS8VnDIw=
 | 
					git.zhangdeman.cn/zhangdeman/exception v0.0.0-20250510123912-a0d52fc093ab/go.mod h1:Voc8J4ordx7nuMWpgACXXZULQy7ZIuBzcEIoS8VnDIw=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/graceful v0.0.0-20250529070945-92833db6f3a4 h1:d1B3IXRitiMlY5ssEWRa//RQD24SqRPk/bCpL4/WyOA=
 | 
					git.zhangdeman.cn/zhangdeman/graceful v0.0.0-20250529070945-92833db6f3a4 h1:d1B3IXRitiMlY5ssEWRa//RQD24SqRPk/bCpL4/WyOA=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/graceful v0.0.0-20250529070945-92833db6f3a4/go.mod h1:faaKb5d5tz3NmQQ+NrTnBDa1G/tN9/CVuKun1V4WBIE=
 | 
					git.zhangdeman.cn/zhangdeman/graceful v0.0.0-20250529070945-92833db6f3a4/go.mod h1:faaKb5d5tz3NmQQ+NrTnBDa1G/tN9/CVuKun1V4WBIE=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20251012094811-1afd71fd8627 h1:chAmVCoiWMcrmm+AfvesrhnZH+3+6LZZb+8UDj/E36M=
 | 
					 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20251012094811-1afd71fd8627/go.mod h1:SZsX6q88TdR5JHZenesYhOw1x386ikfs2MkchQmW8D8=
 | 
					 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20251031042950-416e962cbf3b h1:+ca511XlP+HoBa2zB/ERSIE6yTiqiXpsgqvs64kRAZA=
 | 
					git.zhangdeman.cn/zhangdeman/logger v0.0.0-20251031042950-416e962cbf3b h1:+ca511XlP+HoBa2zB/ERSIE6yTiqiXpsgqvs64kRAZA=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20251031042950-416e962cbf3b/go.mod h1:tlQR2nfdP291Lug+b3BSu0q+kTPoSVNRL5dPq2nv9zQ=
 | 
					git.zhangdeman.cn/zhangdeman/logger v0.0.0-20251031042950-416e962cbf3b/go.mod h1:tlQR2nfdP291Lug+b3BSu0q+kTPoSVNRL5dPq2nv9zQ=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/network v0.0.0-20250726060351-78810e906bfa h1:r3AK2EKbQ82ShC5+AjbE95sqm90CkpbzLpmoV3zok9Q=
 | 
					 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/network v0.0.0-20250726060351-78810e906bfa/go.mod h1:v0tMMfXvE4WyUxaRo1r/D20BAbMkT5QPLSW7XtgQOxo=
 | 
					 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/network v0.0.0-20251013095944-5b89fff39bde h1:+3zIOditaUwzSpl2ybM1PYN4OYTIKiemMBt+pNv3Yko=
 | 
					git.zhangdeman.cn/zhangdeman/network v0.0.0-20251013095944-5b89fff39bde h1:+3zIOditaUwzSpl2ybM1PYN4OYTIKiemMBt+pNv3Yko=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/network v0.0.0-20251013095944-5b89fff39bde/go.mod h1:Ewh0UYOqXxEh0khgHj9bDz1rbnd7cCCsJrcOTFX/8wg=
 | 
					git.zhangdeman.cn/zhangdeman/network v0.0.0-20251013095944-5b89fff39bde/go.mod h1:Ewh0UYOqXxEh0khgHj9bDz1rbnd7cCCsJrcOTFX/8wg=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20251013024601-da007da2fb42 h1:VjYrb4adud7FHeiYS9XA0B/tOaJjfRejzQAlwimrrDc=
 | 
					git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20251013024601-da007da2fb42 h1:VjYrb4adud7FHeiYS9XA0B/tOaJjfRejzQAlwimrrDc=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20251013024601-da007da2fb42/go.mod h1:VHb9qmhaPDAQDcS6vUiDCamYjZ4R5lD1XtVsh55KsMI=
 | 
					git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20251013024601-da007da2fb42/go.mod h1:VHb9qmhaPDAQDcS6vUiDCamYjZ4R5lD1XtVsh55KsMI=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20251013044511-86c1a4a3a9dd h1:kTZOpR8iHx27sUufMWVYhDZx9Q4h80j7RWlaR8GIBiU=
 | 
					git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20251013044511-86c1a4a3a9dd h1:kTZOpR8iHx27sUufMWVYhDZx9Q4h80j7RWlaR8GIBiU=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20251013044511-86c1a4a3a9dd/go.mod h1:pLrQ63JICi81/3w2BrD26QZiu+IpddvEVfMJ6No3Xb4=
 | 
					git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20251013044511-86c1a4a3a9dd/go.mod h1:pLrQ63JICi81/3w2BrD26QZiu+IpddvEVfMJ6No3Xb4=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/trace v0.0.0-20250830115953-2779077bc555 h1:XQgYVEui0QKl5NXOvYpAg48zSc81obXF9cOinU8JuqQ=
 | 
					 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/trace v0.0.0-20250830115953-2779077bc555/go.mod h1:+tLRnfL+ddqljSTOacSJoIv7TpbdWih3efd8Yvk/Hh8=
 | 
					 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/trace v0.0.0-20251013092356-b7b9fb5f8a76 h1:Y1GME5dg3jFmoURKvuujK07VUNMpsuRR4FkhinfBQIs=
 | 
					git.zhangdeman.cn/zhangdeman/trace v0.0.0-20251013092356-b7b9fb5f8a76 h1:Y1GME5dg3jFmoURKvuujK07VUNMpsuRR4FkhinfBQIs=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/trace v0.0.0-20251013092356-b7b9fb5f8a76/go.mod h1:avN/muzbNjUM2qamRZeY4fuLEmA9cmfslk1dkdtRQBE=
 | 
					git.zhangdeman.cn/zhangdeman/trace v0.0.0-20251013092356-b7b9fb5f8a76/go.mod h1:avN/muzbNjUM2qamRZeY4fuLEmA9cmfslk1dkdtRQBE=
 | 
				
			||||||
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/go.mod h1:L/7JugxKZL3JP9JP/XDvPAPz0FQXG1u181Su1+u/d1c=
 | 
					 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20251013144324-313024336a6f h1:InxNoLPHBLwCLblW0lsL2P1ZBYoUEzw9Yh+KNLt4Xmg=
 | 
					git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20251013144324-313024336a6f h1:InxNoLPHBLwCLblW0lsL2P1ZBYoUEzw9Yh+KNLt4Xmg=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20251013144324-313024336a6f/go.mod h1:Pbs7tusW6RNcqrNCVcLE2zrM8JfPaO7lBJQuRiAzzLs=
 | 
					git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20251013144324-313024336a6f/go.mod h1:Pbs7tusW6RNcqrNCVcLE2zrM8JfPaO7lBJQuRiAzzLs=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20251013094128-d57d32b103be h1:mlmXacZHRKxmFmFKNFYRjZJ8+z2+QW3CH8L7AzoMTcQ=
 | 
					 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20251013094128-d57d32b103be/go.mod h1:mBvTwcdqHRF3QIkAh92j/JRhru2LzyJ2LBqolxjzzKE=
 | 
					 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20251014035305-c0ec06fa6dff h1:ym1Qs4diJe27CK/0K6vy7RvgH90mXgslWA++L8mXaKE=
 | 
					git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20251014035305-c0ec06fa6dff h1:ym1Qs4diJe27CK/0K6vy7RvgH90mXgslWA++L8mXaKE=
 | 
				
			||||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20251014035305-c0ec06fa6dff/go.mod h1:mBvTwcdqHRF3QIkAh92j/JRhru2LzyJ2LBqolxjzzKE=
 | 
					git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20251014035305-c0ec06fa6dff/go.mod h1:mBvTwcdqHRF3QIkAh92j/JRhru2LzyJ2LBqolxjzzKE=
 | 
				
			||||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
 | 
					github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
 | 
				
			||||||
@ -47,12 +36,8 @@ github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc
 | 
				
			|||||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
 | 
					github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
 | 
				
			||||||
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
 | 
					github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
 | 
				
			||||||
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
 | 
					github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
 | 
				
			||||||
github.com/bytedance/sonic v1.14.1 h1:FBMC0zVz5XUmE4z9wF4Jey0An5FueFvOsTKKKtwIl7w=
 | 
					 | 
				
			||||||
github.com/bytedance/sonic v1.14.1/go.mod h1:gi6uhQLMbTdeP0muCnrjHLeCUPyb70ujhnNlhOylAFc=
 | 
					 | 
				
			||||||
github.com/bytedance/sonic v1.14.2 h1:k1twIoe97C1DtYUo+fZQy865IuHia4PR5RPiuGPPIIE=
 | 
					github.com/bytedance/sonic v1.14.2 h1:k1twIoe97C1DtYUo+fZQy865IuHia4PR5RPiuGPPIIE=
 | 
				
			||||||
github.com/bytedance/sonic v1.14.2/go.mod h1:T80iDELeHiHKSc0C9tubFygiuXoGzrkjKzX2quAx980=
 | 
					github.com/bytedance/sonic v1.14.2/go.mod h1:T80iDELeHiHKSc0C9tubFygiuXoGzrkjKzX2quAx980=
 | 
				
			||||||
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
 | 
					 | 
				
			||||||
github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
 | 
					 | 
				
			||||||
github.com/bytedance/sonic/loader v0.4.0 h1:olZ7lEqcxtZygCK9EKYKADnpQoYkRQxaeY2NYzevs+o=
 | 
					github.com/bytedance/sonic/loader v0.4.0 h1:olZ7lEqcxtZygCK9EKYKADnpQoYkRQxaeY2NYzevs+o=
 | 
				
			||||||
github.com/bytedance/sonic/loader v0.4.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
 | 
					github.com/bytedance/sonic/loader v0.4.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
 | 
				
			||||||
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
 | 
					github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
 | 
				
			||||||
@ -60,11 +45,8 @@ github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gE
 | 
				
			|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
					github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
				
			||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 | 
					github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 | 
				
			||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
					github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
				
			||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
 | 
					 | 
				
			||||||
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU=
 | 
					github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU=
 | 
				
			||||||
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4=
 | 
					github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4=
 | 
				
			||||||
github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
 | 
					 | 
				
			||||||
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
 | 
					 | 
				
			||||||
github.com/gabriel-vasile/mimetype v1.4.11 h1:AQvxbp830wPhHTqc1u7nzoLT+ZFxGY7emj5DR5DYFik=
 | 
					github.com/gabriel-vasile/mimetype v1.4.11 h1:AQvxbp830wPhHTqc1u7nzoLT+ZFxGY7emj5DR5DYFik=
 | 
				
			||||||
github.com/gabriel-vasile/mimetype v1.4.11/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
 | 
					github.com/gabriel-vasile/mimetype v1.4.11/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
 | 
				
			||||||
github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
 | 
					github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
 | 
				
			||||||
@ -188,7 +170,6 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/
 | 
				
			|||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 | 
					github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 | 
				
			||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 | 
					github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 | 
				
			||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 | 
					github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 | 
				
			||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 | 
					 | 
				
			||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 | 
					github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 | 
				
			||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 | 
					github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 | 
				
			||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
 | 
					github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
 | 
				
			||||||
@ -209,8 +190,6 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
 | 
				
			|||||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
 | 
					github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
 | 
				
			||||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
 | 
					github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
 | 
				
			||||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
 | 
					github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
 | 
				
			||||||
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
 | 
					 | 
				
			||||||
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
 | 
					 | 
				
			||||||
github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY=
 | 
					github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY=
 | 
				
			||||||
github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
 | 
					github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
 | 
				
			||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 | 
					github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										31
									
								
								logger/instance.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								logger/instance.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					// Package logger ...
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Description : logger ...
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Author : go_developer@163.com<白茶清欢>
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Date : 2025-10-30 16:54
 | 
				
			||||||
 | 
					package logger
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "go.uber.org/zap"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						Instance = zap.NewNop()
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SetInstance 设置日志实例
 | 
				
			||||||
 | 
					func SetInstance(l *zap.Logger) {
 | 
				
			||||||
 | 
						if nil == l {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						Instance = l
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						RecordType = "GIN_LOG"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						CodeInjectCommonParam = "inject-common-param"
 | 
				
			||||||
 | 
						CodeLogicHook         = "logic-hook"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@ -11,11 +11,11 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"git.zhangdeman.cn/zhangdeman/trace"
 | 
						"git.zhangdeman.cn/zhangdeman/consts"
 | 
				
			||||||
	"git.zhangdeman.cn/zhangdeman/wrapper/op_ternary"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"git.zhangdeman.cn/zhangdeman/gin/define"
 | 
						"git.zhangdeman.cn/zhangdeman/gin/define"
 | 
				
			||||||
	"git.zhangdeman.cn/zhangdeman/gin/request/parse_body"
 | 
						"git.zhangdeman.cn/zhangdeman/gin/request/parse_body"
 | 
				
			||||||
 | 
						"git.zhangdeman.cn/zhangdeman/trace"
 | 
				
			||||||
 | 
						"git.zhangdeman.cn/zhangdeman/wrapper/op_ternary"
 | 
				
			||||||
	"github.com/gin-gonic/gin"
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -242,33 +242,29 @@ func (wh *wrapperHandle) ParseCookie(ctx *gin.Context) map[string]string {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetLogicAfterResponse ...
 | 
					// GetLogicAfterResponse ...
 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Author : go_developer@163.com<白茶清欢>
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Date : 16:54 2025/2/28
 | 
					 | 
				
			||||||
func (wh *wrapperHandle) GetLogicAfterResponse(ctx *gin.Context) *define.LogicAfterResponse {
 | 
					func (wh *wrapperHandle) GetLogicAfterResponse(ctx *gin.Context) *define.LogicAfterResponse {
 | 
				
			||||||
	if nil == ctx || nil == ctx.Request {
 | 
						if nil == ctx || nil == ctx.Request {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	l, exist := ctx.Get(define.LogicAfterResponseKey)
 | 
						l, exist := ctx.Get(consts.GinLogicAfterResponseKey)
 | 
				
			||||||
	if !exist || nil == l {
 | 
						if !exist || nil == l {
 | 
				
			||||||
		l = &define.LogicAfterResponse{
 | 
							l = &define.LogicAfterResponse{
 | 
				
			||||||
			SuccessHookFuncList: make([]func(), 0),
 | 
								SuccessHookFuncList: make([]func(ctx *gin.Context), 0),
 | 
				
			||||||
			FailureHookFuncList: make([]func(), 0),
 | 
								FailureHookFuncList: make([]func(ctx *gin.Context), 0),
 | 
				
			||||||
			Lock:                &sync.RWMutex{},
 | 
								Lock:                &sync.RWMutex{},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ctx.Set(define.LogicAfterResponseKey, l)
 | 
							ctx.Set(consts.GinLogicAfterResponseKey, l)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// 就这么写, key值如果被其他人覆盖成非法值, 此处会直接panic
 | 
						// 就这么写, key值如果被其他人覆盖成非法值, 此处会直接panic
 | 
				
			||||||
	return l.(*define.LogicAfterResponse)
 | 
						return l.(*define.LogicAfterResponse)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetCustomContext 获取自定义context
 | 
					 | 
				
			||||||
func (wh *wrapperHandle) GetCustomContext(ctx *gin.Context) *define.Context {
 | 
					 | 
				
			||||||
	return define.NewContext(ctx)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetTraceInstance 获取trace实例
 | 
					// GetTraceInstance 获取trace实例
 | 
				
			||||||
func (wh *wrapperHandle) GetTraceInstance(ctx *gin.Context) *trace.Runtime {
 | 
					func (wh *wrapperHandle) GetTraceInstance(ctx *gin.Context) *trace.Runtime {
 | 
				
			||||||
	return define.NewContext(ctx).Trace
 | 
						i, exist := ctx.Get(consts.GinTraceInstanceField)
 | 
				
			||||||
 | 
						if !exist || nil == i {
 | 
				
			||||||
 | 
							i = trace.NewRuntime(wh.GetCtxStringData(ctx, consts.GinTraceIDField, ""), 2)
 | 
				
			||||||
 | 
							ctx.Set(consts.GinTraceInstanceField, i)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return i.(*trace.Runtime)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										119
									
								
								router/common_param.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								router/common_param.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,119 @@
 | 
				
			|||||||
 | 
					// Package router ...
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Description : router ...
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Author : go_developer@163.com<白茶清欢>
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Date : 2025-10-30 15:39
 | 
				
			||||||
 | 
					package router
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.zhangdeman.cn/zhangdeman/gin/logger"
 | 
				
			||||||
 | 
						"git.zhangdeman.cn/zhangdeman/gin/util"
 | 
				
			||||||
 | 
						pkgLogger "git.zhangdeman.cn/zhangdeman/logger"
 | 
				
			||||||
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetCommonParam 获取公共参数
 | 
				
			||||||
 | 
					type GetCommonParam func(ctx *gin.Context) (any, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AddCommonParamRule 添加公共参数注入规则
 | 
				
			||||||
 | 
					func (s *server) AddCommonParamRule(fieldName string, getParamFunc GetCommonParam) {
 | 
				
			||||||
 | 
						s.commonParam[fieldName] = getParamFunc
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AddCommonParamRules 批量添加公共参数注入规则
 | 
				
			||||||
 | 
					func (s *server) AddCommonParamRules(rules map[string]GetCommonParam) {
 | 
				
			||||||
 | 
						for fieldName, rule := range rules {
 | 
				
			||||||
 | 
							s.AddCommonParamRule(fieldName, rule)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// injectCommonParam 注入公共参数
 | 
				
			||||||
 | 
					func (s *server) injectCommonParam(ctx *gin.Context, formValue any) error {
 | 
				
			||||||
 | 
						innerCtx := util.GinCtxToContext(ctx)
 | 
				
			||||||
 | 
						var (
 | 
				
			||||||
 | 
							val              any
 | 
				
			||||||
 | 
							err              error
 | 
				
			||||||
 | 
							reflectFormValue reflect.Value
 | 
				
			||||||
 | 
							reflectType      reflect.Type
 | 
				
			||||||
 | 
							ok               bool
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if reflectFormValue, ok = formValue.(reflect.Value); !ok {
 | 
				
			||||||
 | 
							reflectFormValue = reflect.ValueOf(formValue)
 | 
				
			||||||
 | 
							reflectType = reflect.TypeOf(formValue)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							reflectType = reflectFormValue.Type()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fieldTable := map[string]bool{}
 | 
				
			||||||
 | 
						fieldNum := reflectType.Elem().NumField()
 | 
				
			||||||
 | 
						for i := 0; i < fieldNum; i++ {
 | 
				
			||||||
 | 
							if reflectType.Elem().Field(i).Anonymous && // 是匿名字段, 再做一次解析
 | 
				
			||||||
 | 
								((reflectType.Elem().Field(i).Type.Kind() == reflect.Ptr && reflectType.Elem().Field(i).Type.Kind() == reflect.Struct) || // 结构体指针
 | 
				
			||||||
 | 
									reflectType.Elem().Field(i).Type.Kind() == reflect.Struct) { // 结构体
 | 
				
			||||||
 | 
								anonymousFieldType := reflectType.Elem().Field(i).Type
 | 
				
			||||||
 | 
								if anonymousFieldType.Kind() == reflect.Ptr {
 | 
				
			||||||
 | 
									anonymousFieldType = anonymousFieldType.Elem()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								for j := 0; j < anonymousFieldType.NumField(); j++ {
 | 
				
			||||||
 | 
									fieldTable[anonymousFieldType.Field(j).Name] = true
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								// 提取全部结构体字段
 | 
				
			||||||
 | 
								fieldTable[reflectType.Elem().Field(i).Name] = true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for fieldName, getParamFunc := range s.commonParam {
 | 
				
			||||||
 | 
							if _, ok = fieldTable[fieldName]; !ok {
 | 
				
			||||||
 | 
								// 结构体字段未配置自动注入
 | 
				
			||||||
 | 
								logger.Instance.Debug("当前结构体不包含指定字段, 忽略执行", pkgLogger.NewLogData(innerCtx, logger.RecordType, logger.CodeInjectCommonParam, map[string]any{
 | 
				
			||||||
 | 
									"field_name": fieldName,
 | 
				
			||||||
 | 
									"struct":     reflectFormValue.Elem().Type().String(),
 | 
				
			||||||
 | 
								}).ToFieldList()...)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							fieldValue := reflectFormValue.Elem().FieldByName(fieldName)
 | 
				
			||||||
 | 
							if !fieldValue.IsZero() {
 | 
				
			||||||
 | 
								// 表单次数不为空, 说明从参数中传递, 不做覆盖填充
 | 
				
			||||||
 | 
								logger.Instance.Debug("指定字段已赋值, 不做重新覆盖填充处理, 跳过", pkgLogger.NewLogData(innerCtx, logger.RecordType, logger.CodeInjectCommonParam, map[string]any{
 | 
				
			||||||
 | 
									"field_name":       fieldName,
 | 
				
			||||||
 | 
									"struct":           reflectFormValue.Elem().Type().String(),
 | 
				
			||||||
 | 
									"input_form_value": fieldValue.Interface(),
 | 
				
			||||||
 | 
								}).ToFieldList()...)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if val, err = getParamFunc(ctx); nil != err {
 | 
				
			||||||
 | 
								logger.Instance.Error("获取公共结构体字段参数值失败", pkgLogger.NewLogData(innerCtx, logger.RecordType, logger.CodeInjectCommonParam, map[string]any{
 | 
				
			||||||
 | 
									"field_name": fieldName,
 | 
				
			||||||
 | 
									"err_msg":    err.Error(),
 | 
				
			||||||
 | 
								}).ToFieldList()...)
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !fieldValue.CanSet() {
 | 
				
			||||||
 | 
								logDataList := pkgLogger.NewLogData(util.GinCtxToContext(ctx), logger.RecordType, logger.CodeInjectCommonParam, map[string]any{
 | 
				
			||||||
 | 
									"field_name": fieldName,
 | 
				
			||||||
 | 
									"field_type": fieldValue.Type().String(),
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								logger.Instance.Error("结构体字段不可设置值", logDataList.ToFieldList()...)
 | 
				
			||||||
 | 
								return errors.New(fieldName + ": 结构体字段不可设置值")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							reflectVal := reflect.ValueOf(val)
 | 
				
			||||||
 | 
							if reflectVal.Type() != fieldValue.Type() {
 | 
				
			||||||
 | 
								logDataList := pkgLogger.NewLogData(util.GinCtxToContext(ctx), logger.RecordType, logger.CodeInjectCommonParam, map[string]any{
 | 
				
			||||||
 | 
									"field_name": fieldName,
 | 
				
			||||||
 | 
									"field_type": fieldValue.Type().String(),
 | 
				
			||||||
 | 
									"value_type": reflectVal.Type().String(),
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								logger.Instance.Error("返回数据类型与字段类型不一致", logDataList.ToFieldList()...)
 | 
				
			||||||
 | 
								return errors.New(fieldName + ": 字段自动注入, 返回数据类型与字段类型不一致")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// 设置值
 | 
				
			||||||
 | 
							fieldValue.Set(reflectVal)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -12,10 +12,6 @@ import "strings"
 | 
				
			|||||||
var defaultValidateErrTag = "err"
 | 
					var defaultValidateErrTag = "err"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SetValidateErrTag 设置验证失败时, 获取错误信息的tag字段
 | 
					// SetValidateErrTag 设置验证失败时, 获取错误信息的tag字段
 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Author : go_developer@163.com<白茶清欢>
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Date : 17:42 2025/2/7
 | 
					 | 
				
			||||||
func SetValidateErrTag(tagName string) {
 | 
					func SetValidateErrTag(tagName string) {
 | 
				
			||||||
	tagName = strings.TrimSpace(tagName)
 | 
						tagName = strings.TrimSpace(tagName)
 | 
				
			||||||
	if tagName == "" {
 | 
						if tagName == "" {
 | 
				
			||||||
 | 
				
			|||||||
@ -13,10 +13,6 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// controller 解析controller有哪些方法要注册为接口
 | 
					// controller 解析controller有哪些方法要注册为接口
 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Author : go_developer@163.com<白茶清欢>
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Date : 15:30 2025/1/27
 | 
					 | 
				
			||||||
type controller struct {
 | 
					type controller struct {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -71,7 +67,7 @@ func (c controller) methodConfig(reflectMethod reflect.Method) (cfg UriConfig, n
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	// 第一个参数必须是 *gin.Context 或者 *define.Context
 | 
						// 第一个参数必须是 *gin.Context 或者 *define.Context
 | 
				
			||||||
	paramOne := methodType.In(1).String()
 | 
						paramOne := methodType.In(1).String()
 | 
				
			||||||
	if paramOne != GinContextType && paramOne != CustomContextType {
 | 
						if paramOne != GinContextType {
 | 
				
			||||||
		needRegister = false
 | 
							needRegister = false
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -107,13 +103,14 @@ func (c controller) methodConfig(reflectMethod reflect.Method) (cfg UriConfig, n
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// 解析meta信息
 | 
						// 解析meta信息
 | 
				
			||||||
	cfg.CtxType = paramOne
 | 
					 | 
				
			||||||
	cfg.Path = metaField.Tag.Get(TagNamePath)
 | 
						cfg.Path = metaField.Tag.Get(TagNamePath)
 | 
				
			||||||
	cfg.RequestMethod = metaField.Tag.Get(TagNameMethod)
 | 
						cfg.RequestMethod = metaField.Tag.Get(TagNameMethod)
 | 
				
			||||||
	cfg.Desc = metaField.Tag.Get(TagNameDesc)
 | 
						cfg.Desc = metaField.Tag.Get(TagNameDesc)
 | 
				
			||||||
	cfg.TagList = strings.Split(metaField.Tag.Get(TagNameUriTag), ",")
 | 
						cfg.TagList = strings.Split(metaField.Tag.Get(TagNameUriTag), ",")
 | 
				
			||||||
	// 解析第一个返回值, 要求必须是结构体或者是map
 | 
						// 解析第一个返回值, 要求必须是结构体或者是map
 | 
				
			||||||
	outputStrictModel := metaField.Tag.Get(TagNameOutputStrict)
 | 
						outputStrictModel := metaField.Tag.Get(TagNameOutputStrict)
 | 
				
			||||||
 | 
						hookSync := strings.ToLower(metaField.Tag.Get(TagNameHookSync))
 | 
				
			||||||
 | 
						cfg.HookSync = hookSync == "1" || hookSync == "true" // 同步执行判断
 | 
				
			||||||
	cfg.OutputStrict = outputStrictModel == "1" || outputStrictModel == "true"
 | 
						cfg.OutputStrict = outputStrictModel == "1" || outputStrictModel == "true"
 | 
				
			||||||
	if cfg.OutputStrict {
 | 
						if cfg.OutputStrict {
 | 
				
			||||||
		// 开启输出严格模式校验
 | 
							// 开启输出严格模式校验
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,6 @@ const (
 | 
				
			|||||||
	PrefixFuncName         = "RouterPrefix"     // 路由前缀函数名称
 | 
						PrefixFuncName         = "RouterPrefix"     // 路由前缀函数名称
 | 
				
			||||||
	MiddlewareFuncName     = "RouterMiddleware" // 路由中间件函数名称
 | 
						MiddlewareFuncName     = "RouterMiddleware" // 路由中间件函数名称
 | 
				
			||||||
	GinContextType         = "*gin.Context"     // gin context 类型名称
 | 
						GinContextType         = "*gin.Context"     // gin context 类型名称
 | 
				
			||||||
	CustomContextType      = "*define.Context"  // custom context 类型名称
 | 
					 | 
				
			||||||
	ErrorType              = "error"            // error类型
 | 
						ErrorType              = "error"            // error类型
 | 
				
			||||||
	ErrorInterfaceFuncName = "Error"            // error接口需要实现的方法名称
 | 
						ErrorInterfaceFuncName = "Error"            // error接口需要实现的方法名称
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@ -26,6 +25,7 @@ const (
 | 
				
			|||||||
	TagNameUriTag       = "tag"           // 接口的tag
 | 
						TagNameUriTag       = "tag"           // 接口的tag
 | 
				
			||||||
	TagNameDesc         = "desc"          // 接口的描述
 | 
						TagNameDesc         = "desc"          // 接口的描述
 | 
				
			||||||
	TagNameOutputStrict = "output_strict" // 接口数据是否为严格模式 : 严格模式, 响应数据必须是结构体/map,非严格模式返回任意值
 | 
						TagNameOutputStrict = "output_strict" // 接口数据是否为严格模式 : 严格模式, 响应数据必须是结构体/map,非严格模式返回任意值
 | 
				
			||||||
 | 
						TagNameHookSync     = "hook-sync"     // hook同步执行
 | 
				
			||||||
	TagNameBinding      = "binding"       // gin 内置的验证规则tag
 | 
						TagNameBinding      = "binding"       // gin 内置的验证规则tag
 | 
				
			||||||
	TagNameValidate     = "validate"      // validator v10 默认的验证规则tag
 | 
						TagNameValidate     = "validate"      // validator v10 默认的验证规则tag
 | 
				
			||||||
	TagNameErrMsg       = "err"           // 验证失败错误信息tag
 | 
						TagNameErrMsg       = "err"           // 验证失败错误信息tag
 | 
				
			||||||
@ -42,7 +42,7 @@ type UriConfig struct {
 | 
				
			|||||||
	TagList        []string       `json:"tag_list"`       // 接口分组
 | 
						TagList        []string       `json:"tag_list"`       // 接口分组
 | 
				
			||||||
	Desc           string         `json:"desc"`           // 接口描述
 | 
						Desc           string         `json:"desc"`           // 接口描述
 | 
				
			||||||
	OutputStrict   bool           `json:"output_strict"`  // 接口是否为严格模式 : 不配置,可返回任意类型, 配置, 必须返回结构体或者map
 | 
						OutputStrict   bool           `json:"output_strict"`  // 接口是否为严格模式 : 不配置,可返回任意类型, 配置, 必须返回结构体或者map
 | 
				
			||||||
	CtxType        string         `json:"ctx_type"`       // ctx参数类型
 | 
						HookSync       bool           `json:"hook_sync"`      // 接口主逻辑执行完成之后,hook是否同步执行, 默认异步执行
 | 
				
			||||||
	FormDataType   reflect.Type   `json:"-"`              // 表单数据类型
 | 
						FormDataType   reflect.Type   `json:"-"`              // 表单数据类型
 | 
				
			||||||
	ResultDataType reflect.Type   `json:"-"`              // 返回值数据类型
 | 
						ResultDataType reflect.Type   `json:"-"`              // 返回值数据类型
 | 
				
			||||||
	ApiStructValue reflect.Value  `json:"-"`              // 逻辑函数所属结构体取值
 | 
						ApiStructValue reflect.Value  `json:"-"`              // 逻辑函数所属结构体取值
 | 
				
			||||||
@ -50,10 +50,6 @@ type UriConfig struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UriParam 接口参数配置
 | 
					// UriParam 接口参数配置
 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Author : go_developer@163.com<白茶清欢>
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Date : 15:40 2025/1/27
 | 
					 | 
				
			||||||
type UriParam struct {
 | 
					type UriParam struct {
 | 
				
			||||||
	Field           string `json:"field"`             // 结构体字段
 | 
						Field           string `json:"field"`             // 结构体字段
 | 
				
			||||||
	Name            string `json:"name"`              // 参数名称
 | 
						Name            string `json:"name"`              // 参数名称
 | 
				
			||||||
 | 
				
			|||||||
@ -12,94 +12,94 @@ import (
 | 
				
			|||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.zhangdeman.cn/zhangdeman/consts"
 | 
				
			||||||
	"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"
 | 
				
			||||||
 | 
						"github.com/mcuadros/go-defaults"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RequestHandler 获取请求处理方法
 | 
					func (s *server) getFormInitValue(ctx *gin.Context, uriCfg UriConfig) (any, error) {
 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Author : go_developer@163.com<白茶清欢>
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Date : 19:44 2025/1/27
 | 
					 | 
				
			||||||
func RequestHandler(uriCfg UriConfig) gin.HandlerFunc {
 | 
					 | 
				
			||||||
	return func(ctx *gin.Context) {
 | 
					 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
 | 
							formParam reflect.Value
 | 
				
			||||||
 | 
							formValue any
 | 
				
			||||||
		err       error
 | 
							err       error
 | 
				
			||||||
			ok  bool
 | 
					 | 
				
			||||||
			e   exception.IException
 | 
					 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var formParam reflect.Value
 | 
					 | 
				
			||||||
	if uriCfg.FormDataType.Kind() == reflect.Ptr {
 | 
						if uriCfg.FormDataType.Kind() == reflect.Ptr {
 | 
				
			||||||
		formParam = reflect.New(uriCfg.FormDataType.Elem())
 | 
							formParam = reflect.New(uriCfg.FormDataType.Elem())
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// 表单解析
 | 
							// 表单解析
 | 
				
			||||||
		formParam = reflect.New(uriCfg.FormDataType)
 | 
							formParam = reflect.New(uriCfg.FormDataType)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
		formValue := formParam.Interface()
 | 
						formValue = formParam.Interface()
 | 
				
			||||||
	if err = request.Form.Parse(ctx, formValue); nil != err {
 | 
						if err = request.Form.Parse(ctx, formValue); nil != err {
 | 
				
			||||||
		// 格式化验证错误的信息
 | 
							// 格式化验证错误的信息
 | 
				
			||||||
		err = GetValidateErr(formValue, err)
 | 
							err = GetValidateErr(formValue, err)
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return formValue, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RequestHandler 获取请求处理方法
 | 
				
			||||||
 | 
					func (s *server) RequestHandler(uriCfg UriConfig) gin.HandlerFunc {
 | 
				
			||||||
 | 
						return func(ctx *gin.Context) {
 | 
				
			||||||
 | 
							var (
 | 
				
			||||||
 | 
								err        error
 | 
				
			||||||
 | 
								ok         bool
 | 
				
			||||||
 | 
								e          exception.IException
 | 
				
			||||||
 | 
								formValue  any
 | 
				
			||||||
 | 
								firstParam reflect.Value
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if formValue, err = s.getFormInitValue(ctx, uriCfg); nil != err {
 | 
				
			||||||
			e = exception.NewFromError(400, err)
 | 
								e = exception.NewFromError(400, err)
 | 
				
			||||||
			response.SendWithException(ctx, e, &define.ResponseOption{
 | 
								response.SendWithException(ctx, e, &define.ResponseOption{
 | 
				
			||||||
				ContentType: "application/json;charset=utf-8",
 | 
									ContentType: consts.MimeTypeJson,
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								ctx.Abort()
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// 表单数据
 | 
				
			||||||
 | 
							inputValue := reflect.ValueOf(formValue)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// 注入公共参数
 | 
				
			||||||
 | 
							if err = s.injectCommonParam(ctx, inputValue); nil != err {
 | 
				
			||||||
 | 
								e = exception.NewFromError(500, err)
 | 
				
			||||||
 | 
								response.SendWithException(ctx, e, &define.ResponseOption{
 | 
				
			||||||
 | 
									ContentType: consts.MimeTypeJson,
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
			ctx.Abort()
 | 
								ctx.Abort()
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		isSuccess := false
 | 
							// 非必传参数设置默认值
 | 
				
			||||||
 | 
							defaults.SetDefaults(formValue)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// 默认请求失败
 | 
				
			||||||
 | 
							ctx.Set(consts.GinRequestSuccess, false)
 | 
				
			||||||
		// 初始化响应之后logic
 | 
							// 初始化响应之后logic
 | 
				
			||||||
		logicAfterResponse := &define.LogicAfterResponse{
 | 
							logicAfterResponse := &define.LogicAfterResponse{
 | 
				
			||||||
			SuccessHookFuncList: make([]func(), 0),
 | 
								SuccessHookFuncList: make([]func(ctx *gin.Context), 0),
 | 
				
			||||||
			FailureHookFuncList: make([]func(), 0),
 | 
								FailureHookFuncList: make([]func(ctx *gin.Context), 0),
 | 
				
			||||||
			Lock:                &sync.RWMutex{},
 | 
								Lock:                &sync.RWMutex{},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// 此处暴露出去,是为了使用方可以获取到对应数据
 | 
							// 此处暴露出去,是为了使用方可以获取到对应数据
 | 
				
			||||||
		ctx.Set(define.LogicAfterResponseKey, logicAfterResponse)
 | 
							ctx.Set(consts.GinLogicAfterResponseKey, logicAfterResponse)
 | 
				
			||||||
		defer func() {
 | 
							defer s.hook(ctx, uriCfg) // 执行Logic之后的相关逻辑
 | 
				
			||||||
			go func() {
 | 
					 | 
				
			||||||
				// 执行响应之后的相关逻辑
 | 
					 | 
				
			||||||
				defer func() {
 | 
					 | 
				
			||||||
					if r := recover(); r != nil {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}()
 | 
					 | 
				
			||||||
				if isSuccess {
 | 
					 | 
				
			||||||
					for _, itemFunc := range logicAfterResponse.SuccessHookFuncList {
 | 
					 | 
				
			||||||
						if nil != itemFunc {
 | 
					 | 
				
			||||||
							itemFunc()
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					for _, itemFunc := range logicAfterResponse.FailureHookFuncList {
 | 
					 | 
				
			||||||
						if nil != itemFunc {
 | 
					 | 
				
			||||||
							itemFunc()
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}()
 | 
					 | 
				
			||||||
		}()
 | 
					 | 
				
			||||||
		// 执行逻辑
 | 
							// 执行逻辑
 | 
				
			||||||
		inputValue := reflect.ValueOf(formValue)
 | 
					 | 
				
			||||||
		if uriCfg.FormDataType.Kind() != reflect.Ptr {
 | 
							if uriCfg.FormDataType.Kind() != reflect.Ptr {
 | 
				
			||||||
			inputValue = inputValue.Elem()
 | 
								inputValue = inputValue.Elem()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		var firstParam reflect.Value
 | 
					
 | 
				
			||||||
		if uriCfg.CtxType == CustomContextType {
 | 
					 | 
				
			||||||
			customCtx := ctx.MustGet(define.CustomContextKey)
 | 
					 | 
				
			||||||
			firstParam = reflect.ValueOf(customCtx)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
		firstParam = reflect.ValueOf(ctx)
 | 
							firstParam = reflect.ValueOf(ctx)
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		resList := uriCfg.ApiLogicFunc.Func.Call([]reflect.Value{uriCfg.ApiStructValue, firstParam, inputValue})
 | 
							resList := uriCfg.ApiLogicFunc.Func.Call([]reflect.Value{uriCfg.ApiStructValue, firstParam, inputValue})
 | 
				
			||||||
		if resList[1].IsNil() {
 | 
							if resList[1].IsNil() {
 | 
				
			||||||
			// 请求成功
 | 
								// 请求成功, 更新标识
 | 
				
			||||||
			isSuccess = true
 | 
								ctx.Set(consts.GinRequestSuccess, true)
 | 
				
			||||||
			response.SuccessWithExtension(ctx, resList[0].Interface(), &define.ResponseOption{ContentType: "application/json;charset=utf-8"})
 | 
								response.SuccessWithExtension(ctx, resList[0].Interface(), &define.ResponseOption{ContentType: consts.MimeTypeJson})
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// 请求失败
 | 
							// 请求失败
 | 
				
			||||||
@ -113,7 +113,7 @@ func RequestHandler(uriCfg UriConfig) gin.HandlerFunc {
 | 
				
			|||||||
			})
 | 
								})
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		response.SendWithException(ctx, e, &define.ResponseOption{
 | 
							response.SendWithException(ctx, e, &define.ResponseOption{
 | 
				
			||||||
			ContentType: "application/json;charset=utf-8",
 | 
								ContentType: consts.MimeTypeJson,
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										74
									
								
								router/hook.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								router/hook.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,74 @@
 | 
				
			|||||||
 | 
					// Package router ...
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Description : router ...
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Author : go_developer@163.com<白茶清欢>
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Date : 2025-11-01 12:34
 | 
				
			||||||
 | 
					package router
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"git.zhangdeman.cn/zhangdeman/consts"
 | 
				
			||||||
 | 
						"git.zhangdeman.cn/zhangdeman/gin/define"
 | 
				
			||||||
 | 
						"git.zhangdeman.cn/zhangdeman/gin/logger"
 | 
				
			||||||
 | 
						"git.zhangdeman.cn/zhangdeman/gin/util"
 | 
				
			||||||
 | 
						pkgLogger "git.zhangdeman.cn/zhangdeman/logger"
 | 
				
			||||||
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// hook 执行hook逻辑
 | 
				
			||||||
 | 
					func (s *server) hook(ctx *gin.Context, uriCfg UriConfig) {
 | 
				
			||||||
 | 
						responseAfter, exist := ctx.Get(consts.GinLogicAfterResponseKey)
 | 
				
			||||||
 | 
						innerContext := util.GinCtxToContext(ctx)
 | 
				
			||||||
 | 
						if !exist || nil != responseAfter {
 | 
				
			||||||
 | 
							// 未配置
 | 
				
			||||||
 | 
							logger.Instance.Debug("未配置Logic执行后的hook逻辑", pkgLogger.NewLogData(innerContext, logger.RecordType, logger.CodeLogicHook, map[string]any{
 | 
				
			||||||
 | 
								"uri":                      uriCfg.Path,
 | 
				
			||||||
 | 
								"logic_after_response_key": consts.GinLogicAfterResponseKey,
 | 
				
			||||||
 | 
							}).ToFieldList()...)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						isSuccess, exist := ctx.Get(consts.GinRequestSuccess)
 | 
				
			||||||
 | 
						success := false
 | 
				
			||||||
 | 
						if nil != isSuccess && (isSuccess == "1" || isSuccess == "true" || isSuccess.(bool)) {
 | 
				
			||||||
 | 
							success = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						hookInstance := responseAfter.(*define.LogicAfterResponse)
 | 
				
			||||||
 | 
						if uriCfg.HookSync {
 | 
				
			||||||
 | 
							// 同步执行
 | 
				
			||||||
 | 
							s.hookAfter(ctx, uriCfg, hookInstance, success)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							// 异步执行
 | 
				
			||||||
 | 
							go s.hookAfter(ctx, uriCfg, hookInstance, success)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *server) hookAfter(ctx *gin.Context, uriCfg UriConfig, hookInstance *define.LogicAfterResponse, success bool) {
 | 
				
			||||||
 | 
						innerContext := util.GinCtxToContext(ctx)
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if err := recover(); err != nil {
 | 
				
			||||||
 | 
								logger.Instance.Error("hook执行异常", pkgLogger.NewLogData(innerContext, logger.RecordType, logger.CodeLogicHook, map[string]any{
 | 
				
			||||||
 | 
									"uri":                      uriCfg.Path,
 | 
				
			||||||
 | 
									"logic_after_response_key": consts.GinLogicAfterResponseKey,
 | 
				
			||||||
 | 
									"error":                    err.(error).Error(),
 | 
				
			||||||
 | 
									"logic_success":            success,
 | 
				
			||||||
 | 
								}).ToFieldList()...)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						if success {
 | 
				
			||||||
 | 
							logger.Instance.Debug("接口Logic执行成功, 执行Hook逻辑")
 | 
				
			||||||
 | 
							for _, itemFunc := range hookInstance.SuccessHookFuncList {
 | 
				
			||||||
 | 
								if nil != itemFunc {
 | 
				
			||||||
 | 
									itemFunc(ctx)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							for _, itemFunc := range hookInstance.FailureHookFuncList {
 | 
				
			||||||
 | 
								if nil != itemFunc {
 | 
				
			||||||
 | 
									itemFunc(ctx)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -13,7 +13,8 @@ package router
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
// method: 请求方法: get/post 等
 | 
					// method: 请求方法: get/post 等
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Author : go_developer@163.com<白茶清欢>
 | 
					// 使用示例如下:
 | 
				
			||||||
//
 | 
					// type RequestForm struct {
 | 
				
			||||||
// Date : 21:40 2024/7/20
 | 
					//	Meta `json:"-" path:"接口路由" method:"get,post" sse:"1" tag:"接口分组标签" summary:"接口描述"`
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
type Meta struct{}
 | 
					type Meta struct{}
 | 
				
			||||||
 | 
				
			|||||||
@ -11,11 +11,10 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"git.zhangdeman.cn/zhangdeman/graceful"
 | 
						"git.zhangdeman.cn/zhangdeman/graceful"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"git.zhangdeman.cn/zhangdeman/gin/define"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	apiDoc "git.zhangdeman.cn/zhangdeman/api-doc"
 | 
						apiDoc "git.zhangdeman.cn/zhangdeman/api-doc"
 | 
				
			||||||
	"git.zhangdeman.cn/zhangdeman/consts"
 | 
						"git.zhangdeman.cn/zhangdeman/consts"
 | 
				
			||||||
	"git.zhangdeman.cn/zhangdeman/gin/middleware"
 | 
						"git.zhangdeman.cn/zhangdeman/gin/middleware"
 | 
				
			||||||
@ -66,10 +65,6 @@ func newServerOption(port int, optionList ...SetServerOptionFunc) *serverOption
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewServer server实例
 | 
					// NewServer server实例
 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Author : go_developer@163.com<白茶清欢>
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Date : 18:20 2025/2/7
 | 
					 | 
				
			||||||
func NewServer(port int, optionList ...SetServerOptionFunc) *server {
 | 
					func NewServer(port int, optionList ...SetServerOptionFunc) *server {
 | 
				
			||||||
	if port < 80 {
 | 
						if port < 80 {
 | 
				
			||||||
		panic("port should be greater than 80")
 | 
							panic("port should be greater than 80")
 | 
				
			||||||
@ -85,10 +80,6 @@ func NewServer(port int, optionList ...SetServerOptionFunc) *server {
 | 
				
			|||||||
	// CustomContext 必须在第一个, 并且进行初始化
 | 
						// CustomContext 必须在第一个, 并且进行初始化
 | 
				
			||||||
	globalMiddlewareList = append(
 | 
						globalMiddlewareList = append(
 | 
				
			||||||
		globalMiddlewareList,
 | 
							globalMiddlewareList,
 | 
				
			||||||
		func(ctx *gin.Context) {
 | 
					 | 
				
			||||||
			// 初始化上下文以及基础信息
 | 
					 | 
				
			||||||
			_ = define.NewContext(ctx)
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	if nil != option.loggerCfg {
 | 
						if nil != option.loggerCfg {
 | 
				
			||||||
		// 请求日志记录中间件
 | 
							// 请求日志记录中间件
 | 
				
			||||||
@ -129,6 +120,8 @@ func NewServer(port int, optionList ...SetServerOptionFunc) *server {
 | 
				
			|||||||
		uiInstance:  apiDoc.NewSwaggerUI(option.serverInfo, option.serverList, apiDocEnum.SwaggerUITheme(option.swaggerUiTheme)),
 | 
							uiInstance:  apiDoc.NewSwaggerUI(option.serverInfo, option.serverList, apiDocEnum.SwaggerUITheme(option.swaggerUiTheme)),
 | 
				
			||||||
		port:        port,
 | 
							port:        port,
 | 
				
			||||||
		option:      option,
 | 
							option:      option,
 | 
				
			||||||
 | 
							lock:        &sync.RWMutex{},
 | 
				
			||||||
 | 
							commonParam: map[string]GetCommonParam{},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -137,6 +130,8 @@ type server struct {
 | 
				
			|||||||
	port        int
 | 
						port        int
 | 
				
			||||||
	uiInstance  *apiDoc.SwaggerUI
 | 
						uiInstance  *apiDoc.SwaggerUI
 | 
				
			||||||
	option      *serverOption
 | 
						option      *serverOption
 | 
				
			||||||
 | 
						commonParam map[string]GetCommonParam // 结构体字段名, 注意, 不是TAG
 | 
				
			||||||
 | 
						lock        *sync.RWMutex
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Start 启动服务
 | 
					// Start 启动服务
 | 
				
			||||||
@ -201,21 +196,22 @@ func (s *server) Group(routerPrefix string, middlewareList []gin.HandlerFunc, cL
 | 
				
			|||||||
		for _, itemUriCfg := range urlTable {
 | 
							for _, itemUriCfg := range urlTable {
 | 
				
			||||||
			_ = s.uiInstance.DocInstance().AddApiFromInAndOut(routerPrefix, itemUriCfg.FormDataType, itemUriCfg.ResultDataType)
 | 
								_ = s.uiInstance.DocInstance().AddApiFromInAndOut(routerPrefix, itemUriCfg.FormDataType, itemUriCfg.ResultDataType)
 | 
				
			||||||
			method := strings.ToUpper(itemUriCfg.RequestMethod)
 | 
								method := strings.ToUpper(itemUriCfg.RequestMethod)
 | 
				
			||||||
 | 
								handleFunc := s.RequestHandler(itemUriCfg)
 | 
				
			||||||
			switch method {
 | 
								switch method {
 | 
				
			||||||
			case http.MethodGet:
 | 
								case http.MethodGet:
 | 
				
			||||||
				g.GET(itemUriCfg.Path, RequestHandler(itemUriCfg))
 | 
									g.GET(itemUriCfg.Path, handleFunc)
 | 
				
			||||||
			case http.MethodHead:
 | 
								case http.MethodHead:
 | 
				
			||||||
				g.HEAD(itemUriCfg.Path, RequestHandler(itemUriCfg))
 | 
									g.HEAD(itemUriCfg.Path, handleFunc)
 | 
				
			||||||
			case http.MethodPost:
 | 
								case http.MethodPost:
 | 
				
			||||||
				g.POST(itemUriCfg.Path, RequestHandler(itemUriCfg))
 | 
									g.POST(itemUriCfg.Path, handleFunc)
 | 
				
			||||||
			case http.MethodPut:
 | 
								case http.MethodPut:
 | 
				
			||||||
				g.PUT(itemUriCfg.Path, RequestHandler(itemUriCfg))
 | 
									g.PUT(itemUriCfg.Path, handleFunc)
 | 
				
			||||||
			case http.MethodPatch:
 | 
								case http.MethodPatch:
 | 
				
			||||||
				g.PATCH(itemUriCfg.Path, RequestHandler(itemUriCfg))
 | 
									g.PATCH(itemUriCfg.Path, handleFunc)
 | 
				
			||||||
			case http.MethodDelete:
 | 
								case http.MethodDelete:
 | 
				
			||||||
				g.DELETE(itemUriCfg.Path, RequestHandler(itemUriCfg))
 | 
									g.DELETE(itemUriCfg.Path, handleFunc)
 | 
				
			||||||
			case http.MethodOptions:
 | 
								case http.MethodOptions:
 | 
				
			||||||
				g.OPTIONS(itemUriCfg.Path, RequestHandler(itemUriCfg))
 | 
									g.OPTIONS(itemUriCfg.Path, handleFunc)
 | 
				
			||||||
			case http.MethodTrace:
 | 
								case http.MethodTrace:
 | 
				
			||||||
				panic(`method Trace is not supported`)
 | 
									panic(`method Trace is not supported`)
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
 | 
				
			|||||||
@ -13,8 +13,28 @@ import (
 | 
				
			|||||||
	"github.com/gin-gonic/gin"
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type testCommon struct {
 | 
				
			||||||
 | 
						UserID uint `json:"user_id"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type testForm struct {
 | 
				
			||||||
 | 
						Meta `json:"-" method:"get" path:"test"`
 | 
				
			||||||
 | 
						testCommon
 | 
				
			||||||
 | 
						Name string `json:"name"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestNewServer(t *testing.T) {
 | 
					func TestNewServer(t *testing.T) {
 | 
				
			||||||
	s := NewServer(9087)
 | 
						s := NewServer(9087)
 | 
				
			||||||
	s.Router().GET("/ping", func(c *gin.Context) {})
 | 
						s.AddCommonParamRule("UserID", func(ctx *gin.Context) (any, error) {
 | 
				
			||||||
 | 
							return uint(123456), nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						s.Group("", nil, testController{})
 | 
				
			||||||
	s.Start()
 | 
						s.Start()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type testController struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (tc testController) Test(ctx *gin.Context, requestData *testForm) (*testCommon, error) {
 | 
				
			||||||
 | 
						return &testCommon{UserID: requestData.UserID}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user