# `ExOss.Runner`
[🔗](https://github.com/choice-form/ex_oss/blob/main/lib/ex_oss/runner.ex#L1)

Executes storage operations with an explicit client.

The `Runner` is the central dispatch layer between storage and CDN.
When a CDN is configured and enabled (`cdn_download: true` /
`cdn_upload: true`), download URLs and upload credentials are
routed through the CDN adapter. Otherwise, they fall back to S3
presigned URLs via `ExOss.Storage`.

## Usage with Explicit Client

    client = ExOss.Client.new(
      provider: :aws,
      access_key_id: "...",
      secret_access_key: "...",
      region: "us-east-1",
      cdn: [provider: :cloudfront, endpoint: "https://cdn.example.com", ...]
    )

    ExOss.Runner.public_url(client, "bucket", "file.jpg")
    ExOss.Runner.authorize_download_url(client, "bucket", "file.jpg", 3600, [])
    ExOss.Runner.upload_credential(client, "bucket", "file.jpg", 3600)

For config-based convenience methods, use `use ExOss` instead.

# `authorize_download_url`

```elixir
@spec authorize_download_url(
  ExOss.Client.Client.t(),
  binary(),
  binary(),
  non_neg_integer(),
  keyword()
) ::
  binary()
```

Generates a signed download URL.

If CDN is enabled and configured, routes to the CDN adapter
(e.g., CloudFront signed URL or Qiniu CDN signed URL).
Otherwise, falls back to S3 presigned URL.

## Options

  * `:att_name` — download filename for Content-Disposition
  * `:query_params` — additional query parameters (S3 only)
  * `:headers` — headers to include in signature (S3 only)

# `metadata`

```elixir
@spec metadata(ExOss.Client.Client.t(), binary(), binary()) ::
  {:ok, %{file_size: non_neg_integer(), mime_type: binary()}}
  | {:error, :no_metadata}
```

Retrieves metadata for a stored object.

# `mkzip_index_content`

```elixir
@spec mkzip_index_content(ExOss.Client.Client.t(), [
  %{access_address: binary(), alias_name: binary()}
]) ::
  binary()
```

Generates zip index content for mkzip operations.

# `public_url`

```elixir
@spec public_url(ExOss.Client.Client.t(), binary(), binary()) :: binary()
```

Generates a public (unsigned) URL using the download endpoint.

If CDN is enabled, uses the CDN endpoint; otherwise uses the
storage endpoint.

# `run`

```elixir
@spec run(ExOss.Client.Client.t(), ExOss.StorageTask.t()) ::
  {:ok, binary() | nil} | {:error, binary()}
```

Executes a storage task (upload, copy, delete, etc.).

See `ExOss.Storage.run/2` for supported task patterns.

# `upload_credential`

```elixir
@spec upload_credential(
  ExOss.Client.Client.t(),
  binary(),
  binary(),
  non_neg_integer()
) ::
  ExOss.UploadCredential.t()
```

Generates upload credentials for the given resource key.

If CDN is enabled and configured, routes to the CDN adapter.
Otherwise, falls back to S3 presigned PUT URL.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
