fix(http body saver): properly deal with EOF terminated bodies (#226)

See https://github.com/ooni/probe-engine/issues/1191
This commit is contained in:
Simone Basso 2021-02-11 14:57:14 +01:00 committed by GitHub
commit 3155549513
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 0 deletions

View file

@ -2,6 +2,7 @@ package httptransport
import (
"bytes"
"errors"
"io"
"io/ioutil"
"net/http"
@ -125,6 +126,7 @@ func (txp SaverBodyHTTPTransport) RoundTrip(req *http.Request) (*http.Response,
return nil, err
}
data, err := saverSnapRead(resp.Body, snapsize)
err = ignoreExpectedEOF(err, resp)
if err != nil {
resp.Body.Close()
return nil, err
@ -139,6 +141,22 @@ func (txp SaverBodyHTTPTransport) RoundTrip(req *http.Request) (*http.Response,
return resp, nil
}
// ignoreExpectedEOF converts an error signalling the end of the body
// into a success. We know that we are in such condition when the
// resp.Close hint flag is set to true. (Thanks, stdlib!)
//
// See https://github.com/ooni/probe-engine/issues/1191 for an analysis
// of how this error was impacting measurements and data quality.
func ignoreExpectedEOF(err error, resp *http.Response) error {
if err == nil {
return nil
}
if errors.Is(err, io.EOF) && resp.Close {
return nil
}
return err
}
func saverSnapRead(r io.ReadCloser, snapsize int) ([]byte, error) {
return ioutil.ReadAll(io.LimitReader(r, int64(snapsize)))
}