Skip to content

fix(upload): opt out of flexible checksum headers for SDA inbox compatibility#689

Open
jhagberg wants to merge 2 commits into
mainfrom
fix/658-transfermanager-checksum-optout
Open

fix(upload): opt out of flexible checksum headers for SDA inbox compatibility#689
jhagberg wants to merge 2 commits into
mainfrom
fix/658-transfermanager-checksum-optout

Conversation

@jhagberg
Copy link
Copy Markdown
Contributor

Related issue(s) and PR(s)
Follow-up to #682 (the transfermanager migration for #658). Fixes a regression spotted in Codex review of that PR.

Description
After #682 moved uploads to feature/s3/transfermanager, small (single-part) uploads suddenly carried the AWS flexible-checksum headers (x-amz-sdk-checksum-algorithm: CRC32, x-amz-checksum-crc32, x-amz-trailer) — even though the s3 client is built with RequestChecksumCalculationWhenRequired, which is supposed to suppress them.

What's going on: transfermanager.New runs resolveChecksumAlgorithm after applying user options, so an unset ChecksumAlgorithm gets rewritten to CRC32 at construction time. From then on the transfer manager's own value wins over the s3 client setting and ends up on the PutObjectInput. The old (now-deprecated) manager path didn't do this, so SDA-style inbox endpoints that don't accept flexible checksums started rejecting normal small uploads after the migration.

The fix is a per-call optFn on UploadObject that resets ChecksumAlgorithm back to "". Per-call optFns run on a copy of the client options and execute before the upload reads the field, so the empty value sticks and no x-amz-sdk-checksum-algorithm / x-amz-checksum-* / x-amz-trailer headers go out. The multipart path reads the same field, so this also clears the headers from CreateMultipartUpload and UploadPart requests.

How to test

  • go test ./upload/... -count=1. The new test TestUploadSinglePartDoesNotSendFlexibleChecksumHeaders wraps the gofakes3 mock with a handler that captures the real PUT request headers, then asserts the three flexible-checksum headers are absent.
  • End-to-end: run sda-cli upload <small-file> against an SDA inbox that was rejecting uploads after [upload,list] Migrate to feature/s3/transfermanager #682 landed, and confirm it now succeeds.

@jhagberg jhagberg requested a review from a team as a code owner April 24, 2026 15:54
Comment thread upload/upload.go Outdated
ContentEncoding: aws.String(config.Encoding),
}, func(o *transfermanager.Options) {
// Preserve RequestChecksumCalculationWhenRequired for S3-compatible inboxes.
o.ChecksumAlgorithm = ""
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
o.ChecksumAlgorithm = ""
o.ChecksumAlgorithm = types.ChecksumAlgorithm("")

To ensure the field is typed correctly by using a explicit conversion or the empty string variant of the type:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in eca7598, pushed. Agreed the explicit conversion reads better — the bare "" only compiles because Go assigns untyped string constants to named string types automatically, and that's not a rule anyone wants to think about mid-review. Added the types import too.

jhagberg added 2 commits May 28, 2026 10:46
…tibility

After #682 moved uploads to feature/s3/transfermanager, single-part
PUTs started carrying x-amz-sdk-checksum-algorithm / x-amz-checksum-*
/ x-amz-trailer headers even though the s3 client is configured with
RequestChecksumCalculationWhenRequired. transfermanager.New resolves
an unset ChecksumAlgorithm to CRC32, after which its own value wins
over the s3 client setting on PutObjectInput.

Reset ChecksumAlgorithm to "" via a per-call optFn on UploadObject;
the empty value also propagates to CreateMultipartUpload and
UploadPart, so the opt-out covers both single- and multipart paths.

New test wraps the gofakes3 mock to capture real PUT headers and
asserts none of the flexible-checksum headers are sent.
Address review feedback from @nanjiangshu — assign the empty value
through the named type rather than relying on untyped-string-to-named-
type assignability. Functionally identical, just clearer at the call
site.
@jhagberg jhagberg force-pushed the fix/658-transfermanager-checksum-optout branch from eca7598 to f8dae2c Compare May 28, 2026 08:47
Copy link
Copy Markdown
Contributor

@nanjiangshu nanjiangshu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants