Compare commits
	
		
			5 Commits
		
	
	
		
			feature/up
			...
			feature/up
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| ab78127317 | |||
| 28da213bb8 | |||
| 13d1ab6607 | |||
| bb5d97f6eb | |||
| ac5776f3f6 | 
							
								
								
									
										12
									
								
								define/request.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								define/request.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| // Package define ... | ||||
| // | ||||
| // Description : define ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2025-03-10 14:38 | ||||
| package define | ||||
|  | ||||
| const ( | ||||
| 	GinWrapperContextKey = "GIN_WRAPPER_CONTEXT" | ||||
| ) | ||||
							
								
								
									
										13
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								go.mod
									
									
									
									
									
								
							| @ -1,17 +1,19 @@ | ||||
| module git.zhangdeman.cn/zhangdeman/gin | ||||
|  | ||||
| go 1.22.2 | ||||
| go 1.23.0 | ||||
|  | ||||
| toolchain go1.23.6 | ||||
| toolchain go1.24.0 | ||||
|  | ||||
| require ( | ||||
| 	git.zhangdeman.cn/gateway/api-doc v0.0.0-20250220105101-71d6db967dc5 | ||||
| 	git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250215141718-8232f587a6ea | ||||
| 	git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250227040546-863c03f34bb8 | ||||
| 	git.zhangdeman.cn/zhangdeman/exception v0.0.0-20250207091724-ca151fbc1f06 | ||||
| 	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/trace v0.0.0-20231220041950-807f3d74a6fa | ||||
| 	git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250124091620-c757e551a8c9 | ||||
| 	github.com/gin-contrib/pprof v1.5.2 | ||||
| 	github.com/gin-gonic/gin v1.10.0 | ||||
| 	github.com/go-playground/validator/v10 v10.25.0 | ||||
| 	github.com/mcuadros/go-defaults v1.2.0 | ||||
| @ -33,7 +35,6 @@ require ( | ||||
| 	github.com/cloudwego/base64x v0.1.5 // indirect | ||||
| 	github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 // indirect | ||||
| 	github.com/gabriel-vasile/mimetype v1.4.8 // indirect | ||||
| 	github.com/gin-contrib/pprof v1.5.2 // indirect | ||||
| 	github.com/gin-contrib/sse v1.0.0 // indirect | ||||
| 	github.com/go-ini/ini v1.67.0 // indirect | ||||
| 	github.com/go-openapi/jsonpointer v0.21.0 // indirect | ||||
| @ -47,7 +48,7 @@ require ( | ||||
| 	github.com/gorilla/websocket v1.5.3 // indirect | ||||
| 	github.com/josharian/intern v1.0.0 // indirect | ||||
| 	github.com/json-iterator/go v1.1.12 // indirect | ||||
| 	github.com/klauspost/cpuid/v2 v2.2.9 // indirect | ||||
| 	github.com/klauspost/cpuid/v2 v2.2.10 // indirect | ||||
| 	github.com/leodido/go-urn v1.4.0 // indirect | ||||
| 	github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect | ||||
| 	github.com/lestrrat-go/strftime v1.1.0 // indirect | ||||
| @ -71,7 +72,7 @@ require ( | ||||
| 	github.com/ugorji/go/codec v1.2.12 // indirect | ||||
| 	go.uber.org/multierr v1.11.0 // indirect | ||||
| 	golang.org/x/arch v0.14.0 // indirect | ||||
| 	golang.org/x/crypto v0.33.0 // indirect | ||||
| 	golang.org/x/crypto v0.35.0 // indirect | ||||
| 	golang.org/x/net v0.35.0 // indirect | ||||
| 	golang.org/x/sys v0.30.0 // indirect | ||||
| 	golang.org/x/text v0.22.0 // indirect | ||||
|  | ||||
							
								
								
									
										20
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								go.sum
									
									
									
									
									
								
							| @ -1,13 +1,7 @@ | ||||
| git.zhangdeman.cn/gateway/api-doc v0.0.0-20250219142545-bd7f6d2cfd99 h1:VYwbWsMcgQ7yWAGHB2v8Zbhh/5NIcQUq3yxay09zjkY= | ||||
| git.zhangdeman.cn/gateway/api-doc v0.0.0-20250219142545-bd7f6d2cfd99/go.mod h1:oNTwnepzW09RNfIQCpgmbiayTKLvGx2XP92esfkxv98= | ||||
| git.zhangdeman.cn/gateway/api-doc v0.0.0-20250220082250-6987b4829bf6 h1:C8otP/n4SPc8hQQxd9jOnPxb24l0KMhTNpxWtwz20js= | ||||
| git.zhangdeman.cn/gateway/api-doc v0.0.0-20250220082250-6987b4829bf6/go.mod h1:oNTwnepzW09RNfIQCpgmbiayTKLvGx2XP92esfkxv98= | ||||
| git.zhangdeman.cn/gateway/api-doc v0.0.0-20250220095851-22d937a4b1cb h1:E+KXP29m18dNfyVU8zBIBAEqE7aspLqFHa1bOnIMdq4= | ||||
| git.zhangdeman.cn/gateway/api-doc v0.0.0-20250220095851-22d937a4b1cb/go.mod h1:oNTwnepzW09RNfIQCpgmbiayTKLvGx2XP92esfkxv98= | ||||
| git.zhangdeman.cn/gateway/api-doc v0.0.0-20250220105101-71d6db967dc5 h1:UV2+nD9HQLbRt+vY98gwPtkd+M8fbfffl7nb4Mkymmc= | ||||
| git.zhangdeman.cn/gateway/api-doc v0.0.0-20250220105101-71d6db967dc5/go.mod h1:oNTwnepzW09RNfIQCpgmbiayTKLvGx2XP92esfkxv98= | ||||
| git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250215141718-8232f587a6ea h1:6b9bfq44ewsXGVOkyZ+DQ4dNaKtmNsdHOFQxHUdEQrY= | ||||
| git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250215141718-8232f587a6ea/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k= | ||||
| git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250227040546-863c03f34bb8 h1:VEifPc+vkpEQoX9rj7zxmT1m+IA81XjOxe7+Z1aqWNM= | ||||
| git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250227040546-863c03f34bb8/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k= | ||||
| 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/easymap v0.0.0-20241101082529-28a6c68e38a4 h1:s6d4b6yY+NaK1AzoBD1pxqsuygEHQz0Oie86c45geDw= | ||||
| @ -22,6 +16,8 @@ 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-20231220041950-807f3d74a6fa h1:2bZ9VmQF0pIZ+scnN3UuGoXjjKhccnwfIL779QGZArY= | ||||
| git.zhangdeman.cn/zhangdeman/trace v0.0.0-20231220041950-807f3d74a6fa/go.mod h1:Bta0kzamTWqBIcc6robGAl/iRuyCFbzy45VGbG8L+7Y= | ||||
| 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= | ||||
| @ -93,8 +89,8 @@ github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFF | ||||
| github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= | ||||
| github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= | ||||
| github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= | ||||
| github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY= | ||||
| github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8= | ||||
| github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= | ||||
| github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= | ||||
| github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= | ||||
| github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= | ||||
| github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= | ||||
| @ -182,8 +178,8 @@ golang.org/x/arch v0.14.0 h1:z9JUEZWr8x4rR0OU6c4/4t6E6jOZ8/QBS2bBYBm4tx4= | ||||
| golang.org/x/arch v0.14.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= | ||||
| golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||||
| golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | ||||
| golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= | ||||
| golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= | ||||
| golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= | ||||
| golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= | ||||
| golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= | ||||
| golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= | ||||
| golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= | ||||
|  | ||||
							
								
								
									
										200
									
								
								request/context.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								request/context.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,200 @@ | ||||
| // Package request ... | ||||
| // | ||||
| // Description : request ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2025-02-28 11:45 | ||||
| package request | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	networkUtil "git.zhangdeman.cn/zhangdeman/network/util" | ||||
| 	"git.zhangdeman.cn/zhangdeman/trace" | ||||
| 	"git.zhangdeman.cn/zhangdeman/wrapper" | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| // getTraceID 生成traceID | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 23:12 2022/6/25 | ||||
| func getTraceID(ctx *gin.Context) string { | ||||
| 	hostname, _ := os.Hostname() | ||||
| 	if hostname != "" { | ||||
| 		hostname = "unknown" | ||||
| 	} | ||||
| 	return fmt.Sprintf( | ||||
| 		"%v-%v-%v-%v-%v", | ||||
| 		time.Now().UnixNano()/1e6, | ||||
| 		strings.ReplaceAll(networkUtil.IP.GetHostIP(), ".", ""), | ||||
| 		strings.ReplaceAll(hostname, ".", ""), | ||||
| 		strings.ReplaceAll(networkUtil.IP.GetRemoteIP(ctx.Request), ".", ""), | ||||
| 		wrapper.StringFromRandom(32, "").Md5().Value, | ||||
| 	) | ||||
| } | ||||
|  | ||||
| // getRequestID 生成requestID | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 23:12 2022/6/25 | ||||
| func getRequestID(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 getTraceID(ctx) | ||||
| } | ||||
|  | ||||
| // NewContext 获取context实例 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 12:01 2025/2/28 | ||||
| func NewContext(ginContext *gin.Context) *Context { | ||||
| 	// 生成traceID | ||||
| 	traceID := getRequestID(ginContext, "") | ||||
| 	hostname, _ := os.Hostname() | ||||
| 	return &Context{ | ||||
| 		Context:              ginContext, | ||||
| 		StartRequestTime:     time.Now(), | ||||
| 		FinishRequestTime:    time.Unix(0, 0), | ||||
| 		HandlerAfterResponse: make([]gin.HandlerFunc, 0), | ||||
| 		customData:           make(map[string]any), | ||||
| 		Hostname:             hostname, | ||||
| 		HostIp:               networkUtil.IP.GetHostIP(), | ||||
| 		customLock:           &sync.RWMutex{}, | ||||
| 		TraceID:              traceID, | ||||
| 		Trace:                trace.NewRuntime(traceID, 0), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Context 请求上下文信息, 对 ctx *gin.Context的二次包装 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 11:45 2025/2/28 | ||||
| type Context struct { | ||||
| 	*gin.Context         `json:"-"` | ||||
| 	StartRequestTime     time.Time         `json:"start_request_time"`  // 开始请求时间(全局) | ||||
| 	FinishRequestTime    time.Time         `json:"finish_request_time"` // 结束请求时间(全局) | ||||
| 	TraceID              string            `json:"trace_id"`            // 请求trace_id | ||||
| 	ParentAppName        string            `json:"parent_app_name"`     // 父级应用名称 | ||||
| 	HandlerAfterResponse []gin.HandlerFunc `json:"-"`                   // 响应数据之后需要执行的逻辑 | ||||
| 	Hostname             string            `json:"hostname"`            // 服务器名称 | ||||
| 	HostIp               string            `json:"host_ip"`             // 服务器IP | ||||
| 	customData           map[string]any    `json:"-"`                   // 业务上下文自定义数据, 可以合 ginCtx.Value 作区分 | ||||
| 	customLock           *sync.RWMutex     `json:"-"`                   // 数据锁 | ||||
| 	Trace                *trace.Runtime    `json:"-"`                   // 追踪实例 | ||||
| } | ||||
|  | ||||
| // SetCustom 设置数据 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 11:58 2025/2/28 | ||||
| func (ctx *Context) SetCustom(key string, val any) { | ||||
| 	ctx.customLock.Lock() | ||||
| 	defer ctx.customLock.Unlock() | ||||
| 	if nil == ctx.customData { | ||||
| 		ctx.customData = make(map[string]any) | ||||
| 	} | ||||
| 	ctx.Set(key, val) | ||||
| 	ctx.customData[key] = val | ||||
| } | ||||
|  | ||||
| // customDataValue 获取customData | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 12:03 2025/2/28 | ||||
| func (ctx *Context) customDataValue(key string) any { | ||||
| 	ctx.customLock.RLock() | ||||
| 	defer ctx.customLock.RUnlock() | ||||
| 	if val, exist := ctx.customData[key]; exist { | ||||
| 		return val | ||||
| 	} else { | ||||
| 		return ctx.Value(key) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // customDataExist 判断 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 12:04 2025/2/28 | ||||
| func (ctx *Context) customDataExist(key string) any { | ||||
| 	ctx.customLock.RLock() | ||||
| 	defer ctx.customLock.RUnlock() | ||||
| 	_, exist := ctx.customData[key] | ||||
| 	return exist | ||||
| } | ||||
|  | ||||
| // customDataAppend 向数组数据中追加元素 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 12:07 2025/2/28 | ||||
| func (ctx *Context) customDataAppend(key string, appendValue any) { | ||||
| 	ctx.customLock.Lock() | ||||
| 	defer ctx.customLock.Unlock() | ||||
| 	val, exist := ctx.customData[key] | ||||
| 	if !exist || nil == val { | ||||
| 		ctx.customData[key] = []any{appendValue} | ||||
| 		return | ||||
| 	} | ||||
| 	if valArr, ok := val.([]any); ok { | ||||
| 		valArr = append(valArr, appendValue) | ||||
| 		ctx.customData[key] = valArr | ||||
| 	} | ||||
| 	// 非数组, 忽略追加行为 | ||||
| } | ||||
|  | ||||
| // customDataAppendProperty 向一个map中追加/更新属性 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 12:11 2025/2/28 | ||||
| func (ctx *Context) customDataAppendProperty(key string, appendKey string, appendValue any) { | ||||
| 	ctx.customLock.Lock() | ||||
| 	defer ctx.customLock.Unlock() | ||||
| 	val, exist := ctx.customData[key] | ||||
| 	if !exist || nil == val { | ||||
| 		ctx.customData[key] = map[string]any{ | ||||
| 			appendKey: appendValue, | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 	if valMap, ok := val.(map[string]any); ok { | ||||
| 		valMap[appendKey] = appendValue | ||||
| 		ctx.customData[key] = valMap | ||||
| 	} | ||||
| 	// 非map, 忽略追加行为 | ||||
| } | ||||
|  | ||||
| // TraceStart 开始监控 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 12:24 2025/2/28 | ||||
| func (ctx *Context) TraceStart(action string, actionData map[string]any) int { | ||||
| 	return ctx.Trace.StartBehavior(action, actionData) | ||||
| } | ||||
|  | ||||
| // TraceEnd 完成监控 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 12:24 2025/2/28 | ||||
| func (ctx *Context) TraceEnd(behaviorID int, endData map[string]any) { | ||||
| 	ctx.Trace.FinishBehavior(behaviorID, endData) | ||||
| } | ||||
| @ -117,8 +117,8 @@ func (wh *wrapperHandle) GetContentType(ctx *gin.Context, defaultVal string) str | ||||
| 	if nil == ctx { | ||||
| 		return defaultVal | ||||
| 	} | ||||
| 	contentType := strings.ToLower(ctx.ContentType()) | ||||
| 	return wrapper.TernaryOperator.String(len(contentType) > 0, wrapper.String(contentType), wrapper.String(defaultVal)).Value() | ||||
| 	contentTypeVal := strings.ToLower(ctx.ContentType()) | ||||
| 	return wrapper.TernaryOperator.String(len(contentTypeVal) > 0, wrapper.String(contentTypeVal), wrapper.String(defaultVal)).Value() | ||||
| } | ||||
|  | ||||
| // GetDomain 获取请求Domain | ||||
| @ -271,6 +271,40 @@ func (wh *wrapperHandle) ParseCookie(ctx *gin.Context) map[string]string { | ||||
| 	return cookieData | ||||
| } | ||||
|  | ||||
| // Copy 复制context | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 11:00 2025/2/28 | ||||
| // | ||||
| // - ctx *gin.Context : 基于哪一个context复制context | ||||
| // - isCopyContextValue bool : 是否继承父级ctx的自定义value | ||||
| func (wh *wrapperHandle) Copy(ctx *gin.Context, isCopyContextValue bool, excludeKeyList []string) *gin.Context { | ||||
| 	if nil == ctx { | ||||
| 		return nil | ||||
| 	} | ||||
| 	newContext := ctx.Copy() | ||||
| 	excludeKeyTable := map[string]bool{} | ||||
| 	for _, excludeKey := range excludeKeyList { | ||||
| 		excludeKeyTable[excludeKey] = true | ||||
| 	} | ||||
| 	if isCopyContextValue { | ||||
| 		// 上下文设置的业务数据值也继承下来, TODO: 并发读写此处可能panic | ||||
| 		for k, v := range newContext.Keys { | ||||
| 			if !excludeKeyTable[k] { | ||||
| 				// 没有指定不继承 | ||||
| 				ctx.Set(k, v) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	// 设置父级context | ||||
| 	ctx.Set("parent_context", ctx) | ||||
| 	if nil == ctx.Value("root_context") { | ||||
| 		ctx.Set("root_context", ctx) | ||||
| 	} | ||||
| 	return newContext | ||||
| } | ||||
|  | ||||
| // GetLogicAfterResponse ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| @ -292,3 +326,21 @@ func (wh *wrapperHandle) GetLogicAfterResponse(ctx *gin.Context) *define.LogicAf | ||||
| 	// 就这么写, key值如果被其他人覆盖成非法值, 此处会直接panic | ||||
| 	return l.(*define.LogicAfterResponse) | ||||
| } | ||||
|  | ||||
| // GetGinWrapperContext 获取包装之后context | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 14:41 2025/3/10 | ||||
| func (wh *wrapperHandle) GetGinWrapperContext(ctx *gin.Context) *Context { | ||||
| 	if nil == ctx { | ||||
| 		return nil | ||||
| 	} | ||||
| 	if val, exist := ctx.Get(define.GinWrapperContextKey); !exist || nil == val { | ||||
| 		newCtx := NewContext(ctx) | ||||
| 		newCtx.SetCustom(define.GinWrapperContextKey, newCtx) | ||||
| 		return newCtx | ||||
| 	} else { | ||||
| 		return val.(*Context) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -70,7 +70,8 @@ func (c controller) methodConfig(reflectMethod reflect.Method) (cfg UriConfig, n | ||||
| 		return | ||||
| 	} | ||||
| 	// 第一个参数必须是 *gin.Context | ||||
| 	if methodType.In(1).String() != GinContextType { | ||||
| 	firstParamStr := methodType.In(1).String() | ||||
| 	if firstParamStr != GinContextType && firstParamStr != GinWrapperContextType { | ||||
| 		needRegister = false | ||||
| 		return | ||||
| 	} | ||||
| @ -105,6 +106,8 @@ func (c controller) methodConfig(reflectMethod reflect.Method) (cfg UriConfig, n | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	// 是否gin包装后的context | ||||
| 	cfg.IsGinWrapperContext = firstParamStr == GinWrapperContextType | ||||
| 	// 解析meta信息 | ||||
| 	cfg.Path = metaField.Tag.Get(TagNamePath) | ||||
| 	cfg.RequestMethod = metaField.Tag.Get(TagNameMethod) | ||||
|  | ||||
| @ -15,6 +15,7 @@ const ( | ||||
| 	PrefixFuncName         = "RouterPrefix"     // 路由前缀函数名称 | ||||
| 	MiddlewareFuncName     = "RouterMiddleware" // 路由中间件函数名称 | ||||
| 	GinContextType         = "*gin.Context"     // gin context 类型名称 | ||||
| 	GinWrapperContextType  = "*request.Context" // gin context 类型名称 | ||||
| 	ErrorType              = "error"            // error类型 | ||||
| 	ErrorInterfaceFuncName = "Error"            // error接口需要实现的方法名称 | ||||
| ) | ||||
| @ -36,15 +37,16 @@ const ( | ||||
| // | ||||
| // Date : 15:41 2024/7/21 | ||||
| type UriConfig struct { | ||||
| 	Path           string         `json:"path"`           // 接口路由, 必须配置 | ||||
| 	RequestMethod  string         `json:"request_method"` // 接口请求方法, 必须配置 | ||||
| 	TagList        []string       `json:"tag_list"`       // 接口分组 | ||||
| 	Desc           string         `json:"desc"`           // 接口描述 | ||||
| 	OutputStrict   bool           `json:"output_strict"`  // 接口是否为严格模式 : 不配置,可返回任意类型, 配置, 必须返回结构体或者map | ||||
| 	FormDataType   reflect.Type   `json:"-"`              // 表单数据类型 | ||||
| 	ResultDataType reflect.Type   `json:"-"`              // 返回值数据类型 | ||||
| 	ApiStructValue reflect.Value  `json:"-"`              // 逻辑函数所属结构体取值 | ||||
| 	ApiLogicFunc   reflect.Method `json:"-"`              // 自定义的接口逻辑 | ||||
| 	Path                string         `json:"path"`                   // 接口路由, 必须配置 | ||||
| 	RequestMethod       string         `json:"request_method"`         // 接口请求方法, 必须配置 | ||||
| 	TagList             []string       `json:"tag_list"`               // 接口分组 | ||||
| 	Desc                string         `json:"desc"`                   // 接口描述 | ||||
| 	OutputStrict        bool           `json:"output_strict"`          // 接口是否为严格模式 : 不配置,可返回任意类型, 配置, 必须返回结构体或者map | ||||
| 	FormDataType        reflect.Type   `json:"-"`                      // 表单数据类型 | ||||
| 	ResultDataType      reflect.Type   `json:"-"`                      // 返回值数据类型 | ||||
| 	ApiStructValue      reflect.Value  `json:"-"`                      // 逻辑函数所属结构体取值 | ||||
| 	ApiLogicFunc        reflect.Method `json:"-"`                      // 自定义的接口逻辑 | ||||
| 	IsGinWrapperContext bool           `json:"is_gin_wrapper_context"` // 是否gin包装后的context | ||||
| } | ||||
|  | ||||
| // UriParam 接口参数配置 | ||||
|  | ||||
| @ -79,7 +79,14 @@ 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}) | ||||
| 		ginWrapperContext := request.NewContext(ctx) | ||||
| 		// wrapper context 设置到 gin context | ||||
| 		ginWrapperContext.Set(define.GinWrapperContextKey, ginWrapperContext) | ||||
| 		ctxReflect := reflect.ValueOf(ctx) | ||||
| 		if uriCfg.IsGinWrapperContext { | ||||
| 			ctxReflect = reflect.ValueOf(ginWrapperContext) | ||||
| 		} | ||||
| 		resList := uriCfg.ApiLogicFunc.Func.Call([]reflect.Value{uriCfg.ApiStructValue, ctxReflect, inputValue}) | ||||
| 		if resList[1].IsNil() { | ||||
| 			// 请求成功 | ||||
| 			isSuccess = true | ||||
|  | ||||
| @ -109,8 +109,9 @@ func parseUriConfig(methodType reflect.Type, routerPrefix string) (*UriConfig, e | ||||
| 	} | ||||
| 	// 接口logic共计两个参数. 两个返回值, 格式 : func(ctx *gin.Context, formData any[组合Meta]) (any[response], error) | ||||
|  | ||||
| 	// 解析第一个参数是 *gin.Context | ||||
| 	if methodType.In(1).String() != "*gin.Context" { | ||||
| 	// 解析第一个参数是 *gin.Context / 或者包装后的 request.Context | ||||
| 	firstParamStr := methodType.In(1).String() | ||||
| 	if firstParamStr != "*gin.Context" && firstParamStr != "*request.Context" { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 	// 解析第二个参数是组合Meta的form表单 | ||||
|  | ||||
| @ -8,14 +8,13 @@ | ||||
| package router | ||||
|  | ||||
| import ( | ||||
| 	"git.zhangdeman.cn/zhangdeman/gin/request" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
|  | ||||
| type TestController struct{} | ||||
|  | ||||
| func (t TestController) Logic(ctx *gin.Context, formData *TestForm) (TestOut, error) { | ||||
| func (t TestController) Logic(ctx *request.Context, formData *TestForm) (TestOut, error) { | ||||
| 	return TestOut{ | ||||
| 		FormData: formData, | ||||
| 	}, nil | ||||
|  | ||||
		Reference in New Issue
	
	Block a user