Compare commits
10 Commits
bb5d97f6eb
...
feature/up
Author | SHA1 | Date | |
---|---|---|---|
ab78127317 | |||
28da213bb8 | |||
13d1ab6607 | |||
2fd9195b77 | |||
c826166256 | |||
84f0e1a4f6 | |||
9ae310782b | |||
0d981b32c6 | |||
9decd12ee8 | |||
b95d464c89 |
12
define/request.go
Normal file
12
define/request.go
Normal file
@ -0,0 +1,12 @@
|
||||
// Package define ...
|
||||
//
|
||||
// Description : define ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2025-03-10 14:38
|
||||
package define
|
||||
|
||||
const (
|
||||
GinWrapperContextKey = "GIN_WRAPPER_CONTEXT"
|
||||
)
|
@ -10,6 +10,7 @@ package define
|
||||
import (
|
||||
"git.zhangdeman.cn/zhangdeman/consts"
|
||||
"git.zhangdeman.cn/zhangdeman/wrapper"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -124,3 +125,24 @@ 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)
|
||||
}
|
||||
|
4
go.mod
4
go.mod
@ -11,7 +11,9 @@ require (
|
||||
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20241125083316-eab7bab9d7ad
|
||||
git.zhangdeman.cn/zhangdeman/network v0.0.0-20230925112156-f0eb86dd2442
|
||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd
|
||||
git.zhangdeman.cn/zhangdeman/trace v0.0.0-20231220041950-807f3d74a6fa
|
||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250124091620-c757e551a8c9
|
||||
github.com/gin-contrib/pprof v1.5.2
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/go-playground/validator/v10 v10.25.0
|
||||
github.com/mcuadros/go-defaults v1.2.0
|
||||
@ -23,7 +25,6 @@ require (
|
||||
git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda // indirect
|
||||
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4 // indirect
|
||||
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 // indirect
|
||||
git.zhangdeman.cn/zhangdeman/trace v0.0.0-20231220041950-807f3d74a6fa // indirect
|
||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e // indirect
|
||||
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20241125101541-c5ea194c9c1e // indirect
|
||||
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||
@ -34,7 +35,6 @@ require (
|
||||
github.com/cloudwego/base64x v0.1.5 // indirect
|
||||
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/gin-contrib/pprof v1.5.2 // indirect
|
||||
github.com/gin-contrib/sse v1.0.0 // indirect
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
|
12
go.sum
12
go.sum
@ -1,13 +1,5 @@
|
||||
git.zhangdeman.cn/gateway/api-doc v0.0.0-20250219142545-bd7f6d2cfd99 h1:VYwbWsMcgQ7yWAGHB2v8Zbhh/5NIcQUq3yxay09zjkY=
|
||||
git.zhangdeman.cn/gateway/api-doc v0.0.0-20250219142545-bd7f6d2cfd99/go.mod h1:oNTwnepzW09RNfIQCpgmbiayTKLvGx2XP92esfkxv98=
|
||||
git.zhangdeman.cn/gateway/api-doc v0.0.0-20250220082250-6987b4829bf6 h1:C8otP/n4SPc8hQQxd9jOnPxb24l0KMhTNpxWtwz20js=
|
||||
git.zhangdeman.cn/gateway/api-doc v0.0.0-20250220082250-6987b4829bf6/go.mod h1:oNTwnepzW09RNfIQCpgmbiayTKLvGx2XP92esfkxv98=
|
||||
git.zhangdeman.cn/gateway/api-doc v0.0.0-20250220095851-22d937a4b1cb h1:E+KXP29m18dNfyVU8zBIBAEqE7aspLqFHa1bOnIMdq4=
|
||||
git.zhangdeman.cn/gateway/api-doc v0.0.0-20250220095851-22d937a4b1cb/go.mod h1:oNTwnepzW09RNfIQCpgmbiayTKLvGx2XP92esfkxv98=
|
||||
git.zhangdeman.cn/gateway/api-doc v0.0.0-20250220105101-71d6db967dc5 h1:UV2+nD9HQLbRt+vY98gwPtkd+M8fbfffl7nb4Mkymmc=
|
||||
git.zhangdeman.cn/gateway/api-doc v0.0.0-20250220105101-71d6db967dc5/go.mod h1:oNTwnepzW09RNfIQCpgmbiayTKLvGx2XP92esfkxv98=
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250215141718-8232f587a6ea h1:6b9bfq44ewsXGVOkyZ+DQ4dNaKtmNsdHOFQxHUdEQrY=
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250215141718-8232f587a6ea/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250227040546-863c03f34bb8 h1:VEifPc+vkpEQoX9rj7zxmT1m+IA81XjOxe7+Z1aqWNM=
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250227040546-863c03f34bb8/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
|
||||
git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda h1:bMD6r9gjRy7cO+T4zRQVYAesgIblBdTnhzT1vN5wjvI=
|
||||
@ -97,8 +89,6 @@ github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFF
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
|
||||
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
@ -188,8 +178,6 @@ golang.org/x/arch v0.14.0 h1:z9JUEZWr8x4rR0OU6c4/4t6E6jOZ8/QBS2bBYBm4tx4=
|
||||
golang.org/x/arch v0.14.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
|
||||
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
||||
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
||||
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
|
@ -10,9 +10,9 @@ package request
|
||||
import (
|
||||
"fmt"
|
||||
networkUtil "git.zhangdeman.cn/zhangdeman/network/util"
|
||||
"git.zhangdeman.cn/zhangdeman/trace"
|
||||
"git.zhangdeman.cn/zhangdeman/wrapper"
|
||||
"github.com/gin-gonic/gin"
|
||||
"git.zhangdeman.cn/zhangdeman/trace"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -63,13 +63,16 @@ func getRequestID(ctx *gin.Context, traceID string) string {
|
||||
func NewContext(ginContext *gin.Context) *Context {
|
||||
// 生成traceID
|
||||
traceID := getRequestID(ginContext, "")
|
||||
hostname, _ := os.Hostname()
|
||||
return &Context{
|
||||
Context: ginContext,
|
||||
StartRequestTime: time.Now(),
|
||||
FinishRequestTime: time.Time(int64(0)),
|
||||
FinishRequestTime: time.Unix(0, 0),
|
||||
HandlerAfterResponse: make([]gin.HandlerFunc, 0),
|
||||
CustomData: make(map[string]any),
|
||||
lock: &sync.RWMutex{},
|
||||
customData: make(map[string]any),
|
||||
Hostname: hostname,
|
||||
HostIp: networkUtil.IP.GetHostIP(),
|
||||
customLock: &sync.RWMutex{},
|
||||
TraceID: traceID,
|
||||
Trace: trace.NewRuntime(traceID, 0),
|
||||
}
|
||||
@ -82,14 +85,16 @@ func NewContext(ginContext *gin.Context) *Context {
|
||||
// Date : 11:45 2025/2/28
|
||||
type Context struct {
|
||||
*gin.Context `json:"-"`
|
||||
StartRequestTime time.Time // 开始请求时间(全局)
|
||||
FinishRequestTime time.Time // 结束请求时间(全局)
|
||||
TraceID string `json:"trace_id"` // 请求trace_id
|
||||
ParentAppName string `json:"parent_app_name"` // 父级应用名称
|
||||
HandlerAfterResponse []gin.HandlerFunc `json:"-"` // 响应数据之后需要执行的逻辑
|
||||
CustomData map[string]any // 业务上下文自定义数据, 可以合 ginCtx.Value 作区分
|
||||
lock *sync.RWMutex
|
||||
Trace *trace.Runtime `json:"-"` // 追踪实例
|
||||
StartRequestTime time.Time `json:"start_request_time"` // 开始请求时间(全局)
|
||||
FinishRequestTime time.Time `json:"finish_request_time"` // 结束请求时间(全局)
|
||||
TraceID string `json:"trace_id"` // 请求trace_id
|
||||
ParentAppName string `json:"parent_app_name"` // 父级应用名称
|
||||
HandlerAfterResponse []gin.HandlerFunc `json:"-"` // 响应数据之后需要执行的逻辑
|
||||
Hostname string `json:"hostname"` // 服务器名称
|
||||
HostIp string `json:"host_ip"` // 服务器IP
|
||||
customData map[string]any `json:"-"` // 业务上下文自定义数据, 可以合 ginCtx.Value 作区分
|
||||
customLock *sync.RWMutex `json:"-"` // 数据锁
|
||||
Trace *trace.Runtime `json:"-"` // 追踪实例
|
||||
}
|
||||
|
||||
// SetCustom 设置数据
|
||||
@ -98,79 +103,80 @@ type Context struct {
|
||||
//
|
||||
// Date : 11:58 2025/2/28
|
||||
func (ctx *Context) SetCustom(key string, val any) {
|
||||
ctx.lock.Lock()
|
||||
defer ctx.lock.Unlock()
|
||||
if nil == ctx.CustomData {
|
||||
ctx.CustomData = make(map[string]any)
|
||||
ctx.customLock.Lock()
|
||||
defer ctx.customLock.Unlock()
|
||||
if nil == ctx.customData {
|
||||
ctx.customData = make(map[string]any)
|
||||
}
|
||||
ctx.CustomData[key] = val
|
||||
ctx.Set(key, val)
|
||||
ctx.customData[key] = val
|
||||
}
|
||||
|
||||
// CustomDataValue 获取customData
|
||||
// customDataValue 获取customData
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:03 2025/2/28
|
||||
func (ctx *Context) CustomDataValue(key string) any {
|
||||
ctx.lock.RLock()
|
||||
defer ctx.lock.RUnlock()
|
||||
if val, exist := ctx.CustomData[key]; exist {
|
||||
func (ctx *Context) customDataValue(key string) any {
|
||||
ctx.customLock.RLock()
|
||||
defer ctx.customLock.RUnlock()
|
||||
if val, exist := ctx.customData[key]; exist {
|
||||
return val
|
||||
} else {
|
||||
return nil
|
||||
return ctx.Value(key)
|
||||
}
|
||||
}
|
||||
|
||||
// CustomDataExist 判断
|
||||
// customDataExist 判断
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:04 2025/2/28
|
||||
func (ctx *Context) CustomDataExist(key string) any {
|
||||
ctx.lock.RLock()
|
||||
defer ctx.lock.RUnlock()
|
||||
_, exist := ctx.CustomData[key]
|
||||
func (ctx *Context) customDataExist(key string) any {
|
||||
ctx.customLock.RLock()
|
||||
defer ctx.customLock.RUnlock()
|
||||
_, exist := ctx.customData[key]
|
||||
return exist
|
||||
}
|
||||
|
||||
// CustomDataAppend 向数组数据中追加元素
|
||||
// customDataAppend 向数组数据中追加元素
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:07 2025/2/28
|
||||
func (ctx *Context) CustomDataAppend(key string, appendValue any) {
|
||||
ctx.lock.Lock()
|
||||
defer ctx.lock.Unlock()
|
||||
val, exist := ctx.CustomData[key]
|
||||
func (ctx *Context) customDataAppend(key string, appendValue any) {
|
||||
ctx.customLock.Lock()
|
||||
defer ctx.customLock.Unlock()
|
||||
val, exist := ctx.customData[key]
|
||||
if !exist || nil == val {
|
||||
ctx.CustomData[key] = []any{appendValue}
|
||||
ctx.customData[key] = []any{appendValue}
|
||||
return
|
||||
}
|
||||
if valArr, ok := val.([]any); ok {
|
||||
valArr = append(valArr, appendValue)
|
||||
ctx.CustomData[key] = valArr
|
||||
ctx.customData[key] = valArr
|
||||
}
|
||||
// 非数组, 忽略追加行为
|
||||
}
|
||||
|
||||
// CustomDataAppendProperty 向一个map中追加/更新属性
|
||||
// customDataAppendProperty 向一个map中追加/更新属性
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:11 2025/2/28
|
||||
func (ctx *Context) CustomDataAppendProperty(key string, appendKey string, appendValue any) {
|
||||
ctx.lock.Lock()
|
||||
defer ctx.lock.Unlock()
|
||||
val, exist := ctx.CustomData[key]
|
||||
func (ctx *Context) customDataAppendProperty(key string, appendKey string, appendValue any) {
|
||||
ctx.customLock.Lock()
|
||||
defer ctx.customLock.Unlock()
|
||||
val, exist := ctx.customData[key]
|
||||
if !exist || nil == val {
|
||||
ctx.CustomData[key] = map[string]any{
|
||||
ctx.customData[key] = map[string]any{
|
||||
appendKey: appendValue,
|
||||
}
|
||||
return
|
||||
}
|
||||
if valMap, ok := val.(map[string]any); ok {
|
||||
valMap[appendKey] = appendValue
|
||||
ctx.CustomData[key] = valMap
|
||||
ctx.customData[key] = valMap
|
||||
}
|
||||
// 非map, 忽略追加行为
|
||||
}
|
||||
|
@ -8,10 +8,12 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"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"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -302,3 +304,43 @@ func (wh *wrapperHandle) Copy(ctx *gin.Context, isCopyContextValue bool, exclude
|
||||
}
|
||||
return newContext
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// GetGinWrapperContext 获取包装之后context
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 14:41 2025/3/10
|
||||
func (wh *wrapperHandle) GetGinWrapperContext(ctx *gin.Context) *Context {
|
||||
if nil == ctx {
|
||||
return nil
|
||||
}
|
||||
if val, exist := ctx.Get(define.GinWrapperContextKey); !exist || nil == val {
|
||||
newCtx := NewContext(ctx)
|
||||
newCtx.SetCustom(define.GinWrapperContextKey, newCtx)
|
||||
return newCtx
|
||||
} else {
|
||||
return val.(*Context)
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,8 @@ func (c controller) methodConfig(reflectMethod reflect.Method) (cfg UriConfig, n
|
||||
return
|
||||
}
|
||||
// 第一个参数必须是 *gin.Context
|
||||
if methodType.In(1).String() != GinContextType {
|
||||
firstParamStr := methodType.In(1).String()
|
||||
if firstParamStr != GinContextType && firstParamStr != GinWrapperContextType {
|
||||
needRegister = false
|
||||
return
|
||||
}
|
||||
@ -105,6 +106,8 @@ func (c controller) methodConfig(reflectMethod reflect.Method) (cfg UriConfig, n
|
||||
return
|
||||
}
|
||||
}
|
||||
// 是否gin包装后的context
|
||||
cfg.IsGinWrapperContext = firstParamStr == GinWrapperContextType
|
||||
// 解析meta信息
|
||||
cfg.Path = metaField.Tag.Get(TagNamePath)
|
||||
cfg.RequestMethod = metaField.Tag.Get(TagNameMethod)
|
||||
|
@ -7,12 +7,15 @@
|
||||
// Date : 2024-07-20 22:57
|
||||
package router
|
||||
|
||||
import "reflect"
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
const (
|
||||
PrefixFuncName = "RouterPrefix" // 路由前缀函数名称
|
||||
MiddlewareFuncName = "RouterMiddleware" // 路由中间件函数名称
|
||||
GinContextType = "*gin.Context" // gin context 类型名称
|
||||
GinWrapperContextType = "*request.Context" // gin context 类型名称
|
||||
ErrorType = "error" // error类型
|
||||
ErrorInterfaceFuncName = "Error" // error接口需要实现的方法名称
|
||||
)
|
||||
@ -34,15 +37,16 @@ const (
|
||||
//
|
||||
// Date : 15:41 2024/7/21
|
||||
type UriConfig struct {
|
||||
Path string `json:"path"` // 接口路由, 必须配置
|
||||
RequestMethod string `json:"request_method"` // 接口请求方法, 必须配置
|
||||
TagList []string `json:"tag_list"` // 接口分组
|
||||
Desc string `json:"desc"` // 接口描述
|
||||
OutputStrict bool `json:"output_strict"` // 接口是否为严格模式 : 不配置,可返回任意类型, 配置, 必须返回结构体或者map
|
||||
FormDataType reflect.Type `json:"-"` // 表单数据类型
|
||||
ResultDataType reflect.Type `json:"-"` // 返回值数据类型
|
||||
ApiStructValue reflect.Value `json:"-"` // 逻辑函数所属结构体取值
|
||||
ApiLogicFunc reflect.Method `json:"-"` // 自定义的接口逻辑
|
||||
Path string `json:"path"` // 接口路由, 必须配置
|
||||
RequestMethod string `json:"request_method"` // 接口请求方法, 必须配置
|
||||
TagList []string `json:"tag_list"` // 接口分组
|
||||
Desc string `json:"desc"` // 接口描述
|
||||
OutputStrict bool `json:"output_strict"` // 接口是否为严格模式 : 不配置,可返回任意类型, 配置, 必须返回结构体或者map
|
||||
FormDataType reflect.Type `json:"-"` // 表单数据类型
|
||||
ResultDataType reflect.Type `json:"-"` // 返回值数据类型
|
||||
ApiStructValue reflect.Value `json:"-"` // 逻辑函数所属结构体取值
|
||||
ApiLogicFunc reflect.Method `json:"-"` // 自定义的接口逻辑
|
||||
IsGinWrapperContext bool `json:"is_gin_wrapper_context"` // 是否gin包装后的context
|
||||
}
|
||||
|
||||
// UriParam 接口参数配置
|
||||
|
@ -9,10 +9,12 @@ package router
|
||||
|
||||
import (
|
||||
"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"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// RequestHandler 获取请求处理方法
|
||||
@ -45,30 +47,62 @@ func RequestHandler(uriCfg UriConfig) gin.HandlerFunc {
|
||||
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 recover()
|
||||
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()
|
||||
}
|
||||
resList := uriCfg.ApiLogicFunc.Func.Call([]reflect.Value{uriCfg.ApiStructValue, reflect.ValueOf(ctx), inputValue})
|
||||
ginWrapperContext := request.NewContext(ctx)
|
||||
// wrapper context 设置到 gin context
|
||||
ginWrapperContext.Set(define.GinWrapperContextKey, ginWrapperContext)
|
||||
ctxReflect := reflect.ValueOf(ctx)
|
||||
if uriCfg.IsGinWrapperContext {
|
||||
ctxReflect = reflect.ValueOf(ginWrapperContext)
|
||||
}
|
||||
resList := uriCfg.ApiLogicFunc.Func.Call([]reflect.Value{uriCfg.ApiStructValue, ctxReflect, inputValue})
|
||||
if resList[1].IsNil() {
|
||||
// 请求成功
|
||||
isSuccess = true
|
||||
response.Success(ctx, resList[0].Interface())
|
||||
return
|
||||
}
|
||||
// 请求失败
|
||||
if e, ok = resList[1].Interface().(exception.IException); ok {
|
||||
response.SendWithException(ctx, e, nil)
|
||||
return
|
||||
}
|
||||
if err, ok = resList[1].Interface().(error); ok {
|
||||
// 本身就是exception.IException
|
||||
} else if err, ok = resList[1].Interface().(error); ok {
|
||||
e = exception.NewFromError(-1, err)
|
||||
response.SendWithException(ctx, e, nil)
|
||||
return
|
||||
} else {
|
||||
e = exception.NewWithCodeAndData(-1, map[string]any{
|
||||
"err": resList[1].Interface(),
|
||||
})
|
||||
}
|
||||
e = exception.NewWithCodeAndData(-1, map[string]any{
|
||||
"err": resList[1].Interface(),
|
||||
})
|
||||
response.SendWithException(ctx, e, nil)
|
||||
return
|
||||
}
|
||||
|
@ -109,8 +109,9 @@ func parseUriConfig(methodType reflect.Type, routerPrefix string) (*UriConfig, e
|
||||
}
|
||||
// 接口logic共计两个参数. 两个返回值, 格式 : func(ctx *gin.Context, formData any[组合Meta]) (any[response], error)
|
||||
|
||||
// 解析第一个参数是 *gin.Context
|
||||
if methodType.In(1).String() != "*gin.Context" {
|
||||
// 解析第一个参数是 *gin.Context / 或者包装后的 request.Context
|
||||
firstParamStr := methodType.In(1).String()
|
||||
if firstParamStr != "*gin.Context" && firstParamStr != "*request.Context" {
|
||||
return nil, nil
|
||||
}
|
||||
// 解析第二个参数是组合Meta的form表单
|
||||
|
@ -8,14 +8,13 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"git.zhangdeman.cn/zhangdeman/gin/request"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type TestController struct{}
|
||||
|
||||
func (t TestController) Logic(ctx *gin.Context, formData *TestForm) (TestOut, error) {
|
||||
func (t TestController) Logic(ctx *request.Context, formData *TestForm) (TestOut, error) {
|
||||
return TestOut{
|
||||
FormData: formData,
|
||||
}, nil
|
||||
|
Reference in New Issue
Block a user