Compare commits

..

2 Commits

Author SHA1 Message Date
bd01c39fcc 参数解析增加解析标题 2025-02-07 18:16:34 +08:00
7ddd96bcb7 参数配置解析 2025-02-07 18:14:57 +08:00
15 changed files with 432 additions and 791 deletions

View File

@ -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
)

View File

@ -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"
"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), ".", ""),
wrapper.StringFromRandom(32, "").Md5().Value,
)
getRequestID := func(ctx *gin.Context, traceID string) string {
requestID := ctx.GetHeader("X-Forward-Request-Id")
if len(requestID) > 0 {
return requestID
}
if len(traceID) > 0 {
return traceID
}
return traceID
}
ctx := &Context{
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
}

View File

@ -10,7 +10,6 @@ package define
import (
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/wrapper"
"sync"
)
var (
@ -125,24 +124,3 @@ func GetHttpHandleConfig() *HttpHandleConfig {
).Value(),
}
}
const (
LogicAfterResponseKey = "__logic_after_response__"
)
type LogicAfterResponse struct {
SuccessHookFuncList []func() `json:"-"` // 请求最后需要执行的成功hook函数
FailureHookFuncList []func() `json:"-"` // 请求最后需要执行的失败hook函数
Lock *sync.RWMutex `json:"-"` // 逻辑锁
}
func (logic *LogicAfterResponse) AddSuccessHook(f func()) {
logic.Lock.Lock()
defer logic.Lock.Unlock()
logic.SuccessHookFuncList = append(logic.SuccessHookFuncList, f)
}
func (logic *LogicAfterResponse) AddFailureHook(f func()) {
logic.Lock.Lock()
defer logic.Lock.Unlock()
logic.FailureHookFuncList = append(logic.FailureHookFuncList, f)
}

50
go.mod
View File

