]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go/internal/modfetch: wrap errors from HTTP response bodies
authorBryan C. Mills <bcmills@google.com>
Mon, 16 May 2022 19:25:28 +0000 (15:25 -0400)
committerGopher Robot <gobot@golang.org>
Tue, 24 May 2022 17:05:39 +0000 (17:05 +0000)
The Read method on the Body returned from a net/http.Transport does
not wrap errors returned by the underlying io.Reader and returns a
bare io.ErrUnexpectedEOF if the body is shorter than the declared
Content-Length.

Since we can't feasibly add detail on the net/http side without
breaking established users, we must instead add detail on the caller
side. Since the net/http client uses url.Error for most of its own
errors, we use that same error type here.

I have not added a regression test for this change. (While it is
theoretically possible to set up a GOPROXY that returns incorrect
Content-Length headers, the change seems straightforward enough that
it isn't worth the complex test setup.)

Fixes #52727.

Change-Id: Id00b04ae4fd518148106a49188fe169aadbcce2c
Reviewed-on: https://go-review.googlesource.com/c/go/+/406675
Auto-Submit: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
Reviewed-by: Michael Matloob <matloob@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/cmd/go/internal/modfetch/proxy.go

index 31d453c8074e6a52b4b9fe7009ef9ef79aba70e3..4d63dd56487d068e298c82a92a10f568fb4a84da 100644 (file)
@@ -247,10 +247,17 @@ func (p *proxyRepo) getBytes(path string) ([]byte, error) {
                return nil, err
        }
        defer body.Close()
-       return io.ReadAll(body)
+
+       b, err := io.ReadAll(body)
+       if err != nil {
+               // net/http doesn't add context to Body errors, so add it here.
+               // (See https://go.dev/issue/52727.)
+               return b, &url.Error{Op: "read", URL: pathpkg.Join(p.redactedURL, path), Err: err}
+       }
+       return b, nil
 }
 
-func (p *proxyRepo) getBody(path string) (io.ReadCloser, error) {
+func (p *proxyRepo) getBody(path string) (r io.ReadCloser, err error) {
        fullPath := pathpkg.Join(p.url.Path, path)
 
        target := *p.url
@@ -407,7 +414,8 @@ func (p *proxyRepo) Zip(dst io.Writer, version string) error {
        if err != nil {
                return p.versionError(version, err)
        }
-       body, err := p.getBody("@v/" + encVer + ".zip")
+       path := "@v/" + encVer + ".zip"
+       body, err := p.getBody(path)
        if err != nil {
                return p.versionError(version, err)
        }
@@ -415,6 +423,9 @@ func (p *proxyRepo) Zip(dst io.Writer, version string) error {
 
        lr := &io.LimitedReader{R: body, N: codehost.MaxZipFile + 1}
        if _, err := io.Copy(dst, lr); err != nil {
+               // net/http doesn't add context to Body errors, so add it here.
+               // (See https://go.dev/issue/52727.)
+               err = &url.Error{Op: "read", URL: pathpkg.Join(p.redactedURL, path), Err: err}
                return p.versionError(version, err)
        }
        if lr.N <= 0 {