@cryptotaxi247 / kubo / commits / c3c0b248e

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 }