Skip to content

Commit 16bc458

Browse files
committed
fix(storage): send Content-Length on empty GCS multipart part
A zero-length *bytes.Reader is "unknown length" to net/http and is sent chunked, which S3-compatible XML backends reject with 411. Pass no body for empty parts so Content-Length: 0 is sent instead.
1 parent 5105c2e commit 16bc458

1 file changed

Lines changed: 9 additions & 2 deletions

File tree

‎packages/shared/pkg/storage/gcp_multipart.go‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,13 +302,20 @@ func (m *MultipartUploader) uploadPart(ctx context.Context, uploadID string, par
302302
url := fmt.Sprintf("%s/%s?partNumber=%d&uploadId=%s",
303303
m.baseURL, m.objectName, partNumber, uploadID)
304304

305-
req, err := retryablehttp.NewRequestWithContext(ctx, "PUT", url, bytes.NewReader(data))
305+
// A non-nil zero-length body counts as "unknown length" to net/http and
306+
// is sent chunked, which S3-compatible XML backends reject with 411. Pass
307+
// no body for empty parts so Content-Length: 0 is sent instead.
308+
var body any
309+
if len(data) > 0 {
310+
body = bytes.NewReader(data)
311+
}
312+
313+
req, err := retryablehttp.NewRequestWithContext(ctx, "PUT", url, body)
306314
if err != nil {
307315
return "", err
308316
}
309317

310318
req.Header.Set("Authorization", "Bearer "+m.token)
311-
req.Header.Set("Content-Length", fmt.Sprintf("%d", len(data)))
312319
sum := md5.Sum(data) //nolint:gosec // GCS multipart uses Content-MD5 for transport integrity.
313320
req.Header.Set("Content-MD5", base64.StdEncoding.EncodeToString(sum[:]))
314321

0 commit comments

Comments
 (0)