Skip to content

Commit 840d496

Browse files
authoredJan 22, 2025··
fix(internal/gensupport): close resp body only on discarding resp (resumableupload) (#2966)
internal, see: b/389767299
1 parent b0536b1 commit 840d496

File tree

1 file changed

+14
-4
lines changed

1 file changed

+14
-4
lines changed
 

‎internal/gensupport/resumable.go

+14-4
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ func (rx *ResumableUpload) transferChunk(ctx context.Context) (*http.Response, e
164164
// and calls the returned functions after the request returns (see send.go).
165165
// rx is private to the auto-generated API code.
166166
// Exactly one of resp or err will be nil. If resp is non-nil, the caller must call resp.Body.Close.
167+
// Upload does not parse the response into the error on a non 200 response;
168+
// it is the caller's responsibility to call resp.Body.Close.
167169
func (rx *ResumableUpload) Upload(ctx context.Context) (resp *http.Response, err error) {
168170

169171
// There are a couple of cases where it's possible for err and resp to both
@@ -256,6 +258,18 @@ func (rx *ResumableUpload) Upload(ctx context.Context) (resp *http.Response, err
256258
rCtx, cancel = context.WithTimeout(ctx, rx.ChunkTransferTimeout)
257259
}
258260

261+
// We close the response's body here, since we definitely will not
262+
// return `resp` now. If we close it before the select case above, a
263+
// timer may fire and cause us to return a response with a closed body
264+
// (in which case, the caller will not get the error message in the body).
265+
if resp != nil && resp.Body != nil {
266+
// Read the body to EOF - if the Body is not both read to EOF and closed,
267+
// the Client's underlying RoundTripper may not be able to re-use the
268+
// persistent TCP connection to the server for a subsequent "keep-alive" request.
269+
// See https://pkg.go.dev/net/http#Client.Do
270+
io.Copy(io.Discard, resp.Body)
271+
resp.Body.Close()
272+
}
259273
resp, err = rx.transferChunk(rCtx)
260274

261275
var status int
@@ -282,15 +296,11 @@ func (rx *ResumableUpload) Upload(ctx context.Context) (resp *http.Response, err
282296

283297
rx.attempts++
284298
pause = bo.Pause()
285-
if resp != nil && resp.Body != nil {
286-
resp.Body.Close()
287-
}
288299
}
289300

290301
// If the chunk was uploaded successfully, but there's still
291302
// more to go, upload the next chunk without any delay.
292303
if statusResumeIncomplete(resp) {
293-
resp.Body.Close()
294304
continue
295305
}
296306

0 commit comments

Comments
 (0)
Please sign in to comment.