gin/render/ssevent.go

59 lines
1.3 KiB
Go

package render
import (
"encoding/json"
"fmt"
"net/http"
"reflect"
)
type sseRender struct{}
var SSEvent Render = sseRender{}
func (_ sseRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
eventName := data[0].(string)
obj := data[1]
return WriteSSEvent(w, eventName, obj)
}
func WriteSSEvent(w http.ResponseWriter, eventName string, data interface{}) error {
header := w.Header()
if len(header.Get("Content-Type")) == 0 {
w.Header().Set("Content-Type", "text/event-stream")
}
var stringData string
switch typeOfData(data) {
case reflect.Struct, reflect.Slice:
if jsonBytes, err := json.Marshal(data); err == nil {
stringData = string(jsonBytes)
} else {
return err
}
case reflect.Ptr:
stringData = escape(fmt.Sprintf("%v", &data)) + "\n"
default:
stringData = escape(fmt.Sprintf("%v", data)) + "\n"
}
_, err := fmt.Fprintf(w, "event: %s\ndata: %s\n", escape(eventName), stringData)
return err
}
func typeOfData(data interface{}) reflect.Kind {
value := reflect.ValueOf(data)
valueType := value.Kind()
if valueType == reflect.Ptr {
newValue := value.Elem().Kind()
if newValue == reflect.Struct || newValue == reflect.Slice {
return newValue
} else {
return valueType
}
}
return valueType
}
func escape(str string) string {
return str
}