commands/http: Made Handler stream channel output
Matt Bell committed
Dec 17, 2014 at 16:19 UTC
c3c0b248e85443495e70caf82c34de4d582f43fe
1 file changed
+40
-3
commands/http/handler.go
+40
-3
@@ -20,8 +20,11 @@ type Handler struct {
20
var ErrNotFound = errors.New("404 page not found")
21
22
const (
23
- streamHeader = "X-Stream-Output"
24
- contentTypeHeader = "Content-Type"
23
+ streamHeader = "X-Stream-Output"
24
+ channelHeader = "X-Chunked-Output"
25
+ contentTypeHeader = "Content-Type"
26
+ contentLengthHeader = "Content-Length"
27
+ transferEncodingHeader = "Transfer-Encoding"
28
)
29
30
var mimeTypes = map[string]string{
@@ -80,6 +83,11 @@ func (i Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
83
w.Header().Set(contentTypeHeader, mime)
84
}
85
86
+ // if the res output is a channel, set a custom header for it
87
+ if _, ok := res.Output().(chan interface{}); ok {
88
+ w.Header().Set(channelHeader, "1")
89
+ }
90
+
91
// if response contains an error, write an HTTP error status code
92
if e := res.Error(); e != nil {
93
if e.Code == cmds.ErrClient {
@@ -97,5 +105,34 @@ func (i Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
105
return
106
}
107
100
- io.Copy(w, out)
108
+ err = copyChunks(w, out)
109
+ if err != nil {
110
+ log.Error(err)
111
+ }
112
+}
113
+
114
+// Copies from an io.Reader to a http.ResponseWriter.
115
+// Flushes chunks over HTTP stream as they are read (if supported by transport).
116
+func copyChunks(w http.ResponseWriter, out io.Reader) error {
117
+ buf := make([]byte, 32*1024)
118
+
119
+ for {
120
+ n, err := out.Read(buf)
121
+
122
+ if n > 0 {
123
+ _, err := w.Write(buf[0:n])
124
+ if err != nil {
125
+ return err
126
+ }
127
+
128
+ if f, ok := w.(http.Flusher); ok {
129
+ f.Flush()
130
+ }
131
+ }
132
+
133
+ if err != nil {
134
+ return err
135
+ }
136
+ }
137
+ return nil
138
}