@ -1,19 +1,18 @@
module git.zhangdeman.cn/zhangdeman/gin
go 1.23.0
go 1.21.0
toolchain go1.24.2
toolchain go1.23.1
require (
git.zhangdeman.cn/gateway/api-doc v0.0.0-20250220105101-71d6db967dc5
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250328040304-7e4a6f9f148c
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250122075709-5ecf3edb4a00
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/wrapper v0.0.0-20250321102712-1cbfbe959740
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250124091620-c757e551a8c9
github.com/gin-gonic/gin v1.10.0
github.com/go-playground/validator/v10 v10.26.0
github.com/go-playground/validator/v10 v10.24.0
github.com/mcuadros/go-defaults v1.2.0
github.com/sbabiv/xml2map v1.2.1
go.uber.org/zap v1.27.0
@ -23,61 +22,48 @@ require (
git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda // indirect
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4 // indirect
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 // indirect
git.zhangdeman.cn/zhangdeman/trace v0.0.0-20250412104923-c1ecb1bfe8d5 // indirect
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e // indirect
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20241125101541-c5ea194c9c1e // indirect
github.com/BurntSushi/toml v1.5.0 // indirect
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/BurntSushi/toml v1.4.0 // indirect
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect
github.com/bytedance/sonic v1.13.2 // indirect
github.com/bytedance/sonic/loader v0.2.4 // indirect
github.com/bytedance/sonic v1.12.8 // indirect
github.com/bytedance/sonic/loader v0.2.3 // indirect
github.com/cloudwego/base64x v0.1.5 // indirect
github.com/cloudwego/iasm v0.2.0 // 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.1.0 // 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
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/spec v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-webtools/knife4go v1.0.4 // indirect
github.com/goccy/go-json v0.10.5 // indirect
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.10 // indirect
github.com/klauspost/cpuid/v2 v2.2.9 // 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
github.com/mailru/easyjson v0.9.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mozillazg/go-pinyin v0.20.0 // indirect
github.com/mssola/user_agent v0.6.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/swaggo/files v1.0.1 // indirect
github.com/swaggo/gin-swagger v1.6.0 // indirect
github.com/swaggo/swag v1.16.4 // indirect
github.com/tidwall/gjson v1.18.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.16.0 // indirect
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/net v0.39.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/text v0.24.0 // indirect
golang.org/x/tools v0.30.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
golang.org/x/arch v0.14.0 // indirect
golang.org/x/crypto v0.32.0 // indirect
golang.org/x/net v0.34.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/text v0.22.0 // indirect
google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

167
go.sum
View File

@ -1,19 +1,13 @@
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-20250328040304-7e4a6f9f148c h1:cl3gQGXQpJ8ugDs0C/hQLfcvF4lGBm5BeABLvROFDoM=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250328040304-7e4a6f9f148c/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250122075709-5ecf3edb4a00 h1:obyJF0CXVR93TOnOtzN5xXxxSLpw1UFMBc4niWiyoQI=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250122075709-5ecf3edb4a00/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=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4/go.mod h1:V4Dfg1v/JVIZGEKCm6/aehs8hK+Xow1dkL1yiQymXlQ=
git.zhangdeman.cn/zhangdeman/exception v0.0.0-20240930081343-1e7f84ed8465 h1:j5EB0hamTMT5fY+xmjJ51oBvll+vS2inNPi+3/UBj60=
git.zhangdeman.cn/zhangdeman/exception v0.0.0-20240930081343-1e7f84ed8465/go.mod h1:Voc8J4ordx7nuMWpgACXXZULQy7ZIuBzcEIoS8VnDIw=
git.zhangdeman.cn/zhangdeman/exception v0.0.0-20250207091353-907c20662792 h1:BehqU7W+FF39xCcrbrlPBggbKVTIguDDXfABn8l5RB4=
git.zhangdeman.cn/zhangdeman/exception v0.0.0-20250207091353-907c20662792/go.mod h1:Voc8J4ordx7nuMWpgACXXZULQy7ZIuBzcEIoS8VnDIw=
git.zhangdeman.cn/zhangdeman/exception v0.0.0-20250207091724-ca151fbc1f06 h1:XsjGMkBCi93h56oCg5Lrz5zVpUxify/CQVhQU9+qLWM=
git.zhangdeman.cn/zhangdeman/exception v0.0.0-20250207091724-ca151fbc1f06/go.mod h1:Voc8J4ordx7nuMWpgACXXZULQy7ZIuBzcEIoS8VnDIw=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20241125083316-eab7bab9d7ad h1:6BI3QiDI64SlER1006UJbTJyOCXxB8KCmCK+Kr7FzQo=
@ -24,79 +18,67 @@ git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 h1:gUDlQ
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0/go.mod h1:VHb9qmhaPDAQDcS6vUiDCamYjZ4R5lD1XtVsh55KsMI=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd h1:q7GG14qgXKB4MEXQFOe7/UYebsqMfPaSX80TcPdOosI=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd/go.mod h1:+D6uPSljwHywjVY5WSBY4TRVMj26TN5f5cFGEYMldjs=
git.zhangdeman.cn/zhangdeman/trace v0.0.0-20250412104923-c1ecb1bfe8d5 h1:dD1Q/MIrRmIhKqfYPH+y167ca9CKwTPuQt3c1hXWGJ8=
git.zhangdeman.cn/zhangdeman/trace v0.0.0-20250412104923-c1ecb1bfe8d5/go.mod h1:PB486NC82nuvn5yi+U2i48ogX/9EAETWAHd8O9TwY9k=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e h1:Q973S6CcWr1ICZhFI1STFOJ+KUImCl2BaIXm6YppBqI=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI=
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20240723075210-85feada512b2 h1:P2kuhU2TFWk9mPbJlZCK6FMDVS7S3NGafWKD4eNqKiI=
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20240723075210-85feada512b2/go.mod h1:7KaMpQmWgiNLpEkaV7oDtep7geI1f/VoCoPVcyvMjAE=
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20241125101541-c5ea194c9c1e h1:YE2Gi+M03UDImIpWa3I7jzSesyfu2RL8x/4ONs5v0oE=
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20241125101541-c5ea194c9c1e/go.mod h1:L/7JugxKZL3JP9JP/XDvPAPz0FQXG1u181Su1+u/d1c=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250124091620-c757e551a8c9 h1:yF770WIDNwyiKL0nwmBGmjZvNCLXtHQL4xJyffPjTMU=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250124091620-c757e551a8c9/go.mod h1:I76wxEsWq7KnMQ84elpwTjEqq4I49QFw60tp5h7iGBs=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740 h1:zPUoylfJTbc0EcxW+NEzOTBmoeFZ2I/rLFBnEzxb4Wk=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740/go.mod h1:1ct92dbVc49pmXusA/iGfcQUJzcYmJ+cjAhgc3sDv1I=
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
github.com/bytedance/sonic v1.12.9 h1:Od1BvK55NnewtGaJsTDeAOSnLVO2BTSLOe0+ooKokmQ=
github.com/bytedance/sonic v1.12.9/go.mod h1:uVvFidNmlt9+wa31S1urfwwthTWteBgG0hWuoKAXTx8=
github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ=
github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
github.com/bytedance/sonic v1.12.5 h1:hoZxY8uW+mT+OpkcUWw4k0fDINtOcVavEsGfzwzFU/w=
github.com/bytedance/sonic v1.12.5/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
github.com/bytedance/sonic v1.12.7 h1:CQU8pxOy9HToxhndH0Kx/S1qU/CuS9GnKYrGioDcU1Q=
github.com/bytedance/sonic v1.12.7/go.mod h1:tnbal4mxOMju17EGfknm2XyYcpyCnIROYOEYuemj13I=
github.com/bytedance/sonic v1.12.8 h1:4xYRVRlXIgvSZ4e8iVTlMF5szgpXd4AfvuWgA8I8lgs=
github.com/bytedance/sonic v1.12.8/go.mod h1:uVvFidNmlt9+wa31S1urfwwthTWteBgG0hWuoKAXTx8=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/bytedance/sonic/loader v0.2.1 h1:1GgorWTqf12TA8mma4DDSbaQigE2wOgQo7iCjjJv3+E=
github.com/bytedance/sonic/loader v0.2.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/bytedance/sonic/loader v0.2.3 h1:yctD0Q3v2NOGfSWPLPvG2ggA2kV6TS6s4wioyEqssH0=
github.com/bytedance/sonic/loader v0.2.3/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
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/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/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4=
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk=
github.com/gin-contrib/pprof v1.5.2 h1:Kcq5W2bA2PBcVtF0MqkQjpvCpwJr+pd7zxcQh2csg7E=
github.com/gin-contrib/pprof v1.5.2/go.mod h1:a1W4CDXwAPm2zql2AKdnT7OVCJdV/oFPhJXVOrDs5Ns=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E=
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8=
github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
github.com/go-webtools/knife4go v1.0.4 h1:p32SApmM0sx2/Y5p0QfeaGv5KD96R1mj2CaHdyH8jy8=
github.com/go-webtools/knife4go v1.0.4/go.mod h1:trOlXN1tqBJ7R44sHON3exGvzCwjbsVriIHEenry3d8=
github.com/go-playground/validator/v10 v10.24.0 h1:KHQckvo8G6hlWnrPX4NJJ+aBfWNAE/HH+qdL2cBpCmg=
github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@ -104,18 +86,12 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQymUhg=
github.com/jonboulle/clockwork v0.3.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
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=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@ -128,8 +104,6 @@ github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkL
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA=
github.com/lestrrat-go/strftime v1.1.0 h1:gMESpZy44/4pXLO/m+sL0yBd1W6LjgjrrD4a68Gapyg=
github.com/lestrrat-go/strftime v1.1.0/go.mod h1:uzeIB52CeUJenCo1syghlugshMysrqUT51HlxphXVeI=
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mcuadros/go-defaults v1.2.0 h1:FODb8WSf0uGaY8elWJAkoLL0Ri6AlZ1bFlenk56oZtc=
@ -147,17 +121,14 @@ github.com/mozillazg/go-pinyin v0.20.0 h1:BtR3DsxpApHfKReaPO1fCqF4pThRwH9uwvXzm+
github.com/mozillazg/go-pinyin v0.20.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
github.com/mssola/user_agent v0.6.0 h1:uwPR4rtWlCHRFyyP9u2KOV0u8iQXmS7Z7feTrstQwk4=
github.com/mssola/user_agent v0.6.0/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/sbabiv/xml2map v1.2.1 h1:1lT7t0hhUvXZCkdxqtq4n8/ZCnwLWGq4rDuDv5XOoFE=
github.com/sbabiv/xml2map v1.2.1/go.mod h1:2TPoAfcaM7+Sd4iriPvzyntb2mx7GY+kkQpB/GQa/eo=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
@ -172,14 +143,10 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
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.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M=
github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo=
github.com/swaggo/swag v1.16.4 h1:clWJtd9LStiG3VeijiCfOVODP6VpHtKdQy9ELFG3s1A=
github.com/swaggo/swag v1.16.4/go.mod h1:VBsHJRsDvfYvqoiMKnsdwhNV9LEMHgEDZcyVYX0sxPg=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
@ -191,76 +158,42 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/arch v0.12.0 h1:UsYJhbzPYGsT0HbEdmYcqtCv8UNGvnaL561NnIUvaKg=
golang.org/x/arch v0.12.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/arch v0.13.0 h1:KCkqVVV1kGg0X87TFysjCJ8MxtZEIU4Ja/yXGeoECdA=
golang.org/x/arch v0.13.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
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/arch v0.16.0 h1:foMtLTdyOmIniqWCHjY6+JxuC54XP1fDwx4N0ASyW+U=
golang.org/x/arch v0.16.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE=
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.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
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=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376 h1:sY2a+y0j4iDrajJcorb+a0hJIQ6uakU5gybjfLWHlXo=
gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376/go.mod h1:BHKOc1m5wm8WwQkMqYBoo4vNxhmF7xg8+xhG8L+Cy3M=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -8,15 +8,10 @@
package request
import (
"strings"
"sync"
"git.zhangdeman.cn/zhangdeman/trace"
"git.zhangdeman.cn/zhangdeman/gin/define"
"git.zhangdeman.cn/zhangdeman/gin/request/parse_body"
"git.zhangdeman.cn/zhangdeman/wrapper"
"github.com/gin-gonic/gin"
"strings"
)
var (
@ -273,35 +268,3 @@ func (wh *wrapperHandle) ParseCookie(ctx *gin.Context) map[string]string {
}
return cookieData
}
// GetLogicAfterResponse ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:54 2025/2/28
func (wh *wrapperHandle) GetLogicAfterResponse(ctx *gin.Context) *define.LogicAfterResponse {
if nil == ctx || nil == ctx.Request {
return nil
}
l, exist := ctx.Get(define.LogicAfterResponseKey)
if !exist || nil == l {
l = &define.LogicAfterResponse{
SuccessHookFuncList: make([]func(), 0),
FailureHookFuncList: make([]func(), 0),
Lock: &sync.RWMutex{},
}
ctx.Set(define.LogicAfterResponseKey, l)
}
// 就这么写, key值如果被其他人覆盖成非法值, 此处会直接panic
return l.(*define.LogicAfterResponse)
}
// GetCustomContext 获取自定义context
func (wh *wrapperHandle) GetCustomContext(ctx *gin.Context) *define.Context {
return define.NewContext(ctx)
}
// GetTraceInstance 获取trace实例
func (wh *wrapperHandle) GetTraceInstance(ctx *gin.Context) *trace.Runtime {
return define.NewContext(ctx).Trace
}

View File

@ -37,9 +37,21 @@ func (c controller) Parse(inputController any) map[string]UriConfig {
return parseRes
}
controllerType := reflect.TypeOf(inputController)
inputController = reflect.New(controllerType).Interface()
controllerType = reflect.TypeOf(inputController)
controllerValue := reflect.ValueOf(inputController)
/*if controllerType.Kind() == reflect.Func {
// 直接函数注册
cfg, isNeedRegister := c.methodConfig(controllerType)
if isNeedRegister {
parseRes[cfg.Path] = cfg
}
return parseRes
}*/
if controllerType.Kind() == reflect.Ptr {
controllerValue = controllerValue.Elem()
}
/*if controllerValue.IsNil() {
return parseRes
}*/
for methodIdx := 0; methodIdx < controllerType.NumMethod(); methodIdx++ {
uriCfg, needRegister := c.methodConfig(controllerType.Method(methodIdx))
if !needRegister {
@ -69,26 +81,23 @@ func (c controller) methodConfig(reflectMethod reflect.Method) (cfg UriConfig, n
needRegister = false
return
}
// 第一个参数必须是 *gin.Context 或者 *define.Context
paramOne := methodType.In(1).String()
if paramOne != GinContextType && paramOne != CustomContextType {
// 第一个参数必须是 *gin.Context
if methodType.In(1).String() != GinContextType {
needRegister = false
return
}
// 解析第二个参数是组合Meta的form表单
formType := methodType.In(2)
cfg.FormDataType = formType
if formType.Kind() == reflect.Ptr {
formType = methodType.In(2).Elem()
}
cfg.FormDataType = formType
metaField, metaFieldExist := formType.FieldByName(FieldNameMeta)
if !metaFieldExist {
needRegister = false
return
}
cfg.ResultDataType = methodType.Out(0)
if cfg.ResultDataType == nil {
}
if methodType.Out(1).Kind().String() != ErrorType {
// 判断是否是实现 error接口的方法
outputErrParse := false
@ -107,7 +116,6 @@ func (c controller) methodConfig(reflectMethod reflect.Method) (cfg UriConfig, n
}
}
// 解析meta信息
cfg.CtxType = paramOne
cfg.Path = metaField.Tag.Get(TagNamePath)
cfg.RequestMethod = metaField.Tag.Get(TagNameMethod)
cfg.Desc = metaField.Tag.Get(TagNameDesc)
@ -123,7 +131,7 @@ func (c controller) methodConfig(reflectMethod reflect.Method) (cfg UriConfig, n
}
}
// 解析参数配置
//cfg.ParamList = c.parseParamConfig(formType)
cfg.ParamList = c.parseParamConfig(formType)
cfg.ApiLogicFunc = reflectMethod
needRegister = true
return
@ -146,7 +154,22 @@ func (c controller) parseParamConfig(formDataType reflect.Type) []UriParam {
if jsonTag == "" {
jsonTag = structField.Name
}
validate := strings.TrimSpace(structField.Tag.Get(TagNameBinding))
if len(validate) == 0 {
validate = strings.TrimSpace(structField.Tag.Get(TagNameValidate))
}
title := strings.TrimSpace(structField.Tag.Get(TagNameDesc))
if len(title) == 0 {
title = jsonTag
}
res = append(res, UriParam{
Field: structField.Name,
Name: jsonTag,
Title: title,
Type: structField.Type.String(),
Validate: validate,
ErrorMsg: "",
})
}
return res
}

View File

@ -7,15 +7,12 @@
// Date : 2024-07-20 22:57
package router
import (
"reflect"
)
import "reflect"
const (
PrefixFuncName = "RouterPrefix" // 路由前缀函数名称
MiddlewareFuncName = "RouterMiddleware" // 路由中间件函数名称
GinContextType = "*gin.Context" // gin context 类型名称
CustomContextType = "*define.Context" // custom context 类型名称
ErrorType = "error" // error类型
ErrorInterfaceFuncName = "Error" // error接口需要实现的方法名称
)
@ -24,7 +21,7 @@ const (
TagNamePath = "path" // 接口的请求路径
TagNameMethod = "method" // 接口的请求方法
TagNameUriTag = "tag" // 接口的tag
TagNameDesc = "desc" // 接口的描述
TagNameDesc = "desc" // 接口/接口参数的描述
TagNameOutputStrict = "output_strict" // 接口数据是否为严格模式 : 严格模式, 响应数据必须是结构体/map非严格模式返回任意值
TagNameBinding = "binding" // gin 内置的验证规则tag
TagNameValidate = "validate" // validator v10 默认的验证规则tag
@ -42,9 +39,8 @@ type UriConfig struct {
TagList []string `json:"tag_list"` // 接口分组
Desc string `json:"desc"` // 接口描述
OutputStrict bool `json:"output_strict"` // 接口是否为严格模式 : 不配置,可返回任意类型, 配置, 必须返回结构体或者map
CtxType string `json:"ctx_type"` // ctx参数类型
ParamList []UriParam `json:"param_list"` // 参数信息表
FormDataType reflect.Type `json:"-"` // 表单数据类型
ResultDataType reflect.Type `json:"-"` // 返回值数据类型
ApiStructValue reflect.Value `json:"-"` // 逻辑函数所属结构体取值
ApiLogicFunc reflect.Method `json:"-"` // 自定义的接口逻辑
}
@ -55,13 +51,12 @@ type UriConfig struct {
//
// Date : 15:40 2025/1/27
type UriParam struct {
Field string `json:"field"` // 结构体字段
Name string `json:"name"` // 参数名称
Type string `json:"type"` // 参数类型
Validate string `json:"validate"` // 验证规则: validator/v10 库
ErrorMsg string `json:"error_msg"` // 验证失败的错误信息
DisableAutoType bool `json:"disable_auto_type"` // 禁用自动类型转换
Sort string `json:"sort"` // 参数读取顺序: 默认 POST : body > query > path GET : query > path > body
Field string `json:"field"` // 结构体字段
Name string `json:"name"` // 参数名称
Title string `json:"title"` // 参数标题
Type string `json:"type"` // 参数类型
Validate string `json:"validate"` // 验证规则: validator/v10 库
ErrorMsg string `json:"error_msg"` // 验证失败的错误信息
}
const (

View File

@ -1,43 +0,0 @@
// Package router ...
//
// Description : router ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-02-14 21:48
package router
import (
"reflect"
apiDoc "git.zhangdeman.cn/gateway/api-doc"
"git.zhangdeman.cn/gateway/api-doc/define"
)
func NewDoc(info *define.Info, servers []*define.ServerItem) *Doc {
return &Doc{
instance: apiDoc.NewOpenapiDoc(info, servers),
}
}
type Doc struct {
instance *apiDoc.Generate
}
// Add 增加接口文档测试
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:55 2025/2/14
func (d *Doc) Add(routePrefix string, paramType reflect.Type, resultType reflect.Type) {
_ = d.instance.AddApiFromInAndOut(routePrefix, paramType, resultType)
}
// Data 文档数据
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:59 2025/2/14
func (d *Doc) Data() *define.OpenapiDoc {
return d.instance.Doc()
}

51
router/group.go Normal file
View File

@ -0,0 +1,51 @@
// Package router ...
//
// Description : router ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-01-27 19:33
package router
import (
"errors"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
// Group 注册接口路由
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 19:35 2025/1/27
func Group(router *gin.Engine, routerPrefix string, middlewareList []gin.HandlerFunc, cList ...any) error {
g := router.Group(routerPrefix)
g.Use(middlewareList...)
cParser := controller{}
for _, c := range cList {
urlTable := cParser.Parse(c)
for _, itemUriCfg := range urlTable {
method := strings.ToUpper(itemUriCfg.RequestMethod)
switch method {
case http.MethodGet:
g.GET(itemUriCfg.Path, RequestHandler(itemUriCfg))
case http.MethodHead:
g.HEAD(itemUriCfg.Path, RequestHandler(itemUriCfg))
case http.MethodPost:
g.POST(itemUriCfg.Path, RequestHandler(itemUriCfg))
case http.MethodPut:
g.PUT(itemUriCfg.Path, RequestHandler(itemUriCfg))
case http.MethodPatch:
g.PATCH(itemUriCfg.Path, RequestHandler(itemUriCfg))
case http.MethodDelete:
g.DELETE(itemUriCfg.Path, RequestHandler(itemUriCfg))
case http.MethodOptions:
g.OPTIONS(itemUriCfg.Path, RequestHandler(itemUriCfg))
case http.MethodTrace:
return errors.New(`method Trace is not supported`)
}
}
}
return nil
}

View File

@ -8,15 +8,11 @@
package router
import (
"errors"
"reflect"
"sync"
"git.zhangdeman.cn/zhangdeman/exception"
"git.zhangdeman.cn/zhangdeman/gin/define"
"git.zhangdeman.cn/zhangdeman/gin/request"
"git.zhangdeman.cn/zhangdeman/gin/response"
"github.com/gin-gonic/gin"
"reflect"
)
// RequestHandler 获取请求处理方法
@ -32,84 +28,35 @@ func RequestHandler(uriCfg UriConfig) gin.HandlerFunc {
e exception.IException
)
var formParam reflect.Value
if uriCfg.FormDataType.Kind() == reflect.Ptr {
formParam = reflect.New(uriCfg.FormDataType.Elem())
} else {
// 表单解析
formParam = reflect.New(uriCfg.FormDataType)
}
formValue := formParam.Interface()
if err = request.Form.Parse(ctx, formValue); nil != err {
formData := reflect.New(uriCfg.FormDataType).Interface()
// 表单解析
if err = request.Form.Parse(ctx, formData); nil != err {
// 格式化验证错误的信息
err = GetValidateErr(formValue, err)
err = GetValidateErr(formData, err)
e = exception.NewFromError(400, err)
response.SendWithException(ctx, e, nil)
ctx.Abort()
return
}
isSuccess := false
// 初始化响应之后logic
logicAfterResponse := &define.LogicAfterResponse{
SuccessHookFuncList: make([]func(), 0),
FailureHookFuncList: make([]func(), 0),
Lock: &sync.RWMutex{},
}
// 此处暴露出去,是为了使用方可以获取到对应数据
ctx.Set(define.LogicAfterResponseKey, logicAfterResponse)
defer func() {
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 {
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)
}
resList := uriCfg.ApiLogicFunc.Func.Call([]reflect.Value{uriCfg.ApiStructValue, firstParam, inputValue})
resList := uriCfg.ApiLogicFunc.Func.Call([]reflect.Value{uriCfg.ApiStructValue, reflect.ValueOf(ctx), reflect.ValueOf(formData)})
if resList[1].IsNil() {
// 请求成功
isSuccess = true
response.Success(ctx, resList[0].Interface())
return
}
// 请求失败
if ok = errors.As(resList[1].Interface().(error), &e); ok {
// 本身就是exception.IException
} else if err, ok = resList[1].Interface().(error); ok {
e = exception.NewFromError(-1, err)
} else {
e = exception.NewWithCodeAndData(-1, map[string]any{
"err": resList[1].Interface(),
})
if e, ok = resList[1].Interface().(exception.IException); ok {
response.SendWithException(ctx, e, nil)
return
}
if err, ok = resList[1].Interface().(error); ok {
e = exception.NewFromError(-1, err)
response.SendWithException(ctx, e, nil)
return
}
e = exception.NewWithCodeAndData(-1, map[string]any{
"err": resList[1].Interface(),
})
response.SendWithException(ctx, e, nil)
return
}

View File

@ -1,151 +0,0 @@
// Package router ...
//
// Description : router ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-02-18 17:26
package router
import (
"strings"
apiDocDefine "git.zhangdeman.cn/gateway/api-doc/define"
"git.zhangdeman.cn/zhangdeman/gin/middleware"
"github.com/gin-gonic/gin"
)
type SetServerOptionFunc func(so *serverOption)
// serverOption 获取server实例的选项
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:28 2025/2/18
type serverOption struct {
swaggerUiTheme string // swagger 主题
swaggerBaseUri string // swagger基础path
globalMiddlewareList []gin.HandlerFunc // 全局中间件列表
disableSwaggerDoc bool // 禁用swagger文档, 特定环境不想展示文档, 可通过次方式禁用
serverInfo *apiDocDefine.Info // 服务器信息
serverList []*apiDocDefine.ServerItem // 服务器环境列表
enablePprof bool // 启用pprof
enableCors bool // 启动跨域支持
loggerCfg *middleware.AccessConfig // 日志配置
}
// WithSwaggerUITheme 设置swaggerUI主题
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:29 2025/2/18
func WithSwaggerUITheme(uiTheme string) SetServerOptionFunc {
return func(so *serverOption) {
uiTheme = strings.TrimSpace(uiTheme)
if len(uiTheme) == 0 {
return
}
so.swaggerUiTheme = uiTheme
}
}
// WithGlobalMiddlewareList 设置全局中间件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:33 2025/2/18
func WithGlobalMiddlewareList(middlewareList ...gin.HandlerFunc) SetServerOptionFunc {
return func(so *serverOption) {
so.globalMiddlewareList = middlewareList
}
}
// WithSwaggerBaseUri ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:05 2025/2/18
func WithSwaggerBaseUri(baseUri string) SetServerOptionFunc {
return func(so *serverOption) {
baseUri = strings.TrimSpace(baseUri)
if len(baseUri) == 0 {
return
}
baseUri = "/" + strings.TrimLeft(baseUri, "/")
so.swaggerBaseUri = baseUri
}
}
// WithDisableSwaggerDoc 禁用swagger文档
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:35 2025/2/18
func WithDisableSwaggerDoc() SetServerOptionFunc {
return func(so *serverOption) {
so.disableSwaggerDoc = true
}
}
// WithServerInfo 设置serverInfo
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:51 2025/2/18
func WithServerInfo(serverInfo *apiDocDefine.Info) SetServerOptionFunc {
return func(so *serverOption) {
if nil == serverInfo {
return
}
so.serverInfo = serverInfo
}
}
// WithServerList 设置服务器列表
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:52 2025/2/18
func WithServerList(serverList []*apiDocDefine.ServerItem) SetServerOptionFunc {
return func(so *serverOption) {
if len(serverList) == 0 {
return
}
so.serverList = serverList
}
}
// WithPprofEnable 启用pprof
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:10 2025/2/21
func WithPprofEnable() SetServerOptionFunc {
return func(so *serverOption) {
so.enablePprof = true
}
}
// WithEnableCors 启用全局跨域
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:56 2025/2/22
func WithEnableCors() SetServerOptionFunc {
return func(so *serverOption) {
so.enableCors = true
}
}
// WithLoggerCfg ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:25 2025/2/22
func WithLoggerCfg(loggerCfg *middleware.AccessConfig) SetServerOptionFunc {
return func(so *serverOption) {
if nil != loggerCfg || nil != loggerCfg.Logger {
so.loggerCfg = loggerCfg
}
}
}

213
router/register.go Normal file
View File

@ -0,0 +1,213 @@
// Package router ...
//
// Description : router ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-07-20 21:39
package router
import (
"fmt"
"git.zhangdeman.cn/zhangdeman/exception"
"git.zhangdeman.cn/zhangdeman/gin/middleware"
"git.zhangdeman.cn/zhangdeman/gin/request"
"git.zhangdeman.cn/zhangdeman/gin/response"
"git.zhangdeman.cn/zhangdeman/wrapper"
"github.com/gin-gonic/gin"
"net/http"
"reflect"
"strings"
)
var (
Debug = false // 是否开启DEBUG
ginRouter = gin.Default()
)
func init() {
}
// Register 注册路由
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:40 2024/7/20
func Register(port int, controllerList ...any) error {
for _, controller := range controllerList {
if nil == controller {
// 忽略空指针
continue
}
parseController(controller)
}
return ginRouter.Run(fmt.Sprintf(":%d", port))
}
// parseController 解析controller
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 22:10 2024/7/20
func parseController(controller any) {
controllerType := reflect.TypeOf(controller)
controllerValue := reflect.ValueOf(controller)
routerPrefix := "/"
// 解析路由前缀函数
// routerPrefix 不能有任何入参, 并且只能有一个返回值,
// 返回值类型为字符串, 为具体路由前缀
routerPrefixFunc, routerPrefixFuncExist := controllerType.MethodByName(PrefixFuncName)
if routerPrefixFuncExist {
routerPrefixFuncType := routerPrefixFunc.Type
if routerPrefixFuncType.NumIn() == 1 && // 无任何入参, 正在没有如何入参情况下, 第一个参数是结构体指针
routerPrefixFuncType.NumOut() == 1 && // 只能有一个返回值
routerPrefixFuncType.Out(0).Kind() == reflect.String { // 返回值必须是字符串
routerPrefix = routerPrefixFunc.Func.Call([]reflect.Value{controllerValue})[0].String()
}
}
// 请求组的中间件
middlewareList := make([]gin.HandlerFunc, 0)
routerMiddlewareFunc, routerMiddlewareFuncExist := controllerType.MethodByName(MiddlewareFuncName)
if routerMiddlewareFuncExist {
routerMiddlewareFuncType := routerMiddlewareFunc.Type
if routerMiddlewareFuncType.NumIn() == 1 && // 无需任何参数
routerMiddlewareFuncType.NumOut() == 1 && // 只能有一个返回值
routerMiddlewareFuncType.Out(0).String() == "[]gin.HandlerFunc" { // 返回值必须是gin.HandlerFunc
res := routerMiddlewareFunc.Func.Call([]reflect.Value{controllerValue})
if !res[0].IsNil() {
middlewareList = res[0].Interface().([]gin.HandlerFunc)
}
}
}
for funcIdx := 0; funcIdx < controllerType.NumMethod(); funcIdx++ {
method := controllerType.Method(funcIdx)
if method.Name == PrefixFuncName || method.Name == MiddlewareFuncName {
continue
}
methodType := method.Type
uriConfig, err := parseUriConfig(methodType, routerPrefix)
if nil != err {
debugLog("parseUriConfig error : %s -> %s", err.Error(), methodType.Kind().String())
}
if nil == uriConfig {
continue
}
registerUri(uriConfig, controllerValue.Method(funcIdx), middlewareList)
}
}
// parseUriConfig 解析Uri配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:40 2024/7/21
func parseUriConfig(methodType reflect.Type, routerPrefix string) (*UriConfig, error) {
if methodType.NumIn() != 3 || // 结构体指针 + 两个参数
methodType.NumOut() != 2 { // 两个返回值
return nil, nil
}
// 接口logic共计两个参数. 两个返回值, 格式 : func(ctx *gin.Context, formData any[组合Meta]) (any[response], error)
// 解析第一个参数是 *gin.Context
if methodType.In(1).String() != "*gin.Context" {
return nil, nil
}
// 解析第二个参数是组合Meta的form表单
formType := methodType.In(2)
if formType.Kind() == reflect.Ptr {
formType = methodType.In(2).Elem()
}
metaField, metaFieldExist := formType.FieldByName(FieldNameMeta)
if !metaFieldExist {
return nil, nil
}
uriConfig := &UriConfig{
Path: strings.TrimRight(routerPrefix, "/") + "/" + strings.TrimLeft(metaField.Tag.Get(TagNamePath), "/"),
RequestMethod: strings.ToUpper(metaField.Tag.Get(TagNameMethod)),
TagList: strings.Split(metaField.Tag.Get(TagNameUriTag), "|"),
Desc: metaField.Tag.Get(TagNameDesc),
OutputStrict: wrapper.ArrayType([]string{"", "true"}).Has(strings.ToLower(metaField.Tag.Get(TagNameOutputStrict))) >= 0,
FormDataType: methodType.In(2).Elem(),
}
// 校验 FormDataType
for fieldIdx := 0; fieldIdx < uriConfig.FormDataType.NumField(); fieldIdx++ {
if uriConfig.FormDataType.Field(fieldIdx).Type.Kind() == reflect.Interface {
panic("request param set type `interface` is not allowed")
}
}
return uriConfig, nil
}
// registerUri 注册路由
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:00 2024/7/21
func registerUri(uriConfig *UriConfig, methodValue reflect.Value, middlewareList []gin.HandlerFunc) {
if nil == middlewareList {
middlewareList = make([]gin.HandlerFunc, 0)
}
handlerFunc := func(ctx *gin.Context) {
formDataReceiver := reflect.New(uriConfig.FormDataType)
if err := request.Form.Parse(ctx, formDataReceiver.Interface()); nil != err {
panic(err)
}
returnValue := methodValue.Call([]reflect.Value{reflect.ValueOf(ctx), formDataReceiver})
businessData := returnValue[0].Interface()
errData := returnValue[1]
if errData.IsNil() {
response.Success(ctx, businessData)
return
}
err := errData.Interface()
if e, ok := err.(exception.IException); ok {
response.SendWithException(ctx, e, map[string]any{"business_data": businessData})
return
} else {
response.SendWithException(ctx, exception.NewFromError(-1, errData.Interface().(error)), map[string]any{"business_data": businessData})
return
}
}
middlewareList = append(middlewareList, handlerFunc)
middlewareList = append([]gin.HandlerFunc{
middleware.InitRequest(),
}, middlewareList...)
switch uriConfig.RequestMethod {
case http.MethodGet:
ginRouter.GET(uriConfig.Path, middlewareList...)
case http.MethodHead:
ginRouter.HEAD(uriConfig.Path, middlewareList...)
case http.MethodPost:
ginRouter.PUT(uriConfig.Path, middlewareList...)
case http.MethodPut:
ginRouter.PUT(uriConfig.Path, middlewareList...)
case http.MethodPatch:
ginRouter.PATCH(uriConfig.Path, middlewareList...)
case http.MethodDelete:
ginRouter.DELETE(uriConfig.Path, middlewareList...)
case http.MethodConnect:
ginRouter.Handle(http.MethodConnect, uriConfig.Path, middlewareList...)
case http.MethodOptions:
ginRouter.OPTIONS(uriConfig.Path, middlewareList...)
case http.MethodTrace:
ginRouter.Handle(http.MethodTrace, uriConfig.Path, middlewareList...)
case "ANY":
ginRouter.Any(uriConfig.Path, middlewareList...)
default:
panic(uriConfig.Path + " : " + uriConfig.RequestMethod + " is not support")
}
}
// debugLog ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:32 2024/7/21
func debugLog(format string, valList ...any) {
if !Debug {
return
}
fmt.Printf("[DEBUG] "+format+"\n", valList...)
}

38
router/register_test.go Normal file
View File

@ -0,0 +1,38 @@
// Package router ...
//
// Description : router ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-07-20 23:24
package router
import (
"testing"
"github.com/gin-gonic/gin"
)
type TestController struct{}
func (t TestController) Logic(ctx *gin.Context, formData *TestForm) (any, error) {
return formData, nil
}
type TestForm struct {
Meta `tag:"测试表单" path:"/a/b/c/d" desc:"测试接口" method:"get"`
Age int `json:"age" form:"age" binding:"min=20" err_msg:"年龄不能小于20"`
Name string `json:"name" form:"name"`
Test *Test `json:"test" form:"test"`
Num *int64 `json:"num" form:"num"`
}
type Test struct {
L string `json:"l"`
}
func Test_parseController(t *testing.T) {
SetValidateErrTag("err_msg")
r := gin.Default()
Group(r, "test", nil, TestController{})
r.Run(":8080")
}

View File

@ -1,212 +0,0 @@
// Package router ...
//
// Description : router ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-02-07 18:19
package router
import (
"fmt"
"net/http"
"strings"
"git.zhangdeman.cn/zhangdeman/gin/define"
apiDoc "git.zhangdeman.cn/gateway/api-doc"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/gin/middleware"
"git.zhangdeman.cn/zhangdeman/gin/middleware/request_cors"
"github.com/gin-contrib/pprof"
apiDocDefine "git.zhangdeman.cn/gateway/api-doc/define"
"github.com/gin-gonic/gin"
)
func newServerOption(port int, optionList ...SetServerOptionFunc) *serverOption {
option := &serverOption{
swaggerUiTheme: apiDocDefine.SwaggerUIThemeRedocFree,
swaggerBaseUri: "/doc/swagger",
globalMiddlewareList: nil,
disableSwaggerDoc: false,
serverInfo: &apiDocDefine.Info{
Description: "这是一个微服务,提供一些必要的的数据接口功能",
Title: "微服务接口文档",
TermsOfService: "",
Contact: &apiDocDefine.Contact{
Name: "开发人员",
Url: "",
Email: "developer@example.com",
},
License: &apiDocDefine.License{
Name: consts.LicenseApache20,
Url: consts.LicenseUrlTable[consts.LicenseApache20],
},
Version: "0.0.1",
},
serverList: []*apiDocDefine.ServerItem{
{
Url: fmt.Sprintf("http://127.0.0.1:%d", port),
Description: "测试服务器",
Variables: nil,
},
},
}
for _, opt := range optionList {
if nil == opt {
continue
}
opt(option)
}
return option
}
// NewServer server实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:20 2025/2/7
func NewServer(port int, optionList ...SetServerOptionFunc) *server {
if port < 80 {
panic("port should be greater than 80")
}
option := newServerOption(port, optionList...)
globalMiddlewareList := make([]gin.HandlerFunc, 0)
// CustomContext 必须在第一个, 并且进行初始化
globalMiddlewareList = append(
globalMiddlewareList,
func(ctx *gin.Context) {
// 初始化上下文以及基础信息
_ = define.NewContext(ctx)
},
)
if nil != option.loggerCfg {
// 请求日志记录中间件
globalMiddlewareList = append(globalMiddlewareList, middleware.LogRequest(option.loggerCfg))
}
if option.enableCors {
// 跨域中间件
globalMiddlewareList = append(globalMiddlewareList, request_cors.New(request_cors.Config{
AllowAllOrigins: true,
AllowOrigins: nil,
AllowOriginFunc: nil,
AllowMethods: []string{"*"},
AllowHeaders: []string{"*"},
AllowCredentials: true,
ExposeHeaders: nil,
MaxAge: 0,
AllowWildcard: true,
AllowBrowserExtensions: true,
AllowWebSockets: true,
AllowFiles: true,
}))
}
if len(option.globalMiddlewareList) > 0 {
// 自定义全局中间件追加
globalMiddlewareList = append(globalMiddlewareList, option.globalMiddlewareList...)
}
r := gin.Default()
// 注册全局中间件
r.Use(globalMiddlewareList...)
// 启用pprof, 注册相关路由
if option.enablePprof {
pprof.Register(r)
}
return &server{
router: r,
uiInstance: apiDoc.NewSwaggerUI(option.serverInfo, option.serverList, option.swaggerUiTheme),
port: port,
option: option,
}
}
type server struct {
router *gin.Engine
port int
uiInstance *apiDoc.SwaggerUI
option *serverOption
}
// Start 启动服务
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:31 2025/2/7
func (s *server) Start() {
// 注册文档
s.uiInstance.RegisterHandler(s.router, s.option.swaggerBaseUri)
if err := s.router.Run(fmt.Sprintf(":%d", s.port)); err != nil {
panic("服务启动监听失败" + err.Error())
}
}
// Router 对外访问路由实例, 不建议直接用
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:35 2025/2/18
func (s *server) Router() *gin.Engine {
return s.router
}
// Handler404 注册404的处理方法
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:01 2025/2/22
func (s *server) Handler404(f gin.HandlerFunc) {
s.router.NoRoute(f)
}
// SetCustomRouter 自定义路由处理
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:09 2025/2/22
func (s *server) SetCustomRouter(f func(r *gin.Engine)) {
if nil == f {
return
}
f(s.router)
}
// Group 注册接口路由
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 19:35 2025/1/27
func (s *server) Group(routerPrefix string, middlewareList []gin.HandlerFunc, cList ...any) {
g := s.router.Group(routerPrefix)
g.Use(middlewareList...)
cParser := controller{}
for _, c := range cList {
urlTable := cParser.Parse(c)
for _, itemUriCfg := range urlTable {
_ = s.uiInstance.DocInstance().AddApiFromInAndOut(routerPrefix, itemUriCfg.FormDataType, itemUriCfg.ResultDataType)
method := strings.ToUpper(itemUriCfg.RequestMethod)
switch method {
case http.MethodGet:
g.GET(itemUriCfg.Path, RequestHandler(itemUriCfg))
case http.MethodHead:
g.HEAD(itemUriCfg.Path, RequestHandler(itemUriCfg))
case http.MethodPost:
g.POST(itemUriCfg.Path, RequestHandler(itemUriCfg))
case http.MethodPut:
g.PUT(itemUriCfg.Path, RequestHandler(itemUriCfg))
case http.MethodPatch:
g.PATCH(itemUriCfg.Path, RequestHandler(itemUriCfg))
case http.MethodDelete:
g.DELETE(itemUriCfg.Path, RequestHandler(itemUriCfg))
case http.MethodOptions:
g.OPTIONS(itemUriCfg.Path, RequestHandler(itemUriCfg))
case http.MethodTrace:
panic(`method Trace is not supported`)
default:
panic("method " + itemUriCfg.RequestMethod + " is not support")
}
}
}
}