Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 1f280e1

Browse files
committedAug 28, 2015
use go's built in handling of trailers and dont do custom chunking
License: MIT Signed-off-by: Jeromy <jeromyj@gmail.com>
1 parent b55cf12 commit 1f280e1

File tree

1 file changed

+8
-75
lines changed

1 file changed

+8
-75
lines changed
 

‎commands/http/handler.go

+8-75
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package http
22

33
import (
4-
"bufio"
54
"errors"
65
"fmt"
76
"io"
@@ -193,6 +192,10 @@ func sendResponse(w http.ResponseWriter, r *http.Request, res cmds.Response, req
193192
}
194193

195194
h := w.Header()
195+
196+
// Set up our potential trailer
197+
h.Set("Trailer", StreamErrHeader)
198+
196199
if res.Length() > 0 {
197200
h.Set(contentLengthHeader, strconv.FormatUint(res.Length(), 10))
198201
}
@@ -230,82 +233,12 @@ func sendResponse(w http.ResponseWriter, r *http.Request, res cmds.Response, req
230233
return
231234
}
232235

233-
if err := writeResponse(status, w, out); err != nil {
234-
if strings.Contains(err.Error(), "broken pipe") {
235-
log.Info("client disconnect while writing stream ", err)
236-
return
237-
}
238-
239-
log.Error("error while writing stream ", err)
240-
}
241-
}
242-
243-
// Copies from an io.Reader to a http.ResponseWriter.
244-
// Flushes chunks over HTTP stream as they are read (if supported by transport).
245-
func writeResponse(status int, w http.ResponseWriter, out io.Reader) error {
246-
// hijack the connection so we can write our own chunked output and trailers
247-
hijacker, ok := w.(http.Hijacker)
248-
if !ok {
249-
log.Error("Failed to create hijacker! cannot continue!")
250-
return errors.New("Could not create hijacker")
251-
}
252-
conn, writer, err := hijacker.Hijack()
236+
w.WriteHeader(status)
237+
_, err = io.Copy(w, out)
253238
if err != nil {
254-
return err
255-
}
256-
defer conn.Close()
257-
258-
// write status
259-
writer.WriteString(fmt.Sprintf("HTTP/1.1 %d %s\r\n", status, http.StatusText(status)))
260-
261-
// Write out headers
262-
w.Header().Write(writer)
263-
264-
// end of headers
265-
writer.WriteString("\r\n")
266-
267-
// write body
268-
streamErr := writeChunks(out, writer)
269-
270-
// close body
271-
writer.WriteString("0\r\n")
272-
273-
// if there was a stream error, write out an error trailer. hopefully
274-
// the client will pick it up!
275-
if streamErr != nil {
276-
writer.WriteString(StreamErrHeader + ": " + sanitizedErrStr(streamErr) + "\r\n")
277-
}
278-
writer.WriteString("\r\n") // close response
279-
writer.Flush()
280-
return streamErr
281-
}
282-
283-
func writeChunks(r io.Reader, w *bufio.ReadWriter) error {
284-
buf := make([]byte, 32*1024)
285-
for {
286-
n, err := r.Read(buf)
287-
288-
if n > 0 {
289-
length := fmt.Sprintf("%x\r\n", n)
290-
w.WriteString(length)
291-
292-
_, err := w.Write(buf[0:n])
293-
if err != nil {
294-
return err
295-
}
296-
297-
w.WriteString("\r\n")
298-
w.Flush()
299-
}
300-
301-
if err != nil && err != io.EOF {
302-
return err
303-
}
304-
if err == io.EOF {
305-
break
306-
}
239+
log.Error("err: ", err)
240+
w.Header().Set(StreamErrHeader, sanitizedErrStr(err))
307241
}
308-
return nil
309242
}
310243

311244
func sanitizedErrStr(err error) string {

0 commit comments

Comments
 (0)
Please sign in to comment.