registry/client/transport: use defer to close response body

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2025-02-25 14:41:43 +01:00
parent 3ae8162724
commit 3e5daf8a9a
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C

View File

@ -159,7 +159,7 @@ func (hrs *httpReadSeeker) reset() {
} }
} }
func (hrs *httpReadSeeker) reader() (io.Reader, error) { func (hrs *httpReadSeeker) reader() (_ io.Reader, retErr error) {
if hrs.err != nil { if hrs.err != nil {
return nil, hrs.err return nil, hrs.err
} }
@ -184,42 +184,41 @@ func (hrs *httpReadSeeker) reader() (io.Reader, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer func() {
if retErr != nil {
_ = resp.Body.Close()
}
}()
// Normally would use client.SuccessStatus, but that would be a cyclic // Normally would use client.SuccessStatus, but that would be a cyclic
// import // import
if resp.StatusCode >= 200 && resp.StatusCode <= 399 { if resp.StatusCode >= 200 && resp.StatusCode <= 399 {
if hrs.readerOffset > 0 { if hrs.readerOffset > 0 {
if resp.StatusCode != http.StatusPartialContent { if resp.StatusCode != http.StatusPartialContent {
resp.Close()
return nil, ErrWrongCodeForByteRange return nil, ErrWrongCodeForByteRange
} }
contentRange := resp.Header.Get("Content-Range") contentRange := resp.Header.Get("Content-Range")
if contentRange == "" { if contentRange == "" {
resp.Close()
return nil, errors.New("no Content-Range header found in HTTP 206 response") return nil, errors.New("no Content-Range header found in HTTP 206 response")
} }
submatches := contentRangeRegexp.FindStringSubmatch(contentRange) submatches := contentRangeRegexp.FindStringSubmatch(contentRange)
if len(submatches) < 4 { if len(submatches) < 4 {
resp.Close()
return nil, fmt.Errorf("could not parse Content-Range header: %s", contentRange) return nil, fmt.Errorf("could not parse Content-Range header: %s", contentRange)
} }
startByte, err := strconv.ParseUint(submatches[1], 10, 64) startByte, err := strconv.ParseUint(submatches[1], 10, 64)
if err != nil { if err != nil {
resp.Close()
return nil, fmt.Errorf("could not parse start of range in Content-Range header: %s", contentRange) return nil, fmt.Errorf("could not parse start of range in Content-Range header: %s", contentRange)
} }
if startByte != uint64(hrs.readerOffset) { if startByte != uint64(hrs.readerOffset) {
resp.Close()
return nil, fmt.Errorf("received Content-Range starting at offset %d instead of requested %d", startByte, hrs.readerOffset) return nil, fmt.Errorf("received Content-Range starting at offset %d instead of requested %d", startByte, hrs.readerOffset)
} }
endByte, err := strconv.ParseUint(submatches[2], 10, 64) endByte, err := strconv.ParseUint(submatches[2], 10, 64)
if err != nil { if err != nil {
resp.Close()
return nil, fmt.Errorf("could not parse end of range in Content-Range header: %s", contentRange) return nil, fmt.Errorf("could not parse end of range in Content-Range header: %s", contentRange)
} }
@ -244,8 +243,11 @@ func (hrs *httpReadSeeker) reader() (io.Reader, error) {
} }
hrs.rc = resp.Body hrs.rc = resp.Body
} else { } else {
defer resp.Body.Close()
if hrs.errorHandler != nil { if hrs.errorHandler != nil {
// Closing the body should be handled by the existing defer,
// but in case a custom "errHandler" is used that doesn't return
// an error, we close the body regardless.
defer resp.Body.Close()
return nil, hrs.errorHandler(resp) return nil, hrs.errorHandler(resp)
} }
return nil, fmt.Errorf("unexpected status resolving reader: %v", resp.Status) return nil, fmt.Errorf("unexpected status resolving reader: %v", resp.Status)