diff options
Diffstat (limited to 'vendor/github.com/manucorporat/sse/sse-encoder.go')
-rw-r--r-- | vendor/github.com/manucorporat/sse/sse-encoder.go | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/vendor/github.com/manucorporat/sse/sse-encoder.go b/vendor/github.com/manucorporat/sse/sse-encoder.go new file mode 100644 index 0000000..16bab76 --- /dev/null +++ b/vendor/github.com/manucorporat/sse/sse-encoder.go @@ -0,0 +1,106 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package sse + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "reflect" + "strconv" + "strings" +) + +// Server-Sent Events +// W3C Working Draft 29 October 2009 +// http://www.w3.org/TR/2009/WD-eventsource-20091029/ + +const ContentType = "text/event-stream" + +var contentType = []string{ContentType} +var noCache = []string{"no-cache"} +var replacer = strings.NewReplacer("\n", "\\n", "\r", "\\r") + +type Event struct { + Event string + Id string + Retry uint + Data interface{} +} + +func Encode(writer io.Writer, event Event) error { + w := checkWriter(writer) + writeId(w, event.Id) + writeEvent(w, event.Event) + writeRetry(w, event.Retry) + return writeData(w, event.Data) +} + +func writeId(w stringWriter, id string) { + if len(id) > 0 { + w.WriteString("id: ") + writeEscape(w, id) + w.WriteString("\n") + } +} + +func writeEvent(w stringWriter, event string) { + if len(event) > 0 { + w.WriteString("event: ") + writeEscape(w, event) + w.WriteString("\n") + } +} + +func writeRetry(w stringWriter, retry uint) { + if retry > 0 { + w.WriteString("retry: ") + w.WriteString(strconv.FormatUint(uint64(retry), 10)) + w.WriteString("\n") + } +} + +func writeData(w stringWriter, data interface{}) error { + w.WriteString("data: ") + switch kindOfData(data) { + case reflect.Struct, reflect.Slice, reflect.Map: + err := json.NewEncoder(w).Encode(data) + if err != nil { + return err + } + w.WriteString("\n") + default: + text := fmt.Sprint(data) + writeEscape(w, text) + w.WriteString("\n\n") + } + return nil +} + +func (r Event) Render(w http.ResponseWriter) error { + header := w.Header() + header["Content-Type"] = contentType + + if _, exist := header["Cache-Control"]; !exist { + header["Cache-Control"] = noCache + } + return Encode(w, r) +} + +func kindOfData(data interface{}) reflect.Kind { + value := reflect.ValueOf(data) + valueType := value.Kind() + if valueType == reflect.Ptr { + valueType = value.Elem().Kind() + } + return valueType +} + +func writeEscape(w stringWriter, str string) { + // any-char = %x0000-0009 / %x000B-000C / %x000E-10FFFF + // ; a Unicode character other than U+000A LINE FEED (LF) or U+000D CARRIAGE RETURN (CR) + replacer.WriteString(w, str) +} |