# Amazon S3 Client

The `:std/net/s3` library provides basic support for interfacing with Amazon S3 and
compatible services.

::: warning
Only HTTPS is currently supported
:::

## Creating a Client

The primary way to interact with S3 via this library is with the `S3` interface.

To create an instance of an `S3` client, use the `S3Client` constructor:

```scheme
(S3Client
  endpoint: (endpoint "s3.amazonaws.com")
  access-key: (access-key (getenv "AWS_ACCESS_KEY_ID" #f))
  secret-key: (secret-key (getenv "AWS_SECRET_KEY" #f))
  region: (region (getenv "AWS_DEFAULT_REGION" "us-east-1")))
```

If `access-key` or `secret-key` aren't passed in and cannot be retrieved from the
environment (via `AWS_ACCESS_KEY_ID` and `AWS_SECRET_KEY` respectively) a `S3Error` is
raised.

## Client

The `S3` interface has the following signature:
```scheme
(interface S3
  (get-bucket (name :~ string?))
  (create-bucket! (name :~ string?))
  (delete-bucket! (name :~ string?))
  (bucket-exists? (name :~ string?))
  (list-buckets))
```

## S3-get-bucket

```scheme
(S3-get-bucket client bucket-name) -> S3Bucket
```

`S3-get-bucket` retrieves a `S3Bucket` instance by name. If the bucket does not exist, a
`S3Error` is raised. Buckets are searched for in the service and region provided to
`S3Client`'s `endpoint` and `region` arguments.

## S3-create-bucket!

```scheme
(S3-create-bucket! client bucket-name) -> S3Bucket
```

`S3-create-bucket!` creates a new bucket in the service and region the client was
instantiated with. If a bucket with the name already exists, a `S3Error` is raised
indicating there was a conflict. If the bucket is successfully created, an instance of
`S3Bucket` corresponding to the newly created bucket is returned.

## S3-delete-bucket!

```scheme
(S3-delete-bucket! client bucket-name) -> void
```

`S3-delete-bucket!` attempts to delete a bucket with the given name. `delete-bucket!` is
idempotent and will **not** error if the bucket does not exist.

## S3-bucket-exists?

```scheme
(S3-bucket-exists? client bucket-name) -> bool
```

`S3-bucket-exists?` checks if a bucket with the provided name exists in the client's
configured region and endpoint. It returns `#t` if a bucket exists and `#f` otherwise.

## S3-list-buckets

```scheme
(S3-list-buckets client) -> list : S3Bucket
```

`S3-list-buckets` returns a list of all buckets available to the client as configured. If
none are available, an empty list is returned. All buckets are instances of `S3Bucket`.

## S3Bucket

The `S3Bucket` interface provides a consistent way to interact with buckets.

```scheme
(interface S3Bucket
  (get  (name :~ string?))
  (put! (name :~ string?)
        (data :~ u8vector?))
  (delete! (name :~ string?))
  (copy-to! (src :~ string?) (dest :~ string?))
  (list-objects))
```
## S3Bucket-get

```scheme
(S3Bucket-get bucket object-name) -> u8vector
```

`S3Bucket-get` retrieves a object by name. If the object does not exist or the client
does not have permission to retrieve the object, an `S3Error` is raised.

## S3Bucket-put!

```scheme
(S3Bucket-put! bucket object-name) -> void
```

`S3Bucket-put!` stores `data` in a object with the provided `name`. Any failures result
in a `S3Error` being raised. All data is stored with `content-type: "octet-stream"` MIME
type.

## S3Bucket-delete!

```scheme
(S3Bucket-delete! bucket object-name) -> void
```

`S3Bucket-delete!` delete's an object with the provided `name`. If the object does not
exist, an `S3Error` is raised.

## S3Bucket-copy-to!

```scheme
(S3Bucket-copy-to! bucket src dest) -> void
```

`S3Bucket-copy-to!` performs server-side copy of object described by `src`. The `src`
format is `<bucket>/<objectname>`. The `dest` is the same as if performing a `put!` and
will store the object in the current `S3Bucket`. Copies must be within a region and
otherwise possible to perform using the `S3` client this bucket was created with.
Any failures result in a `S3Error` being raised.

## S3Bucket-list-objects

```scheme
(S3Bucket-list-objects bucket) -> list : string
```

`S3Bucket-list-objects` enumerates all objects in the bucket, returning their names as
strings.
