Skip to main content

Crate s3lean

Crate s3lean 

Source
Expand description

A lean S3 client.

Most services that talk to object storage do four things — store an object, fetch one, check one, delete one — and hand out the occasional presigned URL. This crate does those, against Amazon S3 or anything that speaks its API (Cloudflare R2, MinIO, Backblaze B2, Wasabi, DigitalOcean Spaces, …), and nothing else. It brings no HTTP stack of its own: the core signs a request and hands you the method, URL, headers and body, and optional features adapt that to reqwest or ureq if you would rather not do it yourself.

use std::time::SystemTime;
use s3lean::{Client, Credentials};

let client = Client::new(
    "https://ACCOUNT_ID.r2.cloudflarestorage.com",
    "my-bucket",
    "auto",
    Credentials::new("ACCESS_KEY", "SECRET_KEY"),
)?;

let request = client
    .put("reports/2026-09.json", br#"{"ok":true}"#.to_vec())
    .content_type("application/json")
    .metadata("source", "nightly")
    .sign(SystemTime::now());

// `request.method`, `request.url`, `request.headers` and `request.body`
// are yours to send with any HTTP client.
assert_eq!(request.method, "PUT");

With the reqwest feature, SignedRequest::into_reqwest does the adapting; with ureq, SignedRequest::send_ureq sends it synchronously:

ⓘ
let http = reqwest::Client::new();
let response = request.into_reqwest(&http).send().await?;
assert!(response.status().is_success());

§What it does not do

Multipart uploads, listing, streaming bodies, and credential discovery from the environment or instance metadata. Those are what the SDKs are for; if you need them, use one. Bodies here are Vec<u8>, credentials are what you hand in, and an object is one request.

§Signing

Requests are signed with AWS Signature Version 4 in its S3 form: the object key is encoded segment by segment and not encoded a second time for the canonical request, and the payload hash is sent in x-amz-content-sha256. The signer reproduces the worked examples in the S3 documentation exactly (see the tests), and the crate’s CI runs every operation against a MinIO server.

Structs§

Client
A client bound to one bucket at one endpoint.
Credentials
An access key pair, with the session token that temporary credentials carry.
Request
One operation, being built. Every header added here is signed.
SignedRequest
A request ready to send: everything the wire needs and nothing tied to any HTTP client. headers includes host, x-amz-date, x-amz-content-sha256 and authorization; a client that sets Host itself from the URL will set it to the same value.

Enums§

Addressing
How the bucket appears in the request.
Error
What can go wrong before a request is sent. Everything after that is the HTTP client’s error type, which this crate does not wrap.