Compare commits
3 Commits
master
...
13d1ab6607
Author | SHA1 | Date | |
---|---|---|---|
13d1ab6607 | |||
bb5d97f6eb | |||
ac5776f3f6 |
11
go.mod
11
go.mod
@ -1,12 +1,12 @@
|
||||
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
|
||||
@ -23,6 +23,7 @@ require (
|
||||
git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda // indirect
|
||||
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4 // indirect
|
||||
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 // indirect
|
||||
git.zhangdeman.cn/zhangdeman/trace v0.0.0-20231220041950-807f3d74a6fa // indirect
|
||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e // indirect
|
||||
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20241125101541-c5ea194c9c1e // indirect
|
||||
github.com/BurntSushi/toml v1.4.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
|
||||
|
8
go.sum
8
go.sum
@ -8,6 +8,8 @@ git.zhangdeman.cn/gateway/api-doc v0.0.0-20250220105101-71d6db967dc5 h1:UV2+nD9H
|
||||
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 +24,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=
|
||||
@ -95,6 +99,8 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
|
||||
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=
|
||||
@ -184,6 +190,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
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=
|
||||
|
194
request/context.go
Normal file
194
request/context.go
Normal file
@ -0,0 +1,194 @@
|
||||
// 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/wrapper"
|
||||
"github.com/gin-gonic/gin"
|
||||
"git.zhangdeman.cn/zhangdeman/trace"
|
||||
"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, "")
|
||||
return &Context{
|
||||
Context: ginContext,
|
||||
StartRequestTime: time.Now(),
|
||||
FinishRequestTime: time.Time(int64(0)),
|
||||
HandlerAfterResponse: make([]gin.HandlerFunc, 0),
|
||||
CustomData: make(map[string]any),
|
||||
lock: &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 // 开始请求时间(全局)
|
||||
FinishRequestTime time.Time // 结束请求时间(全局)
|
||||
TraceID string `json:"trace_id"` // 请求trace_id
|
||||
ParentAppName string `json:"parent_app_name"` // 父级应用名称
|
||||
HandlerAfterResponse []gin.HandlerFunc `json:"-"` // 响应数据之后需要执行的逻辑
|
||||
CustomData map[string]any // 业务上下文自定义数据, 可以合 ginCtx.Value 作区分
|
||||
lock *sync.RWMutex
|
||||
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.lock.Lock()
|
||||
defer ctx.lock.Unlock()
|
||||
if nil == ctx.CustomData {
|
||||
ctx.CustomData = make(map[string]any)
|
||||
}
|
||||
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.lock.RLock()
|
||||
defer ctx.lock.RUnlock()
|
||||
if val, exist := ctx.CustomData[key]; exist {
|
||||
return val
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// CustomDataExist 判断
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:04 2025/2/28
|
||||
func (ctx *Context) CustomDataExist(key string) any {
|
||||
ctx.lock.RLock()
|
||||
defer ctx.lock.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.lock.Lock()
|
||||
defer ctx.lock.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.lock.Lock()
|
||||
defer ctx.lock.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<白茶清欢>
|
||||
|
Reference in New Issue
Block a user