Skip to content

fix(s3): include checksum headers in object responses#4

Merged
tyrchen merged 13 commits intomasterfrom
fix/s3-checksum-response
Mar 10, 2026
Merged

fix(s3): include checksum headers in object responses#4
tyrchen merged 13 commits intomasterfrom
fix/s3-checksum-response

Conversation

@tyrchen
Copy link
Owner

@tyrchen tyrchen commented Mar 10, 2026

Summary

  • Auto-compute CRC32 checksum during PutObject when no client checksum is provided (matching AWS S3 default behavior)
  • Populate x-amz-checksum-* headers in GetObject, HeadObject, and PutObject responses from stored checksum data
  • Preserve source object checksums during CopyObject operations

Closes #3

Test plan

  • Run existing unit and integration tests (cargo test)
  • Start ruststack with S3 service and verify with Go AWS SDK v2 client that GetObject no longer produces "Response has no supported checksum" warning
  • Verify PutObject response includes x-amz-checksum-crc32 header
  • Verify GetObject/HeadObject responses include the stored checksum header
  • Test with client-provided checksums (CRC32C, SHA256) to verify they are preserved and returned correctly

🤖 Generated with Claude Code

tyrchen and others added 13 commits March 9, 2026 20:42
…esponses

When no client-provided checksum is sent during PutObject, auto-compute
CRC32 (matching AWS S3 default behavior). Populate checksum fields in
GetObject, HeadObject, and PutObject responses from stored checksum data.
Also preserve source object checksums during CopyObject.

Closes #3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ributes

- Gate checksum headers in GetObject/HeadObject behind ChecksumMode=ENABLED
  (matching AWS behavior; modern SDKs send this header automatically)
- Validate client-provided checksums against server-computed values on PutObject,
  returning BadDigest on mismatch
- Reject requests with multiple checksum headers (InvalidArgument)
- Populate checksum data in GetObjectAttributes response
- Add CRC64NVME support to checksum field mapping

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add crc64fast-nvme dependency for hardware-accelerated CRC-64/NVME
- Add Crc64Nvme variant to ChecksumAlgorithm enum with compute/streaming support
- Add checksum_type field to ChecksumData (FULL_OBJECT or COMPOSITE)
  with serde default for backward compatibility
- Update all checksum field mappings to include CRC64NVME
- Use stored checksum_type instead of hardcoding FULL_OBJECT in responses

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 3: Refactor decode_aws_chunked() to return AwsChunkedResult with
both the decoded body and trailing headers. Trailing headers (e.g.
x-amz-checksum-*) sent after the chunked body are now parsed and
injected into the request headers so downstream checksum validation
picks them up. The x-amz-trailer-signature header is silently skipped.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 4: Store and validate checksums for multipart upload parts.
CreateMultipartUpload now stores checksum_type based on the algorithm
(CRC64NVME forces FULL_OBJECT, SHA-1/SHA-256 force COMPOSITE).
UploadPart extracts, validates, and stores per-part checksums.
CompleteMultipartUpload computes the composite checksum from part
checksums and stores it on the final object. ListParts returns per-part
checksum values.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix double-call to extract_checksum_from_put in handle_put_object by
  saving the is_client_provided flag before shadowing the Option
- Fix GetObjectAttributes hardcoding ChecksumType::FullObject; now reads
  the stored checksum_type from ChecksumData (correctly returns COMPOSITE
  for multipart objects)
- Remove dead identical branch in CompleteMultipartUpload that claimed to
  handle FULL_OBJECT differently but computed the same composite checksum

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When serving a range request (HTTP 206), do not return the full-object
checksum in the response headers. The checksum covers the entire object
data, not the requested byte range, causing SDK checksum validation to
fail with ChecksumMismatch. This matches AWS S3 behavior where checksums
are omitted for partial content responses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rove CI diagnostics

Replace hardcoded allowlist of x-amz-content-sha256 placeholder values
with prefix-based matching (STREAMING-*, UNSIGNED-PAYLOAD-*) to handle
future AWS SDK signing variants (SigV4a, CRT-based, etc.).

Remove continue-on-error from Bucket Config CI step and add server log
dump on failure to diagnose the pre-existing put-bucket-cors issue.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Change LOG_LEVEL from warn to info to capture request logs
- Add 2>&1 to put-bucket-cors to show stderr in CI output
- Increase server log dump to 500 lines

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…fig command

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…Website

GetBucketWebsite was returning hardcoded empty fields instead of the
actual stored configuration. PutBucketWebsite was storing a dummy JSON
blob instead of the real config. Replace opaque serde_json::Value
with typed WebsiteConfig struct and wire up both handlers correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove verbose diagnostic output now that the underlying issue (empty
GetBucketWebsite response) is fixed. Restore LOG_LEVEL=warn. Keep the
server log dump step for future debugging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@tyrchen tyrchen merged commit 53f30fb into master Mar 10, 2026
12 checks passed
@tyrchen tyrchen deleted the fix/s3-checksum-response branch March 10, 2026 06:34
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.

s3/GetObject: Response has no supported checksum. Not validating response payload.

1 participant