Skip to content

fix(s3): implement S3-compliant CORS and bucket existence checks#2026

Merged
overtrue merged 2 commits intomainfrom
fix/s3-compat-post-object-and-delete
Mar 1, 2026
Merged

fix(s3): implement S3-compliant CORS and bucket existence checks#2026
overtrue merged 2 commits intomainfrom
fix/s3-compat-post-object-and-delete

Conversation

@overtrue
Copy link
Collaborator

@overtrue overtrue commented Mar 1, 2026

Summary

  • CORS middleware refactor: Replace generic hardcoded CORS headers with bucket-level CORS configuration for S3 paths. OPTIONS preflight now returns proper 400/403 status codes per the S3 CORS spec. Non-preflight requests also respect Access-Control-Request-Method header for CORS matching.
  • DeleteObject bucket check: Return NoSuchBucket (404) instead of AccessDenied (403) when deleting from a non-existent bucket, by checking bucket existence before authorization.
  • Tag conditions fix: Handle bucket_not_found in get_object_tag_conditions_for_policy to return NoSuchBucket instead of AccessDenied.

Changes

File Change
rustfs/src/server/layer.rs Refactor ConditionalCorsService to use bucket-level CORS for S3 paths; generic CORS only for admin/console
rustfs/src/storage/ecfs_extend.rs Use Access-Control-Request-Method for all requests, not just preflight
rustfs/src/storage/access.rs Add bucket existence check before auth in delete_object
rustfs/src/storage/ecfs.rs Handle bucket_not_found in tag conditions
rustfs/src/storage/ecfs_test.rs Add 5 unit tests for CORS origin pattern matching
rustfs/src/server/layer.rs (tests) Add 3 unit tests for S3 path detection and generic CORS layer

Test plan

  • All 14 newly passing S3 compatibility tests verified:
    • CORS: test_set_cors, test_cors_origin_response, test_cors_origin_wildcard, test_cors_header_option, test_cors_presigned_get_object, test_cors_presigned_get_object_tenant, test_cors_presigned_put_object, test_cors_presigned_put_object_with_acl, test_cors_presigned_put_object_tenant, test_cors_presigned_put_object_tenant_with_acl
    • HTTP: test_100_continue, test_abort_multipart_upload_not_found, test_post_object_tags_authenticated_request
    • DeleteObject: test_object_delete_key_bucket_gone
  • All 298 existing implemented tests pass (no regressions)
  • 8 new unit tests pass
  • cargo fmt --all --check passes
  • cargo clippy --all-targets --all-features -- -D warnings passes
  • cargo test --workspace --exclude e2e_test passes

Made with Cursor

- Refactor CORS middleware to use bucket-level CORS configuration for
  S3 paths instead of generic hardcoded methods. OPTIONS preflight
  returns 400 for missing headers, 403 for non-matching rules.
- Support Access-Control-Request-Method header on all requests (not
  just preflight) for CORS rule matching, matching AWS S3 behavior.
- Return NoSuchBucket (404) instead of AccessDenied (403) for
  DeleteObject on non-existent buckets by checking bucket existence
  before authorization.
- Handle bucket-not-found in get_object_tag_conditions_for_policy to
  return NoSuchBucket instead of AccessDenied.
- Add unit tests for CORS origin pattern matching, S3 path detection,
  and generic CORS layer behavior.
- Move 14 newly passing tests from non_standard to implemented list
  (379 → 393 total).

Made-with: Cursor
Copilot AI review requested due to automatic review settings March 1, 2026 07:25
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves S3 compatibility by aligning CORS behavior with S3 bucket-level CORS configuration and correcting error codes for bucket-not-found scenarios (notably for DeleteObject and policy tag condition evaluation). It also updates the s3-tests allowlist/non-standard lists to reflect newly supported tests and adds unit coverage for CORS matching/path detection.

Changes:

  • Refactor server CORS handling to apply bucket-level CORS rules for S3 paths (including OPTIONS preflight) while keeping generic CORS for admin/console paths.
  • Adjust S3 error mapping to return NoSuchBucket when appropriate (DeleteObject pre-check, tag condition evaluation).
  • Promote previously non-standard s3-tests to implemented and add unit tests for CORS origin wildcard matching and S3-path detection.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
scripts/s3-tests/non_standard_tests.txt Removes now-supported CORS/HTTP/DeleteObject tests from the non-standard list.
scripts/s3-tests/implemented_tests.txt Adds newly supported tests to the implemented list and updates summary comments.
rustfs/src/storage/ecfs_test.rs Adds unit tests for matches_origin_pattern wildcard behaviors.
rustfs/src/storage/ecfs_extend.rs Updates CORS method matching to prefer Access-Control-Request-Method when present.
rustfs/src/storage/ecfs.rs Maps bucket_not_found during tag-condition fetching to NoSuchBucket.
rustfs/src/storage/access.rs Adds a bucket existence check before authorization in delete_object.
rustfs/src/server/layer.rs Refactors conditional CORS service behavior + adds tests for S3 path detection and generic CORS behavior.

- Only return NoSuchBucket for actual bucket_not_found errors (not
  transient storage errors) using is_err_bucket_not_found check.
- Remove eager path_trimmed allocation; compute bucket segment lazily
  inside the CORS branch to reduce per-request overhead.

Made-with: Cursor
@overtrue overtrue merged commit 8aecc72 into main Mar 1, 2026
13 checks passed
@overtrue overtrue deleted the fix/s3-compat-post-object-and-delete branch March 1, 2026 08:02
houseme added a commit that referenced this pull request Mar 1, 2026
…anup

* 'main' of github.com:rustfs/rustfs:
  fix(s3): return InvalidRange when CopySourceRange exceeds source object size (#2029)
  fix(s3): implement S3-compliant CORS and bucket existence checks (#2026)
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