aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/manucorporat/sse/sse-encoder.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/manucorporat/sse/sse-encoder.go')
-rw-r--r--vendor/github.com/manucorporat/sse/sse-encoder.go106
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)
+}