207 lines
7.6 KiB
Go
207 lines
7.6 KiB
Go
// Package router ...
|
|
//
|
|
// Description : router ...
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 2025-01-27 19:42
|
|
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"
|
|
)
|
|
|
|
func (s *server) getFormInitValue(ctx *gin.Context, uriCfg UriConfig) (any, error) {
|
|
var (
|
|
formParam reflect.Value
|
|
formValue any
|
|
err error
|
|
)
|
|
|
|
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 {
|
|
// 格式化验证错误的信息
|
|
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
|
|
}
|
|
|
|
// RequestHandler 获取请求处理方法
|
|
func (s *server) RequestHandler(uriCfg UriConfig) gin.HandlerFunc {
|
|
return func(ctx *gin.Context) {
|
|
var (
|
|
err error
|
|
ok bool
|
|
e exception.IException
|
|
formValue any
|
|
firstParam reflect.Value
|
|
)
|
|
|
|
if formValue, err = s.getFormInitValue(ctx, uriCfg); nil != err {
|
|
e = exception.NewFromError(http.StatusBadRequest, err)
|
|
response.SendWithException(ctx, e, &define.ResponseOption{
|
|
ContentType: consts.MimeTypeJson,
|
|
})
|
|
ctx.Abort()
|
|
return
|
|
}
|
|
// 表单数据
|
|
inputValue := reflect.ValueOf(formValue).Elem()
|
|
|
|
// 注入公共参数
|
|
if err = s.injectCommonParam(ctx, inputValue); nil != err {
|
|
e = exception.NewFromError(500, err)
|
|
response.SendWithException(ctx, e, &define.ResponseOption{
|
|
ContentType: consts.MimeTypeJson,
|
|
})
|
|
ctx.Abort()
|
|
return
|
|
}
|
|
|
|
// 非必传参数设置默认值
|
|
defaults.SetDefaults(formValue)
|
|
|
|
// 默认请求失败
|
|
ctx.Set(consts.GinRequestSuccess, false)
|
|
// 初始化响应之后 logic
|
|
logicAfterResponse := &define.LogicAfterResponse{
|
|
SuccessHookFuncList: make([]func(ctx *gin.Context), 0),
|
|
FailureHookFuncList: make([]func(ctx *gin.Context), 0),
|
|
Lock: &sync.RWMutex{},
|
|
}
|
|
// 此处暴露出去,是为了使用方可以获取到对应数据
|
|
ctx.Set(consts.GinLogicAfterResponseKey, logicAfterResponse)
|
|
defer s.hook(ctx, uriCfg) // 执行 Logic 之后的相关逻辑
|
|
|
|
firstParam = reflect.ValueOf(ctx)
|
|
resList := uriCfg.ApiLogicFunc.Func.Call([]reflect.Value{uriCfg.ApiStructValue, firstParam, inputValue})
|
|
if resList[1].IsNil() {
|
|
// 请求成功, 更新标识
|
|
ctx.Set(consts.GinRequestSuccess, true)
|
|
response.SuccessWithExtension(ctx, resList[0].Interface(), &define.ResponseOption{ContentType: consts.MimeTypeJson})
|
|
return
|
|
}
|
|
// 请求失败
|
|
if ok = errors.As(resList[1].Interface().(error), &e); ok {
|
|
// 本身就是exception.IException
|
|
logger.Instance.Debug("请求结果err类型为 exception.IException, 无需特殊处理", loggerPkg.NewLogData(util.GinCtxToContext(ctx), logger.RecordType, logger.CodeLogicErrorWrapper, map[string]any{}).ToFieldList()...)
|
|
} else if err, ok = resList[1].Interface().(error); ok {
|
|
logger.Instance.Debug("请求结果err类型为 error, 包装为 exception.IException", loggerPkg.NewLogData(util.GinCtxToContext(ctx), logger.RecordType, logger.CodeLogicErrorWrapper, map[string]any{}).ToFieldList()...)
|
|
e = exception.NewFromError(-1, err)
|
|
} else {
|
|
logger.Instance.Debug("请求结果err类型 既不是 error 也不是 exception.IException, 包装为 exception.IException", loggerPkg.NewLogData(util.GinCtxToContext(ctx), logger.RecordType, logger.CodeLogicErrorWrapper, map[string]any{}).ToFieldList()...)
|
|
e = exception.NewWithCodeAndData(-1, map[string]any{
|
|
"err": resList[1].Interface(),
|
|
})
|
|
}
|
|
response.SendWithException(ctx, e, &define.ResponseOption{
|
|
ContentType: consts.MimeTypeJson,
|
|
})
|
|
}
|
|
}
|
|
|
|
// SseHandler sse连接请求
|
|
func (s *server) SseHandler(uriCfg UriConfig) gin.HandlerFunc {
|
|
return func(ctx *gin.Context) {
|
|
var (
|
|
err error
|
|
ok bool
|
|
e exception.IException
|
|
formValue any
|
|
firstParam reflect.Value
|
|
)
|
|
|
|
if formValue, err = s.getFormInitValue(ctx, uriCfg); nil != err {
|
|
e = exception.NewFromError(http.StatusBadRequest, err)
|
|
response.SendWithException(ctx, e, &define.ResponseOption{
|
|
ContentType: consts.MimeTypeJson,
|
|
})
|
|
ctx.Abort()
|
|
return
|
|
}
|
|
// 表单数据
|
|
inputValue := reflect.ValueOf(formValue).Elem()
|
|
|
|
// 注入公共参数
|
|
if err = s.injectCommonParam(ctx, inputValue); nil != err {
|
|
e = exception.NewFromError(500, err)
|
|
response.SendWithException(ctx, e, &define.ResponseOption{
|
|
ContentType: consts.MimeTypeJson,
|
|
})
|
|
ctx.Abort()
|
|
return
|
|
}
|
|
|
|
// 非必传参数设置默认值
|
|
defaults.SetDefaults(formValue)
|
|
|
|
// 默认请求失败
|
|
ctx.Set(consts.GinRequestSuccess, false)
|
|
// 初始化响应之后 logic
|
|
logicAfterResponse := &define.LogicAfterResponse{
|
|
SuccessHookFuncList: make([]func(ctx *gin.Context), 0),
|
|
FailureHookFuncList: make([]func(ctx *gin.Context), 0),
|
|
Lock: &sync.RWMutex{},
|
|
}
|
|
// 此处暴露出去,是为了使用方可以获取到对应数据
|
|
ctx.Set(consts.GinLogicAfterResponseKey, logicAfterResponse)
|
|
defer s.hook(ctx, uriCfg) // 执行 Logic 之后的相关逻辑
|
|
|
|
ctx.Writer.Header().Set(consts.HeaderKeyContentType.String(), "text/event-stream")
|
|
ctx.Writer.Header().Set(consts.HeaderKeyCacheControl.String(), "no-cache")
|
|
ctx.Writer.Header().Set(consts.HeaderKeyConnection.String(), "keep-alive")
|
|
ctx.Writer.Header().Set(consts.HeaderKeyXAccelBuffering.String(), "no")
|
|
flusher, _ := ctx.Writer.(http.Flusher)
|
|
// TODO: 发送连接就绪消息
|
|
flusher.Flush()
|
|
firstParam = reflect.ValueOf(ctx)
|
|
resList := uriCfg.ApiLogicFunc.Func.Call([]reflect.Value{uriCfg.ApiStructValue, firstParam, inputValue})
|
|
if resList[1].IsNil() {
|
|
// 请求成功, 更新标识
|
|
ctx.Set(consts.GinRequestSuccess, true)
|
|
response.SuccessWithExtension(ctx, resList[0].Interface(), &define.ResponseOption{ContentType: consts.MimeTypeJson})
|
|
return
|
|
}
|
|
// 请求失败
|
|
if ok = errors.As(resList[1].Interface().(error), &e); ok {
|
|
// 本身就是exception.IException
|
|
logger.Instance.Debug("请求结果err类型为 exception.IException, 无需特殊处理", loggerPkg.NewLogData(util.GinCtxToContext(ctx), logger.RecordType, logger.CodeLogicErrorWrapper, map[string]any{}).ToFieldList()...)
|
|
} else if err, ok = resList[1].Interface().(error); ok {
|
|
logger.Instance.Debug("请求结果err类型为 error, 包装为 exception.IException", loggerPkg.NewLogData(util.GinCtxToContext(ctx), logger.RecordType, logger.CodeLogicErrorWrapper, map[string]any{}).ToFieldList()...)
|
|
e = exception.NewFromError(-1, err)
|
|
} else {
|
|
logger.Instance.Debug("请求结果err类型 既不是 error 也不是 exception.IException, 包装为 exception.IException", loggerPkg.NewLogData(util.GinCtxToContext(ctx), logger.RecordType, logger.CodeLogicErrorWrapper, map[string]any{}).ToFieldList()...)
|
|
e = exception.NewWithCodeAndData(-1, map[string]any{
|
|
"err": resList[1].Interface(),
|
|
})
|
|
}
|
|
response.SendWithException(ctx, e, &define.ResponseOption{
|
|
ContentType: consts.MimeTypeJson,
|
|
})
|
|
}
|
|
}
|