提交 ce21a10a authored 作者: mooncake9527's avatar mooncake9527

v1.0.59

上级 eeaf1350
...@@ -58,7 +58,7 @@ func (a *App) Run() { ...@@ -58,7 +58,7 @@ func (a *App) Run() {
return a.watch(ctx) return a.watch(ctx)
}) })
fmt.Println(buff) fmt.Println(LOGO1)
if err := eg.Wait(); err != nil { if err := eg.Wait(); err != nil {
panic(err) panic(err)
...@@ -129,3 +129,81 @@ const ( ...@@ -129,3 +129,81 @@ const (
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
` `
) )
const (
LOGO = `
¶ ¶
¶ ¶
¶ ¶ ¶ ¶
¶ ¶¶ ¶¶ ¶
¶¶ ¶¶¶ ¶¶¶ ¶¶
¶ ¶¶ ¶¶¶ ¶¶¶ ¶¶ ¶
¶¶ ¶¶ ¶¶¶ ¶¶¶ ¶¶ ¶¶
¶¶ ¶¶ ¶¶¶¶ ¶¶¶¶ ¶¶ ¶¶
¶¶ ¶¶¶ ¶¶¶¶ ¶¶¶¶¶ ¶¶¶ ¶¶¶
¶ ¶¶¶ ¶¶¶¶ ¶¶¶¶ ¶¶¶¶ ¶¶¶¶ ¶¶¶¶ ¶
¶¶ ¶¶¶¶¶ ¶¶¶¶ ¶¶¶¶¶ ¶¶¶¶¶ ¶¶¶¶ ¶¶¶¶¶ ¶¶
¶¶ ¶¶¶¶¶ ¶¶¶¶¶¶¶¶¶¶¶ ¶¶¶¶¶¶¶¶¶¶¶ ¶¶¶¶¶ ¶
¶¶ ¶¶¶¶¶ ¶¶¶¶¶¶¶¶¶¶¶ ¶¶¶¶¶¶¶¶¶¶¶ ¶¶¶¶¶ ¶¶
¶¶¶ ¶¶¶¶ ¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶ ¶¶¶¶ ¶¶¶
¶¶¶¶ ¶¶¶¶ ¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶ ¶¶¶¶ ¶¶¶¶
¶¶¶¶ ¶¶¶¶¶ ¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶ ¶¶¶¶¶ ¶¶¶¶
¶¶¶¶ ¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶ ¶¶¶¶
¶¶¶¶¶ ¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶ ¶¶¶¶
¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶
¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶
¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶
¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶
¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶
¶¶¶¶¶ ¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶ ¶¶¶¶¶
¶¶¶¶¶¶ ¶¶¶¶¶¶¶¶¶¶¶¶¶ ¶¶¶¶¶¶
¶¶¶¶¶¶¶ .. ¶¶¶¶¶¶¶¶¶ .. ¶¶¶¶¶¶¶
¶¶¶¶¶¶¶¶ ¶¶¶¶¶ ¶¶¶¶¶¶¶¶
¶¶¶¶¶¶¶¶¶¶ ¶¶¶ ¶¶¶¶¶¶¶¶¶¶
¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶
¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶ ¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶
¶¶¶¶¶¶¶¶¶¶ ¶¶¶¶¶¶¶¶¶¶
¶¶¶¶¶¶¶¶ ¶¶¶¶¶¶¶¶
¶¶¶¶¶¶¶¶¶ ¶¶¶¶¶¶¶¶¶
¶¶¶¶¶¶¶¶¶ ¶¶¶¶¶ ¶¶¶¶¶¶¶¶¶
¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶
¶¶¶ ¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶ ¶¶¶
¶¶ ¶¶¶¶ ¶¶¶¶¶ ¶¶¶¶ ¶¶
`
)
const (
LOGO1 = `
▐▒▒░▄
▒▒▒▒▒▒▒▒▄
▐▒▒▒▒▒▒▒▒▒▒▒▄ ▄▄▒▒
▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▄ ▄▄▒▒▒▒▒▒▒▒
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▄ ▄▒▒▒▒▒▒▒▒▒▒▒▒▒▌
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▄ ▄▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▄░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░
▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▄ ▄▄▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▄▄▄▄▄░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▀▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▀
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▀▒▒▒░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▀
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▒▒▒▒▀
▄▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▒▒▒▒▒▒▒▒▒▒░▄▄▄ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▄▄▄ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▒▒▒▒▒▒▒▒▒▒▒ ▀█▀ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▐██▀ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒░
▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▐▒▒▒▒▒▒▒▒▒▒▒▒▒▄ ▄▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▄ ▄▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▀▀▀▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▄▄ ▄▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▒▒░░░░░░░░▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░░░░▒▒▒▒▒▒▒▒
▐▒░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░░░░░░░▐▒▒▒▒▒▒
▒▒░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▀░░░░▄░░░▀▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░░░░░░░▐▒▒▒▒▒▒▒
▐▒▒░░░░░░░▄░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░░░░░░▒▒▒▒▒▒▒▒
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒░▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░░▒▒▒▒▒▒▒▒▒▒▒▒
▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒░▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▄░▀▒▒▒▒▀░▄▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
`
)
...@@ -21,7 +21,6 @@ func Parse(configFile string, obj interface{}, reloads ...func()) error { ...@@ -21,7 +21,6 @@ func Parse(configFile string, obj interface{}, reloads ...func()) error {
if err != nil { if err != nil {
return err return err
} }
filePathStr, filename := filepath.Split(confFileAbs) filePathStr, filename := filepath.Split(confFileAbs)
ext := strings.TrimLeft(path.Ext(filename), ".") ext := strings.TrimLeft(path.Ext(filename), ".")
filename = strings.ReplaceAll(filename, "."+ext, "") // excluding suffix names filename = strings.ReplaceAll(filename, "."+ext, "") // excluding suffix names
......
...@@ -14,47 +14,41 @@ import ( ...@@ -14,47 +14,41 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
type CtxKey string
func (x CtxKey) String() string {
return string(x)
}
const ( const (
GinContextKey CtxKey = "ginContext" GinContextKey = "ginContext"
HeaderXTimestampKey CtxKey = "Timestamp" HeaderXTimestampKey = "Timestamp"
KeyReqBody CtxKey = "reqBody" KeyReqBody = "reqBody"
KeyRspBody CtxKey = "rspBody" KeyRspBody = "rspBody"
KeyRspCode CtxKey = "rspCode" KeyRspCode = "rspCode"
KeyOApiReqBody CtxKey = "oApiReqBody%s" KeyOApiReqBody = "oApiReqBody%s"
KeyOApiRspBody CtxKey = "oApiRspBody%s" KeyOApiRspBody = "oApiRspBody%s"
KeyAppName CtxKey = "appName" KeyAppName = "appName"
KeyUser CtxKey = "user" KeyUser = "user"
KeyApiStartTime CtxKey = "apiStartTime" KeyApiStartTime = "apiStartTime"
KeyClientIP CtxKey = "clientIP" KeyClientIP = "clientIP"
KeyUID CtxKey = "uid" KeyUID = "uid"
KeyUType CtxKey = "uType" KeyUType = "uType"
KeyCompanyID CtxKey = "companyID" KeyCompanyID = "companyID"
KeyShopID CtxKey = "shopID" KeyShopID = "shopID"
KeyUName CtxKey = "uname" KeyUName = "uname"
KeyToken CtxKey = "token" KeyToken = "token"
KeyCost CtxKey = "X-Request-Cost" KeyCost = "X-Request-Cost"
KeyRspBodyMax CtxKey = "rsp-body-max" KeyRspBodyMax = "rsp-body-max"
) )
var ( var (
HeaderXRequestIDKey CtxKey = "X-Request-ID" HeaderXRequestIDKey = "X-Request-ID"
ContextTraceIDKey CtxKey = "X-Request-ID" ContextTraceIDKey = "X-Request-ID"
) )
var ( var (
ErrorGinContextNotFound = errors.New("gin context not found") ErrorGinContextNotFound = errors.New("gin context not found")
) )
func Set(c *gin.Context, key CtxKey, val any) { func Set(c *gin.Context, key string, val any) {
c.Set(key.String(), val) c.Set(key, val)
} }
func SetRspBodyMax(ctx context.Context, max int) { func SetRspBodyMax(ctx context.Context, max int) {
...@@ -63,8 +57,8 @@ func SetRspBodyMax(ctx context.Context, max int) { ...@@ -63,8 +57,8 @@ func SetRspBodyMax(ctx context.Context, max int) {
} }
} }
func Get[T any](c *gin.Context, key CtxKey) (T, bool) { func Get[T any](c *gin.Context, key string) (T, bool) {
if val, ok := c.Get(key.String()); ok { if val, ok := c.Get(key); ok {
if v, ok1 := val.(T); ok1 { if v, ok1 := val.(T); ok1 {
return v, true return v, true
} }
...@@ -75,7 +69,7 @@ func Get[T any](c *gin.Context, key CtxKey) (T, bool) { ...@@ -75,7 +69,7 @@ func Get[T any](c *gin.Context, key CtxKey) (T, bool) {
// GetGinCtxTraceID get request id from gin.Context // GetGinCtxTraceID get request id from gin.Context
func GetGinCtxTraceID(c *gin.Context) string { func GetGinCtxTraceID(c *gin.Context) string {
if v, isExist := c.Get(ContextTraceIDKey.String()); isExist { if v, isExist := c.Get(ContextTraceIDKey); isExist {
if requestID, ok := v.(string); ok { if requestID, ok := v.(string); ok {
return requestID return requestID
} }
...@@ -85,7 +79,7 @@ func GetGinCtxTraceID(c *gin.Context) string { ...@@ -85,7 +79,7 @@ func GetGinCtxTraceID(c *gin.Context) string {
// GinTraceIDField get request id field from gin.Context // GinTraceIDField get request id field from gin.Context
func GinTraceIDField(c *gin.Context) zap.Field { func GinTraceIDField(c *gin.Context) zap.Field {
return zap.String(ContextTraceIDKey.String(), GetGinCtxTraceID(c)) return zap.String(ContextTraceIDKey, GetGinCtxTraceID(c))
} }
// CtxRequestID get request id from context.Context // CtxRequestID get request id from context.Context
...@@ -115,23 +109,27 @@ func CtxGetGinCtx(c context.Context) *gin.Context { ...@@ -115,23 +109,27 @@ func CtxGetGinCtx(c context.Context) *gin.Context {
// CtxTraceIDField get request id field from context.Context // CtxTraceIDField get request id field from context.Context
func CtxTraceIDField(c context.Context) zap.Field { func CtxTraceIDField(c context.Context) zap.Field {
return zap.String(ContextTraceIDKey.String(), CtxRequestID(c)) return zap.String(ContextTraceIDKey, CtxRequestID(c))
}
func NewCtx() context.Context {
return context.WithValue(context.Background(), ContextTraceIDKey, GenerateTid())
} }
func GetGinUserID(c *gin.Context) xsf.ID { func GetGinUserID(c *gin.Context) xsf.ID {
return getGinVal[xsf.ID](c, KeyUID.String()) return getGinVal[xsf.ID](c, KeyUID)
} }
func GetGinShopID(c *gin.Context) xsf.ID { func GetGinShopID(c *gin.Context) xsf.ID {
return getGinVal[xsf.ID](c, KeyShopID.String()) return getGinVal[xsf.ID](c, KeyShopID)
} }
func GetCtxUserID(c context.Context) xsf.ID { func GetCtxUserID(c context.Context) xsf.ID {
return getCtxVal[xsf.ID](c, KeyUID.String()) return getCtxVal[xsf.ID](c, KeyUID)
} }
func GetCtxShopID(c context.Context) xsf.ID { func GetCtxShopID(c context.Context) xsf.ID {
return getCtxVal[xsf.ID](c, KeyShopID.String()) return getCtxVal[xsf.ID](c, KeyShopID)
} }
func GetCtxString(c context.Context, key string) string { func GetCtxString(c context.Context, key string) string {
val := c.Value(key) val := c.Value(key)
...@@ -150,10 +148,10 @@ func GetCtxUserToken(c context.Context) string { ...@@ -150,10 +148,10 @@ func GetCtxUserToken(c context.Context) string {
} }
func GetGinCtxTid(c *gin.Context) string { func GetGinCtxTid(c *gin.Context) string {
tid := c.GetString(ContextTraceIDKey.String()) tid := c.GetString(ContextTraceIDKey)
if tid == "" { if tid == "" {
tid = GenerateTid() tid = GenerateTid()
c.Set(ContextTraceIDKey.String(), tid) c.Set(ContextTraceIDKey, tid)
} }
return tid return tid
} }
...@@ -189,9 +187,9 @@ func GetClientIP(ctx context.Context) string { ...@@ -189,9 +187,9 @@ func GetClientIP(ctx context.Context) string {
} }
func WrapCtx(c *gin.Context) context.Context { func WrapCtx(c *gin.Context) context.Context {
ctx := context.WithValue(c.Request.Context(), ContextTraceIDKey, c.GetString(ContextTraceIDKey.String())) //nolint ctx := context.WithValue(c.Request.Context(), ContextTraceIDKey, c.GetString(ContextTraceIDKey))
for k, v := range c.Keys { for k, v := range c.Keys {
ctx = context.WithValue(ctx, k, v) //nolint ctx = context.WithValue(ctx, k, v)
} }
ctx = context.WithValue(ctx, GinContextKey, c) //nolint ctx = context.WithValue(ctx, GinContextKey, c) //nolint
return ctx return ctx
...@@ -212,15 +210,15 @@ func GetGinCtx(ctx context.Context) (*gin.Context, error) { ...@@ -212,15 +210,15 @@ func GetGinCtx(ctx context.Context) (*gin.Context, error) {
} }
func GetCtxUID(c context.Context) uint { func GetCtxUID(c context.Context) uint {
return getCtxVal[uint](c, KeyUID.String()) return getCtxVal[uint](c, KeyUID)
} }
func GetCtxUType(c context.Context) uint { func GetCtxUType(c context.Context) uint {
return getCtxVal[uint](c, KeyUType.String()) return getCtxVal[uint](c, KeyUType)
} }
func GetCtxCompanyID(c context.Context) uint { func GetCtxCompanyID(c context.Context) uint {
return getCtxVal[uint](c, KeyCompanyID.String()) return getCtxVal[uint](c, KeyCompanyID)
} }
func getGinVal[T any](c *gin.Context, key string) T { func getGinVal[T any](c *gin.Context, key string) T {
...@@ -246,7 +244,7 @@ func getCtxVal[T any](c context.Context, key string) T { ...@@ -246,7 +244,7 @@ func getCtxVal[T any](c context.Context, key string) T {
} }
func GetGinReq(c *gin.Context) []byte { func GetGinReq(c *gin.Context) []byte {
v, ok1 := c.Get(KeyReqBody.String()) v, ok1 := c.Get(KeyReqBody)
if ok1 { if ok1 {
ret, ok2 := v.([]byte) ret, ok2 := v.([]byte)
if ok2 { if ok2 {
...@@ -257,7 +255,7 @@ func GetGinReq(c *gin.Context) []byte { ...@@ -257,7 +255,7 @@ func GetGinReq(c *gin.Context) []byte {
} }
func GetGinRsp(c *gin.Context) []byte { func GetGinRsp(c *gin.Context) []byte {
v, ok1 := c.Get(KeyRspBody.String()) v, ok1 := c.Get(KeyRspBody)
if ok1 { if ok1 {
ret, ok2 := v.([]byte) ret, ok2 := v.([]byte)
if ok2 { if ok2 {
...@@ -275,14 +273,14 @@ func SetVal(ctx context.Context, key string, val interface{}) context.Context { ...@@ -275,14 +273,14 @@ func SetVal(ctx context.Context, key string, val interface{}) context.Context {
} }
func AddApiCost(c *gin.Context, appName string, start time.Time) { func AddApiCost(c *gin.Context, appName string, start time.Time) {
cost := c.Writer.Header().Get(KeyCost.String()) cost := c.Writer.Header().Get(KeyCost)
currentCost := fmt.Sprintf("%s:%s", appName, formatDuration(time.Since(start))) currentCost := fmt.Sprintf("%s:%s", appName, formatDuration(time.Since(start)))
if cost == "" { if cost == "" {
cost = currentCost cost = currentCost
} else { } else {
cost = fmt.Sprintf("%s,%s", currentCost, cost) cost = fmt.Sprintf("%s,%s", currentCost, cost)
} }
c.Writer.Header().Set(KeyCost.String(), cost) c.Writer.Header().Set(KeyCost, cost)
} }
func formatDuration(d time.Duration) string { func formatDuration(d time.Duration) string {
...@@ -294,12 +292,12 @@ func SetApiCost(ctx context.Context, header map[string][]string) { ...@@ -294,12 +292,12 @@ func SetApiCost(ctx context.Context, header map[string][]string) {
if ginCtx, _ := GetGinCtx(ctx); ginCtx != nil && len(header) > 0 { if ginCtx, _ := GetGinCtx(ctx); ginCtx != nil && len(header) > 0 {
cost := "" cost := ""
for k, v := range header { for k, v := range header {
if k == KeyCost.String() { if k == KeyCost {
cost = strings.Join(v, ",") cost = strings.Join(v, ",")
} }
} }
if cost != "" { if cost != "" {
ginCtx.Writer.Header().Set(KeyCost.String(), cost) ginCtx.Writer.Header().Set(KeyCost, cost)
} }
} }
} }
...@@ -102,8 +102,8 @@ func Auth(opts ...JwtOption) gin.HandlerFunc { ...@@ -102,8 +102,8 @@ func Auth(opts ...JwtOption) gin.HandlerFunc {
} }
} else { } else {
xsfID, _ := xsf.ParseString(claims.UID) xsfID, _ := xsf.ParseString(claims.UID)
c.Set(ctxUtils.KeyUID.String(), xsfID) c.Set(ctxUtils.KeyUID, xsfID)
c.Set(ctxUtils.KeyUName.String(), claims.Name) c.Set(ctxUtils.KeyUName, claims.Name)
} }
c.Next() c.Next()
......
...@@ -205,19 +205,19 @@ func Logging(opts ...Option) gin.HandlerFunc { ...@@ -205,19 +205,19 @@ func Logging(opts ...Option) gin.HandlerFunc {
entity.SetCopyReq(c, buf) entity.SetCopyReq(c, buf)
c.Set(ctxUtils.KeyAppName.String(), o.appName) c.Set(ctxUtils.KeyAppName, o.appName)
reqID := "" reqID := ""
if o.traceIDFrom == 1 { if o.traceIDFrom == 1 {
if v, isExist := c.Get(ctxUtils.ContextTraceIDKey.String()); isExist { if v, isExist := c.Get(ctxUtils.ContextTraceIDKey); isExist {
if requestID, ok := v.(string); ok { if requestID, ok := v.(string); ok {
reqID = requestID reqID = requestID
fields = append(fields, zap.String(ctxUtils.ContextTraceIDKey.String(), reqID)) fields = append(fields, zap.String(ctxUtils.ContextTraceIDKey, reqID))
} }
} }
} else if o.traceIDFrom == 2 { } else if o.traceIDFrom == 2 {
reqID = c.Request.Header.Get(ctxUtils.HeaderXRequestIDKey.String()) reqID = c.Request.Header.Get(ctxUtils.HeaderXRequestIDKey)
fields = append(fields, zap.String(ctxUtils.ContextTraceIDKey.String(), reqID)) fields = append(fields, zap.String(ctxUtils.ContextTraceIDKey, reqID))
} }
o.log.Info("<<<<<<<<<req", fields...) o.log.Info("<<<<<<<<<req", fields...)
...@@ -228,12 +228,12 @@ func Logging(opts ...Option) gin.HandlerFunc { ...@@ -228,12 +228,12 @@ func Logging(opts ...Option) gin.HandlerFunc {
c.Writer = newWriter c.Writer = newWriter
ip := ips.GetClientIP(c) ip := ips.GetClientIP(c)
c.Set(ctxUtils.KeyClientIP.String(), ip) c.Set(ctxUtils.KeyClientIP, ip)
// processing requests // processing requests
c.Next() c.Next()
rspBodyMax := c.GetInt(ctxUtils.KeyRspBodyMax.String()) rspBodyMax := c.GetInt(ctxUtils.KeyRspBodyMax)
contentType := c.Writer.Header().Get("Content-Type") contentType := c.Writer.Header().Get("Content-Type")
isMedia := false isMedia := false
if strings.Contains(contentType, "image") { if strings.Contains(contentType, "image") {
...@@ -259,7 +259,7 @@ func Logging(opts ...Option) gin.HandlerFunc { ...@@ -259,7 +259,7 @@ func Logging(opts ...Option) gin.HandlerFunc {
} }
} }
if reqID != "" { if reqID != "" {
fields = append(fields, zap.String(ctxUtils.ContextTraceIDKey.String(), reqID)) fields = append(fields, zap.String(ctxUtils.ContextTraceIDKey, reqID))
} }
o.log.Info(">>>>>>>>>rsp", fields...) o.log.Info(">>>>>>>>>rsp", fields...)
...@@ -283,13 +283,13 @@ func SimpleLog(opts ...Option) gin.HandlerFunc { ...@@ -283,13 +283,13 @@ func SimpleLog(opts ...Option) gin.HandlerFunc {
reqID := "" reqID := ""
if o.traceIDFrom == 1 { if o.traceIDFrom == 1 {
if v, isExist := c.Get(ctxUtils.ContextTraceIDKey.String()); isExist { if v, isExist := c.Get(ctxUtils.ContextTraceIDKey); isExist {
if requestID, ok := v.(string); ok { if requestID, ok := v.(string); ok {
reqID = requestID reqID = requestID
} }
} }
} else if o.traceIDFrom == 2 { } else if o.traceIDFrom == 2 {
reqID = c.Request.Header.Get(ctxUtils.HeaderXRequestIDKey.String()) reqID = c.Request.Header.Get(ctxUtils.HeaderXRequestIDKey)
} }
// processing requests // processing requests
...@@ -304,7 +304,7 @@ func SimpleLog(opts ...Option) gin.HandlerFunc { ...@@ -304,7 +304,7 @@ func SimpleLog(opts ...Option) gin.HandlerFunc {
zap.Int("size", c.Writer.Size()), zap.Int("size", c.Writer.Size()),
} }
if reqID != "" { if reqID != "" {
fields = append(fields, zap.String(ctxUtils.ContextTraceIDKey.String(), reqID)) fields = append(fields, zap.String(ctxUtils.ContextTraceIDKey, reqID))
} }
o.log.Info("Gin msg", fields...) o.log.Info("Gin msg", fields...)
} }
......
...@@ -20,8 +20,8 @@ type requestIDOptions struct { ...@@ -20,8 +20,8 @@ type requestIDOptions struct {
func defaultRequestIDOptions() *requestIDOptions { func defaultRequestIDOptions() *requestIDOptions {
return &requestIDOptions{ return &requestIDOptions{
contextRequestIDKey: ctxUtil.ContextTraceIDKey.String(), contextRequestIDKey: ctxUtil.ContextTraceIDKey,
headerXRequestIDKey: ctxUtil.HeaderXRequestIDKey.String(), headerXRequestIDKey: ctxUtil.HeaderXRequestIDKey,
} }
} }
...@@ -32,11 +32,11 @@ func (o *requestIDOptions) apply(opts ...RequestIDOption) { ...@@ -32,11 +32,11 @@ func (o *requestIDOptions) apply(opts ...RequestIDOption) {
} }
func (o *requestIDOptions) setRequestIDKey() { func (o *requestIDOptions) setRequestIDKey() {
if o.contextRequestIDKey != ctxUtil.ContextTraceIDKey.String() { if o.contextRequestIDKey != ctxUtil.ContextTraceIDKey {
ctxUtil.ContextTraceIDKey = ctxUtil.CtxKey(o.contextRequestIDKey) ctxUtil.ContextTraceIDKey = o.contextRequestIDKey
} }
if o.headerXRequestIDKey != ctxUtil.HeaderXRequestIDKey.String() { if o.headerXRequestIDKey != ctxUtil.HeaderXRequestIDKey {
ctxUtil.HeaderXRequestIDKey = ctxUtil.CtxKey(o.headerXRequestIDKey) ctxUtil.HeaderXRequestIDKey = o.headerXRequestIDKey
} }
} }
...@@ -76,21 +76,21 @@ func RequestID(opts ...RequestIDOption) gin.HandlerFunc { ...@@ -76,21 +76,21 @@ func RequestID(opts ...RequestIDOption) gin.HandlerFunc {
o.setRequestIDKey() o.setRequestIDKey()
return func(c *gin.Context) { return func(c *gin.Context) {
requestID := c.Request.Header.Get(ctxUtil.HeaderXRequestIDKey.String()) requestID := c.Request.Header.Get(ctxUtil.HeaderXRequestIDKey)
// Create request id // Create request id
if requestID == "" { if requestID == "" {
requestID = ctxUtil.GenerateTid() requestID = ctxUtil.GenerateTid()
c.Request.Header.Set(ctxUtil.HeaderXRequestIDKey.String(), requestID) c.Request.Header.Set(ctxUtil.HeaderXRequestIDKey, requestID)
} }
st := time.Now() st := time.Now()
// Expose it for use in the application // Expose it for use in the application
c.Set(ctxUtil.ContextTraceIDKey.String(), requestID) c.Set(ctxUtil.ContextTraceIDKey, requestID)
c.Set(ctxUtil.KeyApiStartTime.String(), st) c.Set(ctxUtil.KeyApiStartTime, st)
// Set X-Request-Id header // Set X-Request-Id header
c.Writer.Header().Set(ctxUtil.HeaderXRequestIDKey.String(), requestID) c.Writer.Header().Set(ctxUtil.HeaderXRequestIDKey, requestID)
c.Next() c.Next()
} }
...@@ -98,12 +98,12 @@ func RequestID(opts ...RequestIDOption) gin.HandlerFunc { ...@@ -98,12 +98,12 @@ func RequestID(opts ...RequestIDOption) gin.HandlerFunc {
// HeaderRequestID get request id from the header // HeaderRequestID get request id from the header
func HeaderRequestID(c *gin.Context) string { func HeaderRequestID(c *gin.Context) string {
return c.Request.Header.Get(ctxUtil.HeaderXRequestIDKey.String()) return c.Request.Header.Get(ctxUtil.HeaderXRequestIDKey)
} }
// HeaderRequestIDField get request id field from header // HeaderRequestIDField get request id field from header
func HeaderRequestIDField(c *gin.Context) zap.Field { func HeaderRequestIDField(c *gin.Context) zap.Field {
return zap.String(ctxUtil.HeaderXRequestIDKey.String(), HeaderRequestID(c)) return zap.String(ctxUtil.HeaderXRequestIDKey, HeaderRequestID(c))
} }
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
...@@ -113,7 +113,7 @@ var RequestHeaderKey = "request_header_key" ...@@ -113,7 +113,7 @@ var RequestHeaderKey = "request_header_key"
// WrapCtx wrap context, put the Keys and Header of gin.Context into context // WrapCtx wrap context, put the Keys and Header of gin.Context into context
func WrapCtx(c *gin.Context) context.Context { func WrapCtx(c *gin.Context) context.Context {
ctx := context.WithValue(c.Request.Context(), ctxUtil.ContextTraceIDKey, c.GetString(ctxUtil.ContextTraceIDKey.String())) //nolint ctx := context.WithValue(c.Request.Context(), ctxUtil.ContextTraceIDKey, c.GetString(ctxUtil.ContextTraceIDKey)) //nolint
for k, v := range c.Keys { for k, v := range c.Keys {
ctx = context.WithValue(ctx, k, v) //nolint ctx = context.WithValue(ctx, k, v) //nolint
} }
...@@ -122,7 +122,7 @@ func WrapCtx(c *gin.Context) context.Context { ...@@ -122,7 +122,7 @@ func WrapCtx(c *gin.Context) context.Context {
} }
func WrapAsyncCtx(c *gin.Context) context.Context { func WrapAsyncCtx(c *gin.Context) context.Context {
ctx := context.WithValue(context.Background(), ctxUtil.ContextTraceIDKey, c.GetString(ctxUtil.ContextTraceIDKey.String())) //nolint ctx := context.WithValue(context.Background(), ctxUtil.ContextTraceIDKey, c.GetString(ctxUtil.ContextTraceIDKey)) //nolint
for k, v := range c.Keys { for k, v := range c.Keys {
ctx = context.WithValue(ctx, k, v) //nolint ctx = context.WithValue(ctx, k, v) //nolint
} }
......
package middleware
import (
"context"
"net/http"
"testing"
"time"
ctxUtil "gitlab.wanzhuangkj.com/tush/xpkg/gin/ctxUtils"
"gitlab.wanzhuangkj.com/tush/xpkg/utils"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
)
func runRequestIDHTTPServer(fn func(c *gin.Context)) string {
serverAddr, requestAddr := utils.GetLocalHTTPAddrPairs()
gin.SetMode(gin.ReleaseMode)
r := gin.Default()
r.Use(RequestID(
//WithRequestIDKey("my_req_id"),
//WithHeaderRequestIDKey("My-X-Req-Id"),
))
r.GET("/ping", func(c *gin.Context) {
fn(c)
c.String(200, "pong")
})
go func() {
err := r.Run(serverAddr)
if err != nil {
panic(err)
}
}()
time.Sleep(time.Millisecond * 200)
return requestAddr
}
func TestFieldRequestIDFromContext(t *testing.T) {
requestAddr := runRequestIDHTTPServer(func(c *gin.Context) {
str := ctxUtil.CtxRequestID(c)
t.Log(str)
field := ctxUtil.CtxTraceIDField(c)
t.Log(field)
str = HeaderRequestID(c)
t.Log(str)
field = HeaderRequestIDField(c)
t.Log(field)
str = ctxUtil.CtxRequestID(c)
t.Log(str)
field = ctxUtil.CtxTraceIDField(c)
t.Log(field)
c.Set("foo", "bar")
ctx := WrapCtx(c)
t.Log(ctx.Value(ctxUtil.ContextTraceIDKey))
t.Log(GetFromCtx(ctx, "foo"))
t.Log(ctxUtil.CtxTraceIDField(ctx))
t.Log(GetFromCtx(ctx, "not-exist"))
t.Log(GetFromHeader(ctx, ctxUtil.HeaderXRequestIDKey.String()))
t.Log(GetFromHeader(ctx, "Accept"))
t.Log(GetFromHeader(ctx, "not-exist"))
t.Log(GetFromHeaders(ctx, "Accept"))
t.Log(GetFromHeaders(ctx, "not-exist"))
cctx := c
c2, ctx2 := AdaptCtx(cctx)
t.Log(ctxUtil.CtxRequestID(c2))
t.Log(ctx2.Value(ctxUtil.ContextTraceIDKey))
})
_, err := http.Get(requestAddr + "/ping")
assert.NoError(t, err)
defer func() { recover() }()
req, _ := http.NewRequest("GET", requestAddr+"/ping", nil)
req.Header.Add("Accept", "application/json")
req.Header.Add("Accept", "text/html")
req.Header.Set(ctxUtil.HeaderXRequestIDKey.String(), "2ab996de-cc03-412d-ba0a-79596efa6947")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
defer resp.Body.Close()
}
func TestGetRequestIDFromContext(t *testing.T) {
str := ctxUtil.CtxRequestID(&gin.Context{})
assert.Equal(t, "", str)
str = ctxUtil.CtxRequestID(context.Background())
assert.Equal(t, "", str)
}
func TestRequestIDKeyOptions(t *testing.T) {
opts := []RequestIDOption{
WithContextRequestIDKey("xx"), // invalid settings
WithContextRequestIDKey("my_req_id"),
WithHeaderRequestIDKey("xx"), // invalid settings
WithHeaderRequestIDKey("My-X-Req-Id"),
}
o := defaultRequestIDOptions()
o.apply(opts...)
o.setRequestIDKey()
t.Log(ctxUtil.ContextTraceIDKey, ctxUtil.HeaderXRequestIDKey)
assert.Equal(t, "my_req_id", ctxUtil.ContextTraceIDKey)
assert.Equal(t, "My-X-Req-Id", ctxUtil.HeaderXRequestIDKey)
}
...@@ -143,9 +143,9 @@ func Out(c *gin.Context, err *errcode.Error, data ...interface{}) { ...@@ -143,9 +143,9 @@ func Out(c *gin.Context, err *errcode.Error, data ...interface{}) {
// status code flat 200, custom error codes in data.code // status code flat 200, custom error codes in data.code
func respJSONWith200(c *gin.Context, code int, msg string, data ...interface{}) { func respJSONWith200(c *gin.Context, code int, msg string, data ...interface{}) {
c.Writer.Header().Set(ctxUtils.HeaderXTimestampKey.String(), strconv.FormatInt(time.Now().Unix(), 10)) c.Writer.Header().Set(ctxUtils.HeaderXTimestampKey, strconv.FormatInt(time.Now().Unix(), 10))
appName := c.GetString(ctxUtils.KeyAppName.String()) appName := c.GetString(ctxUtils.KeyAppName)
stTime := c.GetTime(ctxUtils.KeyApiStartTime.String()) stTime := c.GetTime(ctxUtils.KeyApiStartTime)
ctxUtils.AddApiCost(c, appName, stTime) ctxUtils.AddApiCost(c, appName, stTime)
if len(data) > 0 { if len(data) > 0 {
...@@ -158,13 +158,13 @@ func respJSONWith200(c *gin.Context, code int, msg string, data ...interface{}) ...@@ -158,13 +158,13 @@ func respJSONWith200(c *gin.Context, code int, msg string, data ...interface{})
// Success return success // Success return success
func Success(c *gin.Context, data ...interface{}) { func Success(c *gin.Context, data ...interface{}) {
c.Set(ctxUtils.KeyRspCode.String(), 1) c.Set(ctxUtils.KeyRspCode, 1)
respJSONWith200(c, errcode.Success.Code(), errcode.Success.Msg(), data...) respJSONWith200(c, errcode.Success.Code(), errcode.Success.Msg(), data...)
} }
// SuccessWithPage return success // SuccessWithPage return success
func SuccessWithPage[T any](c *gin.Context, list []*T, total int64) { func SuccessWithPage[T any](c *gin.Context, list []*T, total int64) {
c.Set(ctxUtils.KeyRspCode.String(), 1) c.Set(ctxUtils.KeyRspCode, 1)
if list == nil { if list == nil {
list = []*T{} list = []*T{}
} }
...@@ -173,7 +173,7 @@ func SuccessWithPage[T any](c *gin.Context, list []*T, total int64) { ...@@ -173,7 +173,7 @@ func SuccessWithPage[T any](c *gin.Context, list []*T, total int64) {
// SuccessWithList return success // SuccessWithList return success
func SuccessWithList[T any](c *gin.Context, list []*T) { func SuccessWithList[T any](c *gin.Context, list []*T) {
c.Set(ctxUtils.KeyRspCode.String(), 1) c.Set(ctxUtils.KeyRspCode, 1)
if list == nil { if list == nil {
list = []*T{} list = []*T{}
} }
...@@ -182,12 +182,12 @@ func SuccessWithList[T any](c *gin.Context, list []*T) { ...@@ -182,12 +182,12 @@ func SuccessWithList[T any](c *gin.Context, list []*T) {
// ErrorE return error // ErrorE return error
func ErrorE(c *gin.Context, err *errcode.Error, data ...interface{}) { func ErrorE(c *gin.Context, err *errcode.Error, data ...interface{}) {
c.Set(ctxUtils.KeyRspCode.String(), 0) c.Set(ctxUtils.KeyRspCode, 0)
respJSONWith200(c, err.Code(), err.Msg(), data...) respJSONWith200(c, err.Code(), err.Msg(), data...)
} }
func Error(c *gin.Context, err error) { func Error(c *gin.Context, err error) {
c.Set(ctxUtils.KeyRspCode.String(), 0) c.Set(ctxUtils.KeyRspCode, 0)
msg := "" msg := ""
if err != nil { if err != nil {
msg = err.Error() msg = err.Error()
......
...@@ -3,6 +3,7 @@ package entity ...@@ -3,6 +3,7 @@ package entity
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"gitlab.wanzhuangkj.com/tush/xpkg/gin/ctxUtils" "gitlab.wanzhuangkj.com/tush/xpkg/gin/ctxUtils"
) )
...@@ -25,11 +26,11 @@ func SetCopyReq(c *gin.Context, buf *bytes.Buffer) { ...@@ -25,11 +26,11 @@ func SetCopyReq(c *gin.Context, buf *bytes.Buffer) {
copyHttpReq.URL = c.Request.URL.String() copyHttpReq.URL = c.Request.URL.String()
copyHttpReq.Headers = c.Request.Header copyHttpReq.Headers = c.Request.Header
copyHttpReq.Body = buf.String() copyHttpReq.Body = buf.String()
c.Set(ctxUtils.KeyReqBody.String(), copyHttpReq) c.Set(ctxUtils.KeyReqBody, copyHttpReq)
} }
func GetCopyReq(c *gin.Context) *CopyHttpReq { func GetCopyReq(c *gin.Context) *CopyHttpReq {
if val, isExist := c.Get(ctxUtils.KeyReqBody.String()); isExist { if val, isExist := c.Get(ctxUtils.KeyReqBody); isExist {
if req, ok := val.(*CopyHttpReq); ok { if req, ok := val.(*CopyHttpReq); ok {
return req return req
} }
...@@ -41,11 +42,11 @@ func SetCopyRsp(c *gin.Context, buf *bytes.Buffer) { ...@@ -41,11 +42,11 @@ func SetCopyRsp(c *gin.Context, buf *bytes.Buffer) {
copyHttpRsp := &CopyHttpRsp{} copyHttpRsp := &CopyHttpRsp{}
copyHttpRsp.Headers = c.Writer.Header() copyHttpRsp.Headers = c.Writer.Header()
copyHttpRsp.Body = buf.String() copyHttpRsp.Body = buf.String()
c.Set(ctxUtils.KeyRspBody.String(), copyHttpRsp) c.Set(ctxUtils.KeyRspBody, copyHttpRsp)
} }
func GetCopyRsp(c *gin.Context) *CopyHttpRsp { func GetCopyRsp(c *gin.Context) *CopyHttpRsp {
if val, isExist := c.Get(ctxUtils.KeyRspBody.String()); isExist { if val, isExist := c.Get(ctxUtils.KeyRspBody); isExist {
if rsp, ok := val.(*CopyHttpRsp); ok { if rsp, ok := val.(*CopyHttpRsp); ok {
return rsp return rsp
} }
...@@ -59,11 +60,11 @@ func SetCopyApiReq(c *gin.Context, buf *bytes.Buffer) { ...@@ -59,11 +60,11 @@ func SetCopyApiReq(c *gin.Context, buf *bytes.Buffer) {
copyHttpReq.URL = c.Request.URL.String() copyHttpReq.URL = c.Request.URL.String()
copyHttpReq.Headers = c.Request.Header copyHttpReq.Headers = c.Request.Header
copyHttpReq.Body = buf.String() copyHttpReq.Body = buf.String()
c.Set(fmt.Sprintf(ctxUtils.KeyOApiReqBody.String(), ctxUtils.GetGinCtxTraceID(c)), copyHttpReq) c.Set(fmt.Sprintf(ctxUtils.KeyOApiReqBody, ctxUtils.GetGinCtxTraceID(c)), copyHttpReq)
} }
func GetCopyApiReq(c *gin.Context) *CopyHttpReq { func GetCopyApiReq(c *gin.Context) *CopyHttpReq {
if val, isExist := c.Get(fmt.Sprintf(ctxUtils.KeyOApiReqBody.String(), ctxUtils.GetGinCtxTraceID(c))); isExist { if val, isExist := c.Get(fmt.Sprintf(ctxUtils.KeyOApiReqBody, ctxUtils.GetGinCtxTraceID(c))); isExist {
if req, ok := val.(*CopyHttpReq); ok { if req, ok := val.(*CopyHttpReq); ok {
return req return req
} }
...@@ -75,11 +76,11 @@ func SetCopyApiRsp(c *gin.Context, buf *bytes.Buffer) { ...@@ -75,11 +76,11 @@ func SetCopyApiRsp(c *gin.Context, buf *bytes.Buffer) {
copyHttpRsp := &CopyHttpRsp{} copyHttpRsp := &CopyHttpRsp{}
copyHttpRsp.Headers = c.Writer.Header() copyHttpRsp.Headers = c.Writer.Header()
copyHttpRsp.Body = buf.String() copyHttpRsp.Body = buf.String()
c.Set(fmt.Sprintf(ctxUtils.KeyOApiRspBody.String(), ctxUtils.GetGinCtxTraceID(c)), copyHttpRsp) c.Set(fmt.Sprintf(ctxUtils.KeyOApiRspBody, ctxUtils.GetGinCtxTraceID(c)), copyHttpRsp)
} }
func GetCopyApiRsp(c *gin.Context) *CopyHttpRsp { func GetCopyApiRsp(c *gin.Context) *CopyHttpRsp {
if val, isExist := c.Get(fmt.Sprintf(ctxUtils.KeyOApiRspBody.String(), ctxUtils.GetGinCtxTraceID(c))); isExist { if val, isExist := c.Get(fmt.Sprintf(ctxUtils.KeyOApiRspBody, ctxUtils.GetGinCtxTraceID(c))); isExist {
if rsp, ok := val.(*CopyHttpRsp); ok { if rsp, ok := val.(*CopyHttpRsp); ok {
return rsp return rsp
} }
......
...@@ -290,7 +290,7 @@ func (x *Request) send(ctx context.Context) { ...@@ -290,7 +290,7 @@ func (x *Request) send(ctx context.Context) {
x.request.Header.Add(k, v) x.request.Header.Add(k, v)
} }
} }
x.request.Header.Add(ctxUtils.HeaderXRequestIDKey.String(), ctxUtils.CtxRequestID(ctx)) x.request.Header.Add(ctxUtils.HeaderXRequestIDKey, ctxUtils.CtxRequestID(ctx))
if x.timeout < 1 { if x.timeout < 1 {
x.timeout = defaultTimeout x.timeout = defaultTimeout
} }
...@@ -378,7 +378,6 @@ func (x *Request) pushDo(ctx context.Context) { ...@@ -378,7 +378,6 @@ func (x *Request) pushDo(ctx context.Context) {
var rsp *http.Response var rsp *http.Response
rsp, x.err = client.Do(x.request) rsp, x.err = client.Do(x.request)
if x.err != nil { if x.err != nil {
x.request = nil
return return
} }
if rsp != nil { if rsp != nil {
...@@ -390,7 +389,6 @@ func (x *Request) pushDo(ctx context.Context) { ...@@ -390,7 +389,6 @@ func (x *Request) pushDo(ctx context.Context) {
defer rsp.Body.Close() defer rsp.Body.Close()
x.response.body, x.err = io.ReadAll(rsp.Body) x.response.body, x.err = io.ReadAll(rsp.Body)
if x.err != nil { if x.err != nil {
x.request = nil
return return
} }
if len(x.response.body) > 0 { if len(x.response.body) > 0 {
...@@ -400,7 +398,6 @@ func (x *Request) pushDo(ctx context.Context) { ...@@ -400,7 +398,6 @@ func (x *Request) pushDo(ctx context.Context) {
} }
} }
} }
x.request = nil
} }
// ----------------------------------- Response ----------------------------------- // ----------------------------------- Response -----------------------------------
......
...@@ -7,7 +7,6 @@ import ( ...@@ -7,7 +7,6 @@ import (
"sync" "sync"
"time" "time"
ctxUtil "gitlab.wanzhuangkj.com/tush/xpkg/gin/ctxUtils"
"gitlab.wanzhuangkj.com/tush/xpkg/jwt" "gitlab.wanzhuangkj.com/tush/xpkg/jwt"
"gitlab.wanzhuangkj.com/tush/xpkg/logger" "gitlab.wanzhuangkj.com/tush/xpkg/logger"
"gitlab.wanzhuangkj.com/tush/xpkg/utils/xsf" "gitlab.wanzhuangkj.com/tush/xpkg/utils/xsf"
...@@ -27,60 +26,54 @@ const ( ...@@ -27,60 +26,54 @@ const (
) )
type wsConn struct { type wsConn struct {
manager *WsConnManager manager *WsConnManager
id xsf.ID receiverID xsf.ID // user id
conn *websocket.Conn conn *websocket.Conn
sendBuff chan []byte sendBuff chan *WsMessage
log *zap.Logger log *zap.Logger
stop chan struct{} stop chan struct{}
wg *sync.WaitGroup
} }
type WsConnManager struct { type WsConnManager struct {
pool map[xsf.ID]*wsConn pool map[xsf.ID]*wsConn
upgrader *websocket.Upgrader upgrader *websocket.Upgrader
sync.RWMutex l *sync.RWMutex
log *zap.Logger log *zap.Logger
hooks []Hook hooks []Hook
} }
var (
WsConnMgr *WsConnManager
)
type Hook interface { type Hook interface {
AfterSend(ctx context.Context, receiverID xsf.ID, payload *WsMessage) error AfterSend(receiverID xsf.ID, payload *WsMessage) error
AfterAccept(ctx context.Context, userID xsf.ID) error AfterAccept(userID xsf.ID) error
AfterUnregister(ctx context.Context, userID xsf.ID) error AfterUnregister(userID xsf.ID) error
OnReceive(senderID xsf.ID, messageType int, msg []byte)
} }
func NewWsConnManager(logger *zap.Logger, upgrader *websocket.Upgrader, hooks ...Hook) *WsConnManager { func NewWsConnManager(logger *zap.Logger, upgrader *websocket.Upgrader, hooks ...Hook) *WsConnManager {
return &WsConnManager{ return &WsConnManager{
pool: make(map[xsf.ID]*wsConn), pool: make(map[xsf.ID]*wsConn),
log: logger, upgrader: upgrader, hooks: hooks} log: logger,
upgrader: upgrader,
hooks: hooks,
l: &sync.RWMutex{},
}
} }
func (m *WsConnManager) register(ctx context.Context, conn *wsConn) { func (m *WsConnManager) register(conn *wsConn) {
m.Lock() if oldClient, exists := m.pool[conn.receiverID]; exists {
defer m.Unlock() oldClient.stop <- struct{}{}
if oldClient, exists := m.pool[conn.id]; exists {
oldClient.close(ctx)
} }
m.pool[conn.id] = conn m.pool[conn.receiverID] = conn
} }
// 注销连接 // 注销连接
func (conn *wsConn) close(ctx context.Context) { func (conn *wsConn) close() {
conn.manager.Lock()
defer conn.manager.Unlock()
delete(conn.manager.pool, conn.id)
close(conn.sendBuff) close(conn.sendBuff)
conn.stop <- struct{}{}
close(conn.stop) close(conn.stop)
conn.conn.Close() conn.conn.Close()
for _, h := range conn.manager.hooks { for _, h := range conn.manager.hooks {
go func() { h.AfterUnregister(conn.receiverID)
h.AfterUnregister(ctx, conn.id)
}()
} }
} }
...@@ -88,7 +81,7 @@ func (conn *wsConn) close(ctx context.Context) { ...@@ -88,7 +81,7 @@ func (conn *wsConn) close(ctx context.Context) {
func (m *WsConnManager) Accept(c *gin.Context) { func (m *WsConnManager) Accept(c *gin.Context) {
err := m.accept(c) err := m.accept(c)
if err != nil { if err != nil {
m.log.Error("handleWsConn failed", logger.Err(err)) m.log.Error("accept conn failed", logger.Err(err))
} }
} }
...@@ -114,44 +107,35 @@ func (m *WsConnManager) accept(c *gin.Context) error { ...@@ -114,44 +107,35 @@ func (m *WsConnManager) accept(c *gin.Context) error {
return xerror.Wrap(err, "ws upgrade failed") return xerror.Wrap(err, "ws upgrade failed")
} }
client := &wsConn{ client := &wsConn{
id: userID, receiverID: userID,
conn: conn, conn: conn,
sendBuff: make(chan []byte, 256), sendBuff: make(chan *WsMessage, 256),
manager: m, manager: m,
log: m.log, log: m.log,
stop: make(chan struct{}), stop: make(chan struct{}),
wg: &sync.WaitGroup{},
} }
go client.start()
ctx := ctxUtil.WrapCtx(c) m.register(client)
m.register(ctx, client)
go client.heartBeat()
go client.writeLoop()
for _, h := range m.hooks { for _, h := range m.hooks {
go func() { h.AfterAccept(userID)
h.AfterAccept(ctx, userID)
}()
} }
return nil return nil
} }
func (m *WsConnManager) getConn(userID xsf.ID) (*wsConn, bool) { func (m *WsConnManager) getConn(userID xsf.ID) (*wsConn, bool) {
m.RLock() m.l.RLock()
defer m.RUnlock() defer m.l.RUnlock()
client, exists := m.pool[userID] client, exists := m.pool[userID]
return client, exists return client, exists
} }
func (m *WsConnManager) Send(ctx context.Context, receiverID xsf.ID, payload *WsMessage) error { func (m *WsConnManager) Send(ctx context.Context, receiverID xsf.ID, payload *WsMessage) error {
if payload == nil {
return nil
}
conn, exists := m.getConn(receiverID) conn, exists := m.getConn(receiverID)
if exists { if exists {
data, _ := json.Marshal(payload) err := conn.send(ctx, payload)
err := conn.send(ctx, data)
if err != nil { if err != nil {
return err return err
} }
...@@ -160,42 +144,117 @@ func (m *WsConnManager) Send(ctx context.Context, receiverID xsf.ID, payload *Ws ...@@ -160,42 +144,117 @@ func (m *WsConnManager) Send(ctx context.Context, receiverID xsf.ID, payload *Ws
} }
for _, h := range m.hooks { for _, h := range m.hooks {
go func() { go func() {
h.AfterSend(ctx, receiverID, payload) h.AfterSend(receiverID, payload)
}() }()
} }
return nil return nil
} }
func (c *wsConn) send(_ context.Context, msg []byte) error { func (c *wsConn) start() {
// todo 1. deadline time 2. retry c.wg.Add(3)
go c.heartBeat()
go c.writeLoop()
go c.readLoop()
c.wg.Wait()
c.close()
}
func (c *wsConn) send(_ context.Context, msg *WsMessage) error {
c.sendBuff <- msg c.sendBuff <- msg
return nil return nil
} }
func (c *wsConn) heartBeat() { func (c *wsConn) heartBeat() {
c.log.Info("[ws][hearbeat]start")
ticker := time.NewTicker(heartbeatDuration) ticker := time.NewTicker(heartbeatDuration)
defer ticker.Stop() defer func() {
c.log.Info("[ws][hearbeat]stop")
ticker.Stop()
c.stop <- struct{}{}
c.wg.Done()
}()
for { for {
select { select {
case <-ticker.C: case <-ticker.C:
if err := c.conn.WriteMessage(websocket.PingMessage, nil); err != nil { if err := c.conn.WriteMessage(websocket.PingMessage, nil); err != nil {
defer c.close(context.Background()) c.log.Error("[ws][hearbeat]ping failed", logger.Err(err))
c.stop <- struct{}{}
return return
} }
case <-c.stop: case <-c.stop:
c.log.Info("[ws][hearbeat]stop signal received")
return return
} }
} }
} }
func (c *wsConn) writeLoop() { func (c *wsConn) writeLoop() {
c.log.Info("[ws][writeLoop]start")
defer func() {
c.log.Info("[ws][writeLoop]stop")
c.stop <- struct{}{}
c.wg.Done()
}()
for { for {
select { select {
case msg := <-c.sendBuff: case msg, ok := <-c.sendBuff:
if err := c.conn.WriteMessage(websocket.BinaryMessage, msg); err != nil { if !ok {
c.log.Error("write message failed", logger.Err(err)) c.log.Info("[ws][writeLoop]send channel closed, writer exit")
return
}
data, _ := json.Marshal(msg)
if err := c.conn.WriteMessage(websocket.TextMessage, data); err != nil {
c.log.Error("[ws][writeLoop]write message failed", logger.Err(err))
return
}
case <-c.stop:
c.log.Info("[ws][writeLoop]stop signal received")
return
}
}
}
type WsMsg struct {
senderID xsf.ID
msgType int
msg []byte
}
func (c *wsConn) readLoop() {
c.log.Info("[ws][readLoop]start")
msgChan := make(chan WsMsg)
defer func() {
c.log.Info("[ws][readLoop]exit")
close(msgChan)
c.stop <- struct{}{}
c.wg.Done()
}()
// 读协程
go func() {
for {
msgType, msg, err := c.conn.ReadMessage()
c.log.Info("[ws][readLoop]receive message", logger.String("msg", string(msg)))
if err != nil {
c.log.Error("[ws][readLoop]read message failed", logger.Err(err))
return
}
msgChan <- WsMsg{c.receiverID, msgType, msg}
}
}()
for {
select {
case m, ok := <-msgChan:
if !ok {
c.log.Info("[ws][readLoop]reader channel closed, exit")
return
}
for _, hook := range c.manager.hooks {
hook.OnReceive(m.senderID, m.msgType, m.msg)
} }
case <-c.stop: case <-c.stop:
c.log.Info("[ws][readLoop]stop signal received")
return return
} }
} }
...@@ -206,7 +265,7 @@ const ( ...@@ -206,7 +265,7 @@ const (
) )
type WsMessage struct { type WsMessage struct {
Seq string `json:"seq"` Seq string `json:"seq"`
Cmd Cmd `json:"cmd"` Cmd Cmd `json:"cmd"`
Data any `json:"payload"` Data json.RawMessage `json:"payload"` // 原始JSON,目前是models.ChatMessage
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论