1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-09-19 06:42:36 +08:00

Merge pull request from ipfs/fix/http-client-close

attempt at properly closing http response bodies
This commit is contained in:
Juan Benet
2015-07-22 13:47:52 -07:00
3 changed files with 35 additions and 5 deletions

@ -102,12 +102,14 @@ func (c *client) Send(req cmds.Request) (cmds.Response, error) {
ec <- err
return
}
// using the overridden JSON encoding in request
res, err := getResponse(httpRes, req)
if err != nil {
ec <- err
return
}
rc <- res
}()
@ -179,6 +181,8 @@ func getResponse(httpRes *http.Response, req cmds.Request) (cmds.Response, error
res.SetLength(length)
}
res.SetCloser(httpRes.Body)
if len(httpRes.Header.Get(streamHeader)) > 0 {
// if output is a stream, we can just use the body reader
res.SetOutput(httpRes.Body)
@ -202,8 +206,15 @@ func getResponse(httpRes *http.Response, req cmds.Request) (cmds.Response, error
} else {
err = dec.Decode(&v)
}
// since we are just looping reading on the response, the only way to
// know we are 'done' is for the consumer to close the response body.
// doing so doesnt throw an io.EOF, but we want to treat it like one.
if err != nil && strings.Contains(err.Error(), "read on closed response body") {
err = io.EOF
}
if err != nil && err != io.EOF {
fmt.Println(err.Error())
log.Error(err)
return
}

@ -171,12 +171,15 @@ func (i internalHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// w.WriteHeader(200)
err = copyChunks(applicationJson, w, out)
if err != nil {
log.Debug(err)
log.Debug("copy chunks error: ", err)
}
return
}
flushCopy(w, out)
err = flushCopy(w, out)
if err != nil {
log.Debug("Flush copy returned an error: ", err)
}
}
func (i Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@ -191,8 +194,8 @@ func flushCopy(w http.ResponseWriter, out io.Reader) error {
return copyChunks("", w, out)
}
io.Copy(&flushResponse{w}, out)
return nil
_, err := io.Copy(&flushResponse{w}, out)
return err
}
// Copies from an io.Reader to a http.ResponseWriter.

@ -101,6 +101,10 @@ type Response interface {
SetLength(uint64)
Length() uint64
// underlying http connections need to be cleaned up, this is for that
Close() error
SetCloser(io.Closer)
// Marshal marshals out the response into a buffer. It uses the EncodingType
// on the Request to chose a Marshaler (Codec).
Marshal() (io.Reader, error)
@ -121,6 +125,7 @@ type response struct {
length uint64
stdout io.Writer
stderr io.Writer
closer io.Closer
}
func (r *response) Request() Request {
@ -214,6 +219,17 @@ func (r *response) Reader() (io.Reader, error) {
return r.out, nil
}
func (r *response) Close() error {
if r.closer != nil {
return r.closer.Close()
}
return nil
}
func (r *response) SetCloser(c io.Closer) {
r.closer = c
}
func (r *response) Stdout() io.Writer {
return r.stdout
}