support event stream

This commit is contained in:
MaysWind
2025-04-30 22:30:01 +08:00
parent 850fbffdde
commit 20b65fd885
3 changed files with 85 additions and 0 deletions
+12
View File
@@ -420,6 +420,18 @@ func bindApiWithTokenUpdate(fn core.ApiHandlerFunc, config *settings.Config) gin
} }
} }
func bindEventStreamApi(fn core.EventStreamApiHandlerFunc) gin.HandlerFunc {
return func(ginCtx *gin.Context) {
c := core.WrapWebContext(ginCtx)
utils.SetEventStreamHeader(c)
err := fn(c)
if err != nil {
utils.WriteEventStreamJsonErrorResult(c, err)
}
}
}
func bindCachedJs(fn core.DataHandlerFunc, store persistence.CacheStore) gin.HandlerFunc { func bindCachedJs(fn core.DataHandlerFunc, store persistence.CacheStore) gin.HandlerFunc {
return cache.CachePage(store, time.Minute, func(ginCtx *gin.Context) { return cache.CachePage(store, time.Minute, func(ginCtx *gin.Context) {
c := core.WrapWebContext(ginCtx) c := core.WrapWebContext(ginCtx)
+3
View File
@@ -15,6 +15,9 @@ type MiddlewareHandlerFunc func(*WebContext)
// ApiHandlerFunc represents the api handler function // ApiHandlerFunc represents the api handler function
type ApiHandlerFunc func(*WebContext) (any, *errs.Error) type ApiHandlerFunc func(*WebContext) (any, *errs.Error)
// EventStreamApiHandlerFunc represents the event stream api handler function
type EventStreamApiHandlerFunc func(*WebContext) *errs.Error
// DataHandlerFunc represents the handler function that returns file data byte array and file name // DataHandlerFunc represents the handler function that returns file data byte array and file name
type DataHandlerFunc func(*WebContext) ([]byte, string, *errs.Error) type DataHandlerFunc func(*WebContext) ([]byte, string, *errs.Error)
+70
View File
@@ -1,6 +1,7 @@
package utils package utils
import ( import (
"encoding/json"
"net/http" "net/http"
"reflect" "reflect"
@@ -80,6 +81,75 @@ func PrintDataErrorResult(c *core.WebContext, contentType string, err *errs.Erro
c.Abort() c.Abort()
} }
// SetEventStreamHeader sets the headers for event stream response
func SetEventStreamHeader(c *core.WebContext) {
c.Writer.Header().Set("Content-Type", "text/event-stream")
c.Writer.Header().Set("Cache-Control", "no-cache")
c.Writer.Header().Set("Connection", "keep-alive")
}
func WriteEventStreamJsonSuccessResult(c *core.WebContext, result any) {
data, err := json.Marshal(result)
if err != nil {
c.Abort()
return
}
_, err = c.Writer.WriteString("data: " + string(data) + "\n\n")
if err != nil {
c.Abort()
return
}
c.Writer.Flush()
}
func WriteEventStreamJsonErrorResult(c *core.WebContext, originalErr *errs.Error) {
c.SetResponseError(originalErr)
errorMessage := originalErr.Error()
if originalErr.Code() == errs.ErrIncompleteOrIncorrectSubmission.Code() && len(originalErr.BaseError) > 0 {
validationErrors, ok := originalErr.BaseError[0].(validator.ValidationErrors)
if ok {
for _, err := range validationErrors {
errorMessage = getValidationErrorText(err)
break
}
}
}
result := gin.H{
"success": false,
"errorCode": originalErr.Code(),
"errorMessage": errorMessage,
"path": c.Request.URL.Path,
}
if originalErr.Context != nil {
result["context"] = originalErr.Context
}
data, err := json.Marshal(result)
if err != nil {
c.Abort()
return
}
_, err = c.Writer.WriteString("data: " + string(data) + "\n\n")
if err != nil {
c.Abort()
return
}
c.Writer.Flush()
}
func getValidationErrorText(err validator.FieldError) string { func getValidationErrorText(err validator.FieldError) string {
fieldName := GetFirstLowerCharString(err.Field()) fieldName := GetFirstLowerCharString(err.Field())