S3-compatible storage client for bunny.net. Uses AWS Signature V4 signing
via Req's built-in put_aws_sigv4 step — no additional dependencies.
S3 must be enabled at storage zone creation time and cannot be toggled later.
Usage
client = Bunnyx.S3.new(zone: "my-zone", storage_key: "pw-...", region: "de")
{:ok, nil} = Bunnyx.S3.put(client, "images/logo.png", image_data)
{:ok, binary} = Bunnyx.S3.get(client, "images/logo.png")
{:ok, headers} = Bunnyx.S3.head(client, "images/logo.png")
{:ok, nil} = Bunnyx.S3.delete(client, "images/logo.png")
Summary
Functions
Aborts a multipart upload.
Completes a multipart upload.
Copies an object within the same storage zone.
Creates a multipart upload and returns the upload ID.
Deletes an object.
Downloads an object.
Returns object metadata (headers) without downloading the body.
Lists objects in the bucket using ListObjectsV2.
Lists in-progress multipart uploads for the bucket.
Lists parts uploaded for a multipart upload.
Creates a new S3 client.
Uploads an object.
Uploads a part for a multipart upload. Returns the ETag needed to complete the upload.
Types
@type t() :: %Bunnyx.S3{req: Req.Request.t(), zone: String.t()}
Functions
@spec abort_multipart_upload(t() | keyword(), String.t(), String.t()) :: {:ok, nil} | {:error, Bunnyx.Error.t()}
Aborts a multipart upload.
@spec complete_multipart_upload(t() | keyword(), String.t(), String.t(), [map()]) :: {:ok, %{etag: String.t() | nil, key: String.t() | nil}} | {:error, Bunnyx.Error.t()}
Completes a multipart upload.
parts is a list of %{part_number: integer, etag: string} maps.
@spec copy(t() | keyword(), String.t(), String.t()) :: {:ok, %{etag: String.t() | nil, last_modified: String.t() | nil}} | {:error, Bunnyx.Error.t()}
Copies an object within the same storage zone.
@spec create_multipart_upload(t() | keyword(), String.t()) :: {:ok, String.t()} | {:error, Bunnyx.Error.t()}
Creates a multipart upload and returns the upload ID.
@spec delete(t() | keyword(), String.t()) :: {:ok, nil} | {:error, Bunnyx.Error.t()}
Deletes an object.
Downloads an object.
Options
:range— byte range string (e.g."bytes=0-1023")
@spec head(t() | keyword(), String.t()) :: {:ok, map()} | {:error, Bunnyx.Error.t()}
Returns object metadata (headers) without downloading the body.
@spec list( t() | keyword(), keyword() ) :: {:ok, %{ contents: [map()], common_prefixes: [String.t()], is_truncated: boolean(), next_continuation_token: String.t() | nil }} | {:error, Bunnyx.Error.t()}
Lists objects in the bucket using ListObjectsV2.
Options
:prefix— filter by key prefix:delimiter— group keys by delimiter (e.g."/"for directory-like listing):continuation_token— pagination token from a previous response:max_keys— maximum number of keys to return (max 1000)
@spec list_multipart_uploads(t() | keyword()) :: {:ok, %{uploads: [map()], is_truncated: boolean()}} | {:error, Bunnyx.Error.t()}
Lists in-progress multipart uploads for the bucket.
@spec list_parts(t() | keyword(), String.t(), String.t()) :: {:ok, %{parts: [map()], is_truncated: boolean()}} | {:error, Bunnyx.Error.t()}
Lists parts uploaded for a multipart upload.
Creates a new S3 client.
Options
:zone(required) — storage zone name (also the S3 access key ID and bucket name):storage_key(required) — storage zone password (S3 secret access key):region(required) —"de","ny", or"sg":receive_timeout— socket receive timeout in milliseconds (default15_000):finch— a custom Finch pool name
@spec put(t() | keyword(), String.t(), binary(), keyword()) :: {:ok, nil} | {:error, Bunnyx.Error.t()}
Uploads an object.
Options
:checksum— SHA-256 checksum (Base64 encoded) for integrity verification
@spec upload_part(t() | keyword(), String.t(), String.t(), pos_integer(), binary()) :: {:ok, String.t()} | {:error, Bunnyx.Error.t()}
Uploads a part for a multipart upload. Returns the ETag needed to complete the upload.