Compare commits

..

13 Commits

15 changed files with 439 additions and 404 deletions

View File

@ -33,7 +33,6 @@ type HttpHandleConfig struct {
ResponseTraceIDField string
StartRequestTimeField string
FinishRequestTimeField string
RequestIsSuccessField string // 请求处理是否成功的标识
}
// ConvertDefaultConfig 覆盖默认配置
@ -107,10 +106,5 @@ func GetHttpHandleConfig() *HttpHandleConfig {
consts.GinRecordResponseDataField,
wrapper.String(inputHttpHandleConfig.RecordResponseDataField),
).Value(),
RequestIsSuccessField: wrapper.TernaryOperator.String(
nil == inputHttpHandleConfig || inputHttpHandleConfig.RequestIsSuccessField == "",
consts.GinRequestIsSuccessField,
wrapper.String(inputHttpHandleConfig.RecordResponseDataField),
).Value(),
}
}

32
go.mod
View File

@ -1,19 +1,17 @@
module git.zhangdeman.cn/zhangdeman/gin
go 1.21.0
go 1.21
toolchain go1.23.1
toolchain go1.21.5
require (
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240823041145-d4df71cf37e5
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240726024939-e424db29c5c4
git.zhangdeman.cn/zhangdeman/exception v0.0.0-20231105153815-e8561a060cc8
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20240725055115-98eb52ae307a
git.zhangdeman.cn/zhangdeman/network v0.0.0-20230925112156-f0eb86dd2442
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240823103024-c38d16dc28d3
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240813083016-da44ae07ab9b
github.com/gin-gonic/gin v1.10.0
github.com/go-playground/validator/v10 v10.22.1
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.9.0
github.com/go-playground/validator/v10 v10.22.0
go.uber.org/zap v1.27.0
)
@ -26,11 +24,10 @@ require (
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20240723075210-85feada512b2 // indirect
github.com/BurntSushi/toml v1.4.0 // indirect
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect
github.com/bytedance/sonic v1.12.2 // indirect
github.com/bytedance/sonic v1.12.1 // indirect
github.com/bytedance/sonic/loader v0.2.0 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 // indirect
github.com/gabriel-vasile/mimetype v1.4.5 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
@ -43,16 +40,15 @@ require (
github.com/klauspost/cpuid/v2 v2.2.8 // 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/lestrrat-go/strftime v1.0.6 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mcuadros/go-defaults v1.2.0 // 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.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/tidwall/gjson v1.17.3 // indirect
github.com/tidwall/match v1.1.1 // indirect
@ -60,11 +56,11 @@ require (
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.10.0 // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/net v0.29.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
golang.org/x/arch v0.9.0 // indirect
golang.org/x/crypto v0.26.0 // indirect
golang.org/x/net v0.28.0 // indirect
golang.org/x/sys v0.24.0 // indirect
golang.org/x/text v0.17.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect

44
go.sum
View File

@ -1,13 +1,5 @@
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240719075638-afb5d1d933ce h1:DH01rT/F/UNMqXm5HIv+Q2oKPSkg8rjy1TK8pE83rpU=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240719075638-afb5d1d933ce/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240723085016-ee0510753552 h1:SgxcaLXEXn3ImMOik9y3xDz82KwK/+9IhqV1kZbqIwQ=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240723085016-ee0510753552/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240726024939-e424db29c5c4 h1:mibnyzYbZullK0aTHVASHl3UeoVr8IgytQZsuyv+yEM=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240726024939-e424db29c5c4/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240817091513-491f455a23c0 h1:U12XDtyRrmsqb/wRvRZG9+SBKMCGFNADpiLogsp5POw=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240817091513-491f455a23c0/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240823041145-d4df71cf37e5 h1:pmIHln0gWW+5xAB762h3WDsRkZuYLUDndvJDsGMKoOY=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240823041145-d4df71cf37e5/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-20240311030808-e2a2e6a3c211 h1:I/wOsRpCSRkU9vo1u703slQsmK0wnNeZzsWQOGtIAG0=
@ -28,10 +20,10 @@ git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20240723075210-85feada512b2 h1:P2k
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20240723075210-85feada512b2/go.mod h1:7KaMpQmWgiNLpEkaV7oDtep7geI1f/VoCoPVcyvMjAE=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240627031706-9ff1c213bb50 h1:olo34i2Gq5gX7bYPv5TR4X5l5CrYFtu9UCElkYlmL2c=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240627031706-9ff1c213bb50/go.mod h1:US/pcq2vstE3iyxIHf53w8IeXKkZys7bj/ozLWkRYeE=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240806072320-3533617196fd h1:zcmfmp/1srHldFpa7BCH6Cpp9iVNFM/7W7DoxHp48UU=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240806072320-3533617196fd/go.mod h1:gnaF3v9/om6gaxFKeNVuKeFTYM61gHyW7vign7vrwyo=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240813083016-da44ae07ab9b h1:CcO2t7ssBSZwE7BDTOkCSgOvTGATarOZ0tajZ00McEc=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240813083016-da44ae07ab9b/go.mod h1:gnaF3v9/om6gaxFKeNVuKeFTYM61gHyW7vign7vrwyo=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240823103024-c38d16dc28d3 h1:RcWNxrHmhZksZWrP/HLEwAM8uIIHYlPLQ20HnLzC+j0=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240823103024-c38d16dc28d3/go.mod h1:KcojKP22mv9/IZrQWlIBfa1EuBxtEOqfWMgN3SYK2N8=
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/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
@ -40,8 +32,6 @@ github.com/bytedance/sonic v1.11.9 h1:LFHENlIY/SLzDWverzdOvgMztTxcfcF+cqNsz9pK5z
github.com/bytedance/sonic v1.11.9/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
github.com/bytedance/sonic v1.12.1 h1:jWl5Qz1fy7X1ioY74WqO0KjAMtAGQs4sYnjiEBiyX24=
github.com/bytedance/sonic v1.12.1/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
github.com/bytedance/sonic v1.12.2 h1:oaMFuRTpMHYLpCntGca65YWt5ny+wAceDERTkT2L9lg=
github.com/bytedance/sonic v1.12.2/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM=
@ -54,7 +44,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
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 v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
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.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I=
@ -75,36 +64,31 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
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/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
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/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
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/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.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
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/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA=
github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205AhTIGQQ=
github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw=
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/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=
github.com/mcuadros/go-defaults v1.2.0/go.mod h1:WEZtHEVIGYVDqkKSWBdWKUVdRyKlMfulPaGDWIVeCWY=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -116,11 +100,8 @@ 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/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
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/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=
@ -163,41 +144,30 @@ golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/arch v0.9.0 h1:ub9TgUInamJ8mrZIGlBG6/4TqWeMszd4N8lNorbrr6k=
golang.org/x/arch v0.9.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/arch v0.10.0 h1:S3huipmSclq3PJMNe76NGwkBR504WFkQ5dhzWzP8ZW8=
golang.org/x/arch v0.10.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
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.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
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,11 +8,10 @@
package middleware
import (
"strings"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/gin/request"
"go.uber.org/zap"
"strings"
"git.zhangdeman.cn/zhangdeman/gin/define"
@ -115,11 +114,7 @@ func LogRequest(cfg *AccessConfig) gin.HandlerFunc {
"response_body": request.WrapperHandle.GetResponseBody(ctx, handleConfig.ResponseDataField, map[string]any{}), // 响应body
"response_header": getLogResponseHeader(ctx, cfg), // 响应header
})
if ctx.GetBool(define.GetHttpHandleConfig().RequestIsSuccessField) {
cfg.Logger.Info("接口响应日志记录", logger.ZapLogDataList(logResponseData)...)
} else {
cfg.Logger.Error("接口响应日志记录", logger.ZapLogDataList(logResponseData)...)
}
cfg.Logger.Info("接口响应日志记录", logger.ZapLogDataList(logResponseData)...)
}
}

View File

@ -10,9 +10,7 @@ package request
import (
"bytes"
"errors"
"github.com/mcuadros/go-defaults"
"io"
"io/ioutil"
"net/http"
"strings"
@ -43,34 +41,28 @@ func (f *form) Parse(ctx *gin.Context, receiver interface{}) error {
// 请求信息写入上下文
ctx.Set(handleConfig.RecordRequestDataField, string(requestBody))
// 因为请求体被读一遍之后就没了,重新赋值 requestBody
ctx.Request.Body = ioutil.NopCloser(bytes.NewReader(requestBody))
ctx.Request.Body = io.NopCloser(bytes.NewReader(requestBody))
method := strings.ToUpper(ctx.Request.Method)
if method == http.MethodGet ||
method == http.MethodPatch ||
method == http.MethodTrace ||
method == http.MethodConnect ||
method == http.MethodOptions {
if err := ctx.ShouldBindQuery(receiver); nil != err {
return err
}
} else if method == http.MethodPost ||
return ctx.ShouldBindQuery(receiver)
}
if method == http.MethodPost ||
method == http.MethodPut ||
method == http.MethodDelete {
if ContentType.IsJson(ctx) {
if err := ctx.ShouldBindJSON(receiver); nil != err {
return err
}
} else if ContentType.IsFormURLEncoded(ctx) {
if err := ctx.ShouldBind(receiver); nil != err {
return err
}
} else {
return errors.New(ctx.ContentType() + " is not support")
return ctx.ShouldBindJSON(receiver)
}
} else {
return errors.New(method + " : request method is not support")
if ContentType.IsFormURLEncoded(ctx) {
return ctx.ShouldBind(receiver)
}
return errors.New(ctx.ContentType() + " is not support")
}
// 设置默认值
defaults.SetDefaults(receiver)
return nil
return errors.New(method + " : request method is not support")
}

View File

@ -121,18 +121,6 @@ func (wh *wrapperHandle) GetContentType(ctx *gin.Context, defaultVal string) str
return wrapper.TernaryOperator.String(len(contentType) > 0, wrapper.String(contentType), wrapper.String(defaultVal)).Value()
}
// GetDomain 获取请求Domain
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:12 2024/9/19
func (wh *wrapperHandle) GetDomain(ctx *gin.Context) string {
if nil == ctx {
return ""
}
return ctx.Request.Host
}
// GetRequestBody 获取请求body
//
// Author : go_developer@163.com<白茶清欢>

