diff --git a/define/middleare.go b/define/middleare.go index bd042a2..0e05c83 100644 --- a/define/middleare.go +++ b/define/middleare.go @@ -10,15 +10,7 @@ package define import "github.com/gin-gonic/gin" // IsBlackIP 是否是黑名单IP -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 23:25 2022/6/25 type IsBlackIP func(ctx *gin.Context, clientIP string) bool // IsWhiteIP 是否白名单IP -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 23:27 2022/6/25 type IsWhiteIP func(ctx *gin.Context, clientIP string) bool diff --git a/define/response.go b/define/response.go index a995dad..43e824e 100644 --- a/define/response.go +++ b/define/response.go @@ -20,10 +20,6 @@ var ( ) // HttpHandleConfig 请求处理配置 -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 20:41 2022/6/25 type HttpHandleConfig struct { RecordRequestDataField string RecordResponseDataField string @@ -43,19 +39,11 @@ type HttpHandleConfig struct { } // ConvertDefaultConfig 覆盖默认配置 -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 20:41 2022/6/25 func ConvertDefaultConfig(cfg *HttpHandleConfig) { inputHttpHandleConfig = cfg } // GetHttpHandleConfig 获取http配置 -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 16:55 2024/7/23 func GetHttpHandleConfig() *HttpHandleConfig { return &HttpHandleConfig{ EnableExtensionOutput: inputHttpHandleConfig.EnableExtensionOutput, @@ -129,8 +117,8 @@ func GetHttpHandleConfig() *HttpHandleConfig { } type LogicAfterResponse struct { - SuccessHookFuncList []func(ctx *gin.Context) `json:"-"` // 请求最后需要执行的成功hook函数 - FailureHookFuncList []func(ctx *gin.Context) `json:"-"` // 请求最后需要执行的失败hook函数 + SuccessHookFuncList []func(ctx *gin.Context) `json:"-"` // 请求最后需要执行的成功 hook函数 + FailureHookFuncList []func(ctx *gin.Context) `json:"-"` // 请求最后需要执行的失败 hook函数 Lock *sync.RWMutex `json:"-"` // 逻辑锁 } diff --git a/logger/instance.go b/logger/instance.go index 5a97bd7..82991de 100644 --- a/logger/instance.go +++ b/logger/instance.go @@ -47,6 +47,7 @@ const ( ) const ( - CodeInjectCommonParam = "inject-common-param" - CodeLogicHook = "logic-hook" + CodeInjectCommonParam = "inject-common-param" + CodeLogicHook = "logic-hook" + CodeParamValidateFailure = "param-validate-failure" ) diff --git a/router/common_param.go b/router/common_param.go index eb576ae..b43d28f 100644 --- a/router/common_param.go +++ b/router/common_param.go @@ -49,14 +49,17 @@ func (s *server) injectCommonParam(ctx *gin.Context, formValue any) error { } else { reflectType = reflectFormValue.Type() } + if reflectType.Kind() == reflect.Ptr { + reflectType = reflectType.Elem() + } fieldTable := map[string]bool{} - fieldNum := reflectType.Elem().NumField() + fieldNum := reflectType.NumField() for i := 0; i < fieldNum; i++ { - if reflectType.Elem().Field(i).Anonymous && // 是匿名字段, 再做一次解析 - ((reflectType.Elem().Field(i).Type.Kind() == reflect.Ptr && reflectType.Elem().Field(i).Type.Kind() == reflect.Struct) || // 结构体指针 - reflectType.Elem().Field(i).Type.Kind() == reflect.Struct) { // 结构体 - anonymousFieldType := reflectType.Elem().Field(i).Type + if reflectType.Field(i).Anonymous && // 是匿名字段, 再做一次解析 + ((reflectType.Field(i).Type.Kind() == reflect.Ptr && reflectType.Field(i).Type.Kind() == reflect.Struct) || // 结构体指针 + reflectType.Field(i).Type.Kind() == reflect.Struct) { // 结构体 + anonymousFieldType := reflectType.Field(i).Type if anonymousFieldType.Kind() == reflect.Ptr { anonymousFieldType = anonymousFieldType.Elem() } @@ -65,7 +68,7 @@ func (s *server) injectCommonParam(ctx *gin.Context, formValue any) error { } } else { // 提取全部结构体字段 - fieldTable[reflectType.Elem().Field(i).Name] = true + fieldTable[reflectType.Field(i).Name] = true } } for fieldName, getParamFunc := range s.commonParam { diff --git a/router/controller.go b/router/controller.go index b6c1adb..38f9156 100644 --- a/router/controller.go +++ b/router/controller.go @@ -11,6 +11,7 @@ import ( "reflect" "strings" + "git.zhangdeman.cn/zhangdeman/gin/logger" "git.zhangdeman.cn/zhangdeman/util" ) @@ -49,37 +50,59 @@ func (c controller) Parse(inputController any) map[string]UriConfig { return parseRes } -// methodConfig 解析方法配置, 要求函数格式, 两个参数, 两个返回值, 格式 : func(ctx *gin.Context, formData anyStruct[组合Meta]) (anyStruct|map[response], error) -// -// 参数 : 方法反射结果 -// -// 返回值 : 第一个 -> 解析出的接口配置 第二个 -> 是否要注册为接口 -func (c controller) methodConfig(reflectMethod reflect.Method) (cfg UriConfig, needRegister bool) { +// preCheckMethod 预检查方法是否可以注册为接口 +func (c controller) preCheckMethod(reflectMethod reflect.Method) (bool, reflect.Type, reflect.StructField) { + var ( + metaField reflect.StructField + metaFieldExist bool + ) + methodType := reflectMethod.Type // num0: 函数声明 // num1: 第一个参数 // num2: 第二个参数 if methodType.NumIn() != 3 { - needRegister = false - return + return false, nil, metaField } // 第一个参数必须是 *gin.Context 或者 *define.Context paramOne := methodType.In(1).String() if paramOne != GinContextType { - needRegister = false - return + return false, nil, metaField } + // 解析第二个参数是组合 Meta 的form表单 formType := methodType.In(2) - cfg.FormDataType = formType if formType.Kind() == reflect.Ptr { - formType = methodType.In(2).Elem() + formType = formType.Elem() } - metaField, metaFieldExist := formType.FieldByName(FieldNameMeta) - if !metaFieldExist { - needRegister = false - return + + if metaField, metaFieldExist = formType.FieldByName(FieldNameMeta); !metaFieldExist { + return false, nil, metaField } + return true, formType, metaField +} + +// methodConfig 解析方法配置, 要求函数格式, 两个参数, 两个返回值, 格式 : func(ctx *gin.Context, formData anyStruct[组合Meta]) (anyStruct|map[response], error) +// +// 参数 : 方法反射结果 +// +// 返回值 : 第一个 -> 解析出的接口配置 第二个 -> 是否要注册为接口 +func (c controller) methodConfig(reflectMethod reflect.Method) (UriConfig, bool) { + var ( + needRegister bool + metaField reflect.StructField + cfg UriConfig + ) + + methodType := reflectMethod.Type + // num0: 函数声明 + // num1: 第一个参数 + // num2: 第二个参数 + if needRegister, cfg.FormDataType, metaField = c.preCheckMethod(reflectMethod); !needRegister { + logger.Instance.Info("接口方法不符合要求, 不注册为接口, 方法名: " + reflectMethod.Name + ", 方法签名: " + methodType.String()) + return UriConfig{}, false + } + cfg.ResultDataType = methodType.Out(0) if methodType.Out(1).Kind().String() != ErrorType { // 判断是否是实现 error接口的方法 @@ -95,7 +118,7 @@ func (c controller) methodConfig(reflectMethod reflect.Method) (cfg UriConfig, n } if !outputErrParse { needRegister = false - return + return cfg, needRegister } } c.setUriMeta(metaField, &cfg) @@ -111,7 +134,7 @@ func (c controller) methodConfig(reflectMethod reflect.Method) (cfg UriConfig, n //cfg.ParamList = c.parseParamConfig(formType) cfg.ApiLogicFunc = reflectMethod needRegister = true - return + return cfg, needRegister } // setUriMeta 设置接口的 meta 信息 diff --git a/router/handler.go b/router/handler.go index 47473bb..566cc80 100644 --- a/router/handler.go +++ b/router/handler.go @@ -9,14 +9,18 @@ package router import ( "errors" + "net/http" "reflect" "sync" "git.zhangdeman.cn/zhangdeman/consts" "git.zhangdeman.cn/zhangdeman/exception" "git.zhangdeman.cn/zhangdeman/gin/define" + "git.zhangdeman.cn/zhangdeman/gin/logger" "git.zhangdeman.cn/zhangdeman/gin/request" "git.zhangdeman.cn/zhangdeman/gin/response" + "git.zhangdeman.cn/zhangdeman/gin/util" + loggerPkg "git.zhangdeman.cn/zhangdeman/logger" "github.com/gin-gonic/gin" "github.com/mcuadros/go-defaults" ) @@ -38,6 +42,9 @@ func (s *server) getFormInitValue(ctx *gin.Context, uriCfg UriConfig) (any, erro if err = request.Form.Parse(ctx, formValue); nil != err { // 格式化验证错误的信息 err = GetValidateErr(formValue, err) + logger.Instance.Error("参数解析出现异常", loggerPkg.NewLogData(util.GinCtxToContext(ctx), logger.RecordType, logger.CodeParamValidateFailure, map[string]any{ + "err_msg": err.Error(), + }).ToFieldList()...) return nil, err } return formValue, nil @@ -55,7 +62,7 @@ func (s *server) RequestHandler(uriCfg UriConfig) gin.HandlerFunc { ) if formValue, err = s.getFormInitValue(ctx, uriCfg); nil != err { - e = exception.NewFromError(400, err) + e = exception.NewFromError(http.StatusBadRequest, err) response.SendWithException(ctx, e, &define.ResponseOption{ ContentType: consts.MimeTypeJson, }) diff --git a/router/option.go b/router/option.go index b551c21..c80cbcb 100644 --- a/router/option.go +++ b/router/option.go @@ -20,12 +20,12 @@ type SetServerOptionFunc func(so *serverOption) // serverOption 获取server实例的选项 type serverOption struct { swaggerUiTheme string // swagger 主题 - swaggerBaseUri string // swagger基础path + swaggerBaseUri string // swagger 基础path globalMiddlewareList []gin.HandlerFunc // 全局中间件列表 disableSwaggerDoc bool // 禁用swagger文档, 特定环境不想展示文档, 可通过次方式禁用 serverInfo *apiDocDefine.Info // 服务器信息 serverList []*apiDocDefine.ServerItem // 服务器环境列表 - enablePprof bool // 启用pprof + enablePprof bool // 启用 pprof enableCors bool // 启动跨域支持 disableInitRequest bool // 禁用初始化请求 loggerCfg *middleware.AccessConfig // 日志配置