s3-wire
Async, streaming S3-compatible client for Rust with explicit bounds on memory, retries, timeouts, and remote input.
Highlights
- Tokio-native uploads and downloads with backpressure
- Replay-aware retries for in-memory and file-backed request bodies
- Managed multipart uploads with bounded concurrency and abort cleanup
- SigV4 request signing and presigned GET and PUT URLs
- Typed object keys, ranges, conditions, checksums, and multipart state
- HTTPS by default, secret-redacting types, and bounded XML parsing
- Integration-tested against pinned MinIO, RustFS, and SeaweedFS releases
s3-wire requires Rust 1.97.1 and does not depend on another S3 client.
Install
Quick start
The default credential provider reads AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and optional AWS_SESSION_TOKEN. Remote endpoints must use HTTPS; plain HTTP is an explicit local-testing opt-in.
use ;
async
Run the complete CRUD, range, listing, and conditional-write example with:
The example uses the standard AWS credential variables plus S3_BUCKET, and supports both AWS and custom endpoints.
Configuration and credentials
S3Config validates addressing, timeouts, retry policy, response limits, multipart bounds, and the credential provider before a client is created:
use Arc;
use Duration;
use ;
The default EnvironmentCredentialsProvider needs no explicit configuration. Use StaticCredentialsProvider for an injected immutable value, or implement the async CredentialsProvider trait for a workload-specific source. CachedCredentialsProvider coalesces concurrent refreshes and respects credential expiration.
Upload sources
Choose a body based on how it should behave if a request must be retried:
| Source | Replayable | Memory behavior | Notes |
|---|---|---|---|
ByteStream::from_bytes |
Yes | Retains the input bytes | Best for small, already-buffered values |
ByteStream::from_path |
Yes | Streams from a private disk snapshot | Requires temporary disk space |
ByteStream::from_stream |
No | Streams with backpressure | Caller supplies exact length and SHA-256 |
File uploads are hashed into an immutable temporary snapshot before the first request. A retry therefore sends the same bytes even if the original file changes.
Multipart uploads
Managed multipart handles part scheduling, bounded in-flight bytes, completion, and best-effort abort cleanup:
use ;
async
Multipart selection is intentional: put_object never switches modes automatically. Call multipart_upload when application policy says a source should use multipart. Primitive create, upload-part, complete, list, and abort operations are also available when the application must own multipart state.
Dropping a managed upload cancels outstanding parts and attempts an abort after an upload ID exists. Process termination can still leave stale uploads, so long-running deployments should also run bounded stale-upload cleanup.
Listing and presigning
list_objects_v2_all follows continuation tokens up to a caller-supplied page limit. presigned_get and presigned_put return a redacted PresignedUrl:
use Duration;
use ;
async
Presigned URLs are bearer credentials. Keep their lifetime short and do not place exposed URLs in logs, analytics, or error messages.
Error handling
S3Error separates a stable category from optional service metadata. Its Display and Debug implementations omit transport text and cleanup details that may contain credentials or signed URLs:
use ;
Retries are applied inside the client only when the classification, attempt and elapsed-time limits, operation deadline, and body replayability all permit another attempt.
Examples
Focused, runnable examples live in examples/README.md:
- Basic object lifecycle
- Streaming download to a file
- One-shot streaming upload
- Managed multipart upload
- Presigned GET and PUT
- Copy and batch delete
- Content-addressed artifact-store adapter
Compatibility
The client currently covers object upload, download, inspection, deletion, batch deletion, server-side copy, listing, range reads, conditional headers, presigning, and primitive or managed multipart uploads.
The pinned MinIO, RustFS, and SeaweedFS suites run in CI. An opt-in AWS suite exists but has not yet been executed for this release, so compatible-server results are not presented as proof of AWS compatibility. See S3 compatibility for the operation matrix, checksum behavior, test status, and unsupported API families.
Scope and limits
- The client is async-only and configured for one bucket at a time.
- AWS chunked SigV4 streaming is not implemented.
- Automatic upload-checksum calculation currently supports SHA-256.
- Managed multipart does not expose a destination
If-None-Matchcondition. - Bucket administration, ACLs, policies, version listing, metadata-service credentials, and encryption configuration are outside the current API.
See the security model for deployment responsibilities and architecture for retry, transport, and ownership details.
Documentation
| Guide | What it covers |
|---|---|
| API reference | Public types, methods, and crate-level quick start |
| Architecture | Modules, request flow, retry rules, and transfer ownership |
| S3 compatibility | Operations, signing, checksums, tested services, and non-goals |
| Security model | Trust boundaries, controls, secret handling, and operator duties |
| Testing | Local checks, MinIO, AWS, property tests, fuzzing, and benchmarks |
| Performance and size | Retained measurements, reproduction, and interpretation |
| sandboxd integration | Content-addressed publication, reads, garbage collection, and cleanup |
| Examples | Runnable object, streaming, multipart, presigning, and integration flows |
| Releasing | Package validation, tagging, publication, and post-release checks |
Also see the API example, security reporting, and contributing.
Development
Run the fast validation set after local changes:
RUSTDOCFLAGS="-D warnings"
The pinned endpoint suites run with ./scripts/test-s3-compat.sh <minio|rustfs|seaweedfs>. Packaging and release checks are described in testing.
License
Licensed under the Apache License 2.0.