View File

@ -8,7 +8,6 @@
package response
import (
"fmt"
"net/http"
"time"
@ -22,26 +21,12 @@ const (
hasSendResponseFlag = "GIN_PKG_HAS_SEND_RESPONSE"
)
var (
// 成功的业务状态码
successBusinessCode any = "200"
)
// SetBusinessSuccessCode 设置成状态码
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:01 2024/8/17
func SetBusinessSuccessCode(code any) {
successBusinessCode = code
}
// Success 成功的响应
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 22:37 2022/6/25
func Success(ctx *gin.Context, data any) {
func Success(ctx *gin.Context, data interface{}) {
successException := exception.NewSuccess(data)
Send(ctx, successException.GetCode(), successException.GetHttpCode(), successException.GetData())
}
@ -51,23 +36,21 @@ func Success(ctx *gin.Context, data any) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 22:40 2022/6/25
func Send(ctx *gin.Context, code any, httpCode int, data any) {
// 设置请求是否成功的标识
ctx.Set(define.GetHttpHandleConfig().RequestIsSuccessField, fmt.Sprintf("%v", code) == fmt.Sprintf("%v", successBusinessCode))
func Send(ctx *gin.Context, code interface{}, httpCode int, data interface{}) {
if ctx.GetBool(hasSendResponseFlag) {
// 已经发送过数据, 后面在发送数据, 不执行
return
}
finishRequestTime := time.Now().UnixMilli()
// 设置数据已发送的标识
defer ctx.Set(hasSendResponseFlag, true)
responseConfig := define.GetHttpHandleConfig()
responseData := map[string]any{
finishRequestTime := time.Now().UnixMilli()
responseData := map[string]interface{}{
responseConfig.ResponseCodeField: code,
responseConfig.ResponseMessageField: exception.GetMessage(code),
responseConfig.ResponseTraceIDField: ctx.GetString(responseConfig.ResponseTraceIDField),
responseConfig.ResponseDataField: data,
responseConfig.HandleRequestCostField: finishRequestTime - ctx.GetInt64(responseConfig.StartRequestTimeField),
responseConfig.HandleRequestCostField: finishRequestTime - ctx.GetTime(responseConfig.StartRequestTimeField).UnixMilli(),
}
// 记录完成时间
ctx.Set(responseConfig.FinishRequestTimeField, finishRequestTime)
@ -81,7 +64,7 @@ func Send(ctx *gin.Context, code any, httpCode int, data any) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 22:41 2022/6/25
func SendWithStatusOK(ctx *gin.Context, code any, data any) {
func SendWithStatusOK(ctx *gin.Context, code interface{}, data interface{}) {
Send(ctx, code, http.StatusOK, data)
}
@ -90,11 +73,11 @@ func SendWithStatusOK(ctx *gin.Context, code any, data any) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 13:08 2022/6/26
func SendWithException(ctx *gin.Context, e exception.IException, data any) {
func SendWithException(ctx *gin.Context, e exception.IException, data interface{}) {
if nil == e {
e = exception.NewSuccess(data)
}
outputData := map[string]any{
outputData := map[string]interface{}{
"e_data": e.GetData(),
"u_e_data": data,
}
@ -106,7 +89,7 @@ func SendWithException(ctx *gin.Context, e exception.IException, data any) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:51 2023/2/15
func JSON(ctx *gin.Context, httpCode int, data any) {
func JSON(ctx *gin.Context, httpCode int, data interface{}) {
if ctx.GetBool(hasSendResponseFlag) {
// 已经发送过数据, 后面在发送数据, 不执行
return

110
router/README.md Normal file
View File

@ -0,0 +1,110 @@
# 路由包使用说明
## 基础说明
- 基于 [web框架GIN](https://github.com/gin-gonic/gin) 的二次封装
## 为什么要二次封装
二次封装的想法来源于 [web框架GoFrame](https://github.com/gogf/gf)。gf框架本身内置集成了大量组件, 对于轻量应用开发, 相比较而言比较笨重, 但是启根据请求数据结构、响应数据结构自动生成表单的能力十分实用。
在采用gin开发时一般接口文档有两种选择 :
- 在内部文档平台手搓文档, 并人工维护, 此方案最终演变方式大概率为文档主键滞后,与接口实现并不一致
- 利用golang的文档生成工具[swag]() 自动生成swagger文档, 此种方案需要在代码中引入大量swag工具解析时需要的注释, 且当输入/输出发生变化时需要维护相关注释
基于以上问题, 对gin的路由注册进行二次封装
## 二次封装解决哪些问题
- 文档维护的繁琐性 : 会通过反射自动基于 **`请求的数据结构 + 返回的数据结构`** , 生成接口文档, 专注于数据结构设计即可, 无需关注文档相关内容, 程序接管, 自动生成
- 做接口设计的统一性规范约束, 如 :
- 入参数据类型不能为 any
- 入参类型不能为 map , 但是特定字段特定场景, 可以强行禁用此规则等
- 返回值必须为结构体等
## 设计方案
### 【可选】路由组定义
路由组可以通过函数进行定义, 函数名必须需为 : **`RouterPrefix`** , 函数无任何参数, 返回路由组名称, 示例 :
```go
type TestController struct{}
func (t *TestController) RouterPrefix() string {
return "/uri/prefix"
}
```
### 【可选】路由组中间件定义
路由组中间件可以通过函数进行定义, 函数名必须需为 : **`RouterMiddleware`** , 函数无任何参数, 返回路由组中间件列表 **`[]gin.HandlerFunc`**, 示例 :
```go
type TestController struct{}
func (t *TestController) RouterPrefix() string {
return "/uri/prefix"
}
func (t *TestController) RouterMiddleware() []gin.HandlerFunc {
return []gin.HandlerFunc{
func(ctx *gin.Context) {
},
}
}
```
### 接口逻辑处理定义
接口逻辑处理函数, 函数名称自定义, 必须是个 **`可导出函数`** , 函数接收两个参数, 分别是 :
- *gin.Context : gin框架的上下文信息
- any: 表单参数 **结构体指针** , 注意 : 类型必须为结构体指针
函数返回值有两个 :
- any : 返回的业务数据, 必须是个 **`结构体指针`**
- error : 可以是内置的 **error** , 也可以是 **exception.IException** , 建议使用 exception.IException , 可承载更多的异常信息
## 使用方式
```go
type TestController struct{}
func (t *TestController) RouterPrefix() string {
return "/uri/prefix"
}
func (t *TestController) RouterMiddleware() []gin.HandlerFunc {
return []gin.HandlerFunc{
func(ctx *gin.Context) {
},
}
}
func (t *TestController) Uri(ctx *gin.Context, formData *TestForm) (any, error) {
return formData, nil
}
type TestForm struct {
Meta `tag:"测试表单" path:"/a/b/c/d" desc:"测试接口" method:"get" strict:"true"`
Age int `json:"age" form:"age"`
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) {
type args struct {
controller any
}
Register(8080, &TestController{})
}
```
注意事项:
- Register 方法第一个入参是监听的端口
- 后面若干个controller实例, 朱一必须以指针的方式传入

View File

@ -1,35 +0,0 @@
// Package router ...
//
// Description : 便捷的相关API处理
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-03-26 2:06 下午
package router
import (
"github.com/gin-gonic/gin"
)
// IApi 每一个接口的实现约束
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:08 下午 2021/3/26
type IApi interface {
// GetMethod 接口请求方法
GetMethod() string
// GetURI 接口URI
GetURI() string
// GetMiddleWareList 使用的中间件列表
GetMiddleWareList() []gin.HandlerFunc
// GetHandler 处理的handler
GetHandler() gin.HandlerFunc
}
// RegisterFunc 注册路由的函数
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:09 下午 2021/3/26
type RegisterFunc func() (method string, uri string, handlerFunc gin.HandlerFunc, middlewareList []gin.HandlerFunc)

37
router/define.go Normal file
View File

@ -0,0 +1,37 @@
// Package router ...
//
// Description : router ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-07-20 22:57
package router
import "reflect"
const (
PrefixFuncName = "RouterPrefix" // 路由前缀函数名称
MiddlewareFuncName = "RouterMiddleware" // 路由中间件函数名称
)
const (
TagNamePath = "path" // 接口的请求路径
TagNameMethod = "method" // 接口的请求方法
TagNameUriTag = "tag" // 接口的tag
TagNameDesc = "desc" // 接口的描述
TagNameStrict = "strict" // 接口是否为严格模式 : 不配置, 则为严格模式.严格模式 : POST 仅解析 BODY , GET 仅解析 QUERY
)
// UriConfig 接口配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:41 2024/7/21
type UriConfig struct {
Path string `json:"path"` // 接口路由, 必须配置
Method string `json:"method"` // 接口请求方法, 必须配置
TagList []string `json:"tag_list"` // 接口分组
Desc string `json:"desc"` // 接口描述
Strict bool `json:"strict"` // 接口是否为严格模式 : 不配置, 则为严格模式.严格模式 : POST 仅解析 BODY , GET 仅解析 QUERY
FormDataType reflect.Type `json:"-"` // 表单数据类型
}

15
router/meta.go Normal file
View File

@ -0,0 +1,15 @@
// Package router ...
//
// Description : router ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-07-20 21:40
package router
// Meta 接口的元信息
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:40 2024/7/20
type Meta struct{}

View File

@ -1,115 +1,213 @@
// Package router ...
//
// Description : 注册路由
// Description : router ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-03-26 2:13 下午
// Date : 2024-07-20 21:39
package router
import (
"log"
"reflect"
"github.com/pkg/errors"
"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 (
// DebugLogEnable 默认打开debug日志
DebugLogEnable = true
Debug = false // 是否开启DEBUG
ginRouter = gin.Default()
)
// DisableDebugLog 禁用debug日志
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:17 下午 2021/3/26
func DisableDebugLog() {
DebugLogEnable = false
func init() {
}
// RegisterRouter 注册一个路由
// Register 注册路由
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:14 下午 2021/3/26
func RegisterRouter(router *gin.Engine, apiInstanceList ...any) error {
for _, apiInstance := range apiInstanceList {
if nil == apiInstance {
// Date : 21:40 2024/7/20
func Register(port int, controllerList ...any) error {
for _, controller := range controllerList {
if nil == controller {
// 忽略空指针
continue
}
val := reflect.ValueOf(apiInstance)
switch val.Kind() {
case reflect.Struct:
fallthrough
case reflect.Ptr:
api, ok := apiInstance.(IApi)
if ok {
if err := HandleRegisterRouter(router, api.GetMethod(), api.GetURI(), api.GetHandler(), api.GetMiddleWareList()); nil != err {
routerLog(err.Error())
return err
}
continue
}
routerLog(val.String() + "结构体或者结构体指针, 自动识别函数是否包含RouterFunc")
// 不是IApi接口,自动识别函数列表 RouterFunc 函数自动注册
methodCnt := val.NumMethod()
for i := 0; i < methodCnt; i++ {
// TODO : 识别函数本身是不是 RouterFunc
af, o := val.Method(i).Interface().(func() (string, string, gin.HandlerFunc, []gin.HandlerFunc))
if o {
method, uri, handler, middlewareList := af()
if err := HandleRegisterRouter(router, method, uri, handler, middlewareList); nil != err {
routerLog(err.Error())
return err
}
continue
}
apiFuncList := val.Method(i).Call(nil)
for _, apiFuncVal := range apiFuncList {
apiFunc, ok := apiFuncVal.Interface().(RegisterFunc)
if !ok {
continue
}
method, uri, handler, middlewareList := apiFunc()
if err := HandleRegisterRouter(router, method, uri, handler, middlewareList); nil != err {
routerLog(err.Error())
return err
}
}
}
case reflect.Func:
api, ok := apiInstance.(RegisterFunc)
if !ok {
err := errors.New("函数方式注册路由必须是 RouterFunc")
routerLog(err.Error())
return err
}
method, uri, handler, middlewareList := api()
if err := HandleRegisterRouter(router, method, uri, handler, middlewareList); nil != err {
routerLog(err.Error())
return err
}
default:
err := errors.New("注册的路由必须是 IApi 或者 RouterFunc 或者 包含 RouterFunc 的结构体")
routerLog(err.Error())
return err
}
parseController(controller)
}
return nil
return ginRouter.Run(fmt.Sprintf(":%d", port))
}
// routerLog 记录日志
// parseController 解析controller
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:28 下午 2021/3/26
func routerLog(msg string) {
if !DebugLogEnable || len(msg) == 0 {
// 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("Meta")
if !metaFieldExist {
return nil, nil
}
uriConfig := &UriConfig{
Path: strings.TrimRight(routerPrefix, "/") + "/" + strings.TrimLeft(metaField.Tag.Get(TagNamePath), "/"),
Method: strings.ToUpper(metaField.Tag.Get(TagNameMethod)),
TagList: strings.Split(metaField.Tag.Get(TagNameUriTag), "|"),
Desc: metaField.Tag.Get(TagNameDesc),
Strict: wrapper.ArrayType([]string{"", "true"}).Has(strings.ToLower(metaField.Tag.Get(TagNameStrict))) >= 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, businessData)
return
} else {
response.SendWithException(ctx, exception.NewFromError(-1, errData.Interface().(error)), businessData)
return
}
}
middlewareList = append(middlewareList, handlerFunc)
middlewareList = append([]gin.HandlerFunc{
middleware.InitRequest(),
}, middlewareList...)
switch uriConfig.Method {
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.Method + " is not support")
}
}
// debugLog ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:32 2024/7/21
func debugLog(format string, valList ...any) {
if !Debug {
return
}
log.Print(msg)
fmt.Printf("[DEBUG] "+format+"\n", valList...)
}

View File

@ -1,78 +0,0 @@
// Package router ...
//
// Description : 路由注册单元测试
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-03-26 3:49 下午
package router
import (
"net/http"
"testing"
"github.com/stretchr/testify/assert"
"github.com/gin-gonic/gin"
)
// TestRegisterRouter ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:50 下午 2021/3/26
func TestRegisterRouter(t *testing.T) {
r := gin.Default()
err := RegisterRouter(r, demoApiFunc(), &demoApi{}, &otherApi{}, nil)
assert.Nil(t, err, "路由注册异常 : %v", err)
}
func demoApiFunc() RouterFunc {
return func() (method string, uri string, handlerFunc gin.HandlerFunc, middlewareList []gin.HandlerFunc) {
return http.MethodGet, "/api/func/test", func(context *gin.Context) {
}, nil
}
}
type demoApi struct {
}
func (d demoApi) GetMethod() string {
return http.MethodGet
}
func (d demoApi) GetURI() string {
return "/api/struct/test"
}
func (d demoApi) GetMiddleWareList() []gin.HandlerFunc {
return nil
}
func (d demoApi) GetHandler() gin.HandlerFunc {
return func(context *gin.Context) {
}
}
type otherApi struct {
}
func (oa *otherApi) DemoApiFunc() RouterFunc {
return func() (method string, uri string, handlerFunc gin.HandlerFunc, middlewareList []gin.HandlerFunc) {
return http.MethodGet, "/api/other/test", func(context *gin.Context) {
}, nil
}
}
func (oa *otherApi) Lala() {
}
func (oa *otherApi) SelfApi() (method string, uri string, handlerFunc gin.HandlerFunc, middlewareList []gin.HandlerFunc) {
return http.MethodGet, "/api/other/self/test", func(context *gin.Context) {
}, nil
}

49
router/register_test.go Normal file
View File

@ -0,0 +1,49 @@
// 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) RouterPrefix() string {
return "/uri/prefix"
}
func (t *TestController) RouterMiddleware() []gin.HandlerFunc {
return []gin.HandlerFunc{
func(ctx *gin.Context) {
},
}
}
func (t *TestController) Uri(ctx *gin.Context, formData *TestForm) (any, error) {
return formData, nil
}
type TestForm struct {
Meta `tag:"测试表单" path:"/a/b/c/d" desc:"测试接口" method:"get" strict:"true"`
Age int `json:"age" form:"age"`
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) {
type args struct {
controller any
}
Register(8080, &TestController{})
}

View File

@ -1,79 +0,0 @@
// Package router ...
//
// Description : router ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2023-03-03 16:48
package router
import (
"fmt"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// HandleRegisterRouter 注册gin路由
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:36 下午 2021/3/9
func HandleRegisterRouter(router *gin.Engine, method string, uri string, handler gin.HandlerFunc, middlewareList []gin.HandlerFunc) error {
if nil == middlewareList {
middlewareList = make([]gin.HandlerFunc, 0)
}
switch strings.ToUpper(method) {
case http.MethodGet:
router.GET(uri, handler).Use(middlewareList...)
case http.MethodPost:
router.POST(uri, handler).Use(middlewareList...)
case http.MethodDelete:
router.DELETE(uri, handler).Use(middlewareList...)
case http.MethodHead:
router.HEAD(uri, handler).Use(middlewareList...)
case http.MethodOptions:
router.OPTIONS(uri, handler).Use(middlewareList...)
case http.MethodPatch:
router.PATCH(uri, handler).Use(middlewareList...)
case http.MethodPut:
router.PUT(uri, handler).Use(middlewareList...)
case "ANY": // 一次性注册全部请求方法的路由
router.Any(uri, handler).Use(middlewareList...)
default:
// 不是一个函数,数名method配置错误
return fmt.Errorf("uri=%s method=%s 请求方法配置错误", uri, method)
}
return nil
}
// RegisterRouterGroup 注册gin路由
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:36 下午 2021/3/9
func RegisterRouterGroup(router *gin.RouterGroup, method string, uri string, handler gin.HandlerFunc) error {
switch strings.ToUpper(method) {
case http.MethodGet:
router.GET(uri, handler)
case http.MethodPost:
router.POST(uri, handler)
case http.MethodDelete:
router.DELETE(uri, handler)
case http.MethodHead:
router.HEAD(uri, handler)
case http.MethodOptions:
router.OPTIONS(uri, handler)
case http.MethodPatch:
router.PATCH(uri, handler)
case http.MethodPut:
router.PUT(uri, handler)
case "ANY": // 一次性注册全部请求方法的路由
router.Any(uri, handler)
default:
// 不是一个函数,数名method配置错误
return fmt.Errorf("uri=%s method=%s 请求方法配置错误", uri, method)
}
return nil
}