# Crate ezs3

Simple AWS-S3-compatible operations.

(c) d2718 (codeberg.org/d2718) \
MIT License

S3 is a huge and sprawling API. If all you want to do is

* list objects in a bucket
* upload objects to the bucket
* download objects from the bucket
* delete objects in the bucket

then this simple crate is for you. This is the 3% of the functionality
that you need in probably 60% of the use cases.

# Quickstart

To instantiate your `Client`, you need these pieces of information:

  * `aws_access_key_id`
  * `aws_secret_access_key`
  * `aws_region`
  * `aws_endpoint_url_s3`
  * `bucket_name`

They can be supplied in a JSON-formatted configuration file, through
environemnt variables, or some combination of the two. You
may wish to put the less-sensitive information in a config file while
supplying the "secrets" via the environment, e.g.:

`config.json`:
```json
{
  "aws_region": "auto",
  "aws_endpoint_url_s3": "https://t3.storage.dev",
  "bucket_name": "my-app-bucket"
}
```

environment variables:
```text
AWS_ACCESS_KEY_ID="tqx4..."
AWS_SECRET_ACCESS_KEY="0x9_4..."
```

and then in your program

```rust
# async fn run() {
use ezs3::Client;

let client = Client::configure(Some("config.json")).expect("oops");
# }
```

## Note

  * Keys in the JSON configuration file are expected to be in lower-case;
    environment variable names are expected to be in upper-case.
  * If a given value is supplied in _both_ the configuration file and as
    an environment variable, the environment variable will take precedence.

# Use

Once your `Client` is instantiated, operations are pretty easy.

```rust
use ezs3::Client;

async fn example() -> eyre::Result<()> {
    let client = Client::configure(Some("config.json"))?;

    let bytes = std::fs::read("portait_of_cat.jpg")?;
    client.upload("portrait_of_cat.jpg", bytes, "image/jpeg").await?;

    let listing = client.list().await?;
    println!("{:#?}", &listing);

    Ok(())
}
```

Should yield something like:

```text
[
    ObjectData {
        key: "portrait_of_cat.jpg",
        etag: "\"01fabcfc4fca973fada9f9a9e03ed2a2\"",
        size: 242232,
        storage_class: Standard,
        last_modified: 2026-06-21T13:20:35Z,
    },
]
```

## Another Note

As suggested by the method signatures and syntax of the examples, all of
these operations are asynchronous; the underlying
[`reqwest`](https://docs.rs/reqwest/latest/reqwest/) crate uses
[`tokio`](https://docs.rs/tokio/1.52.3/tokio/), so use `tokio`.