HTTP client for S3-compatible cloud storage (AWS S3, Cloudflare R2, MinIO, S3-compatible).
Handles:
put_object/5— upload to remote bucket (streaming via binary)get_object/2— download from remote buckethead_object/2— check existence and metadatadelete_object/2— delete from remote buckettest_connection/1— HEAD on bucket to verify credentials/reachability
All requests are signed with AWS Signature Version 4.
Region used for SigV4 signing:
:aws— usesconfig.region(defaultus-east-1):r2— always"auto"(Cloudflare requirement):minio— usesconfig.region(defaultus-east-1; value is arbitrary for MinIO):s3_compat— usesconfig.region
Summary
Functions
Delete an object from the remote S3/R2 bucket.
Download an object from the remote S3/R2 bucket.
Get metadata (headers) for an object without downloading the body.
List objects in the remote bucket, using S3 ListObjectsV2.
Upload an object to the remote S3/R2 bucket.
Test connectivity by calling HEAD on the remote bucket.
Functions
@spec delete_object(ExStorageService.CloudCache.Config.t(), String.t()) :: :ok | {:error, term()}
Delete an object from the remote S3/R2 bucket.
Returns :ok for both successful deletes and 404 (idempotent).
@spec get_object(ExStorageService.CloudCache.Config.t(), String.t()) :: {:ok, binary()} | {:error, :not_found | term()}
Download an object from the remote S3/R2 bucket.
Returns {:ok, body_binary} on success,
{:error, :not_found} for 404, or {:error, reason}.
@spec head_object(ExStorageService.CloudCache.Config.t(), String.t()) :: {:ok, map()} | {:error, :not_found | term()}
Get metadata (headers) for an object without downloading the body.
Returns {:ok, headers_map} with at least :content_length, :etag,
:content_type, :last_modified.
@spec list_objects( ExStorageService.CloudCache.Config.t(), keyword() ) :: {:ok, %{ keys: [{String.t(), map()}], common_prefixes: [String.t()], truncated: boolean(), next_continuation_token: String.t() | nil }} | {:error, term()}
List objects in the remote bucket, using S3 ListObjectsV2.
Options:
:prefix— key prefix to filter (default""):delimiter— delimiter for virtual folders (default"/"):max_keys— max results (default 1000):continuation_token— pagination token
Returns {:ok, %{keys: [{key, meta}], common_prefixes: [prefix], truncated: bool}}
where meta is %{size: integer, last_modified: string, etag: string}.
@spec put_object( ExStorageService.CloudCache.Config.t(), String.t(), iodata(), String.t(), map() ) :: :ok | {:error, term()}
Upload an object to the remote S3/R2 bucket.
Returns :ok on success, {:error, reason} on failure.
@spec test_connection(ExStorageService.CloudCache.Config.t()) :: :ok | {:error, term()}
Test connectivity by calling HEAD on the remote bucket.
Returns :ok if reachable, {:error, reason} otherwise.