|
1 | 1 | package http
|
2 | 2 |
|
3 | 3 | import (
|
4 |
| - "bufio" |
5 | 4 | "errors"
|
6 | 5 | "fmt"
|
7 | 6 | "io"
|
@@ -193,6 +192,10 @@ func sendResponse(w http.ResponseWriter, r *http.Request, res cmds.Response, req
|
193 | 192 | }
|
194 | 193 |
|
195 | 194 | h := w.Header()
|
| 195 | + |
| 196 | + // Set up our potential trailer |
| 197 | + h.Set("Trailer", StreamErrHeader) |
| 198 | + |
196 | 199 | if res.Length() > 0 {
|
197 | 200 | h.Set(contentLengthHeader, strconv.FormatUint(res.Length(), 10))
|
198 | 201 | }
|
@@ -230,82 +233,12 @@ func sendResponse(w http.ResponseWriter, r *http.Request, res cmds.Response, req
|
230 | 233 | return
|
231 | 234 | }
|
232 | 235 |
|
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) |
253 | 238 | 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)) |
307 | 241 | }
|
308 |
| - return nil |
309 | 242 | }
|
310 | 243 |
|
311 | 244 | func sanitizedErrStr(err error) string {
|
|
0 commit comments