准备支持 sse 连接能力

This commit is contained in:
2025-12-26 17:48:31 +08:00
parent 166ce9a52a
commit 94aaccaa9c
3 changed files with 84 additions and 1 deletions

View File

@@ -123,3 +123,84 @@ func (s *server) RequestHandler(uriCfg UriConfig) gin.HandlerFunc {
})
}
}
// 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,
})
}
}