Spaces:
Build error
Build error
| // 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 common | |
| import ( | |
| "fmt" | |
| "io" | |
| "net/http" | |
| "strings" | |
| "sync" | |
| ) | |
| type stringWriter interface { | |
| io.Writer | |
| writeString(string) (int, error) | |
| } | |
| type stringWrapper struct { | |
| io.Writer | |
| } | |
| func (w stringWrapper) writeString(str string) (int, error) { | |
| return w.Writer.Write([]byte(str)) | |
| } | |
| func checkWriter(writer io.Writer) stringWriter { | |
| if w, ok := writer.(stringWriter); ok { | |
| return w | |
| } else { | |
| return stringWrapper{writer} | |
| } | |
| } | |
| // Server-Sent Events | |
| // W3C Working Draft 29 October 2009 | |
| // http://www.w3.org/TR/2009/WD-eventsource-20091029/ | |
| var contentType = []string{"text/event-stream"} | |
| var noCache = []string{"no-cache"} | |
| var fieldReplacer = strings.NewReplacer( | |
| "\n", "\\n", | |
| "\r", "\\r") | |
| var dataReplacer = strings.NewReplacer( | |
| "\n", "\n", | |
| "\r", "\\r") | |
| type CustomEvent struct { | |
| Event string | |
| Id string | |
| Retry uint | |
| Data interface{} | |
| Mutex sync.Mutex | |
| } | |
| func encode(writer io.Writer, event CustomEvent) error { | |
| w := checkWriter(writer) | |
| return writeData(w, event.Data) | |
| } | |
| func writeData(w stringWriter, data interface{}) error { | |
| dataReplacer.WriteString(w, fmt.Sprint(data)) | |
| if strings.HasPrefix(data.(string), "data") { | |
| w.writeString("\n\n") | |
| } | |
| return nil | |
| } | |
| func (r CustomEvent) Render(w http.ResponseWriter) error { | |
| r.WriteContentType(w) | |
| return encode(w, r) | |
| } | |
| func (r CustomEvent) WriteContentType(w http.ResponseWriter) { | |
| r.Mutex.Lock() | |
| defer r.Mutex.Unlock() | |
| header := w.Header() | |
| header["Content-Type"] = contentType | |
| if _, exist := header["Cache-Control"]; !exist { | |
| header["Cache-Control"] = noCache | |
| } | |
| } | |