Skip to content

v2.0.0

@achempion achempion tagged this 24 Aug 08:34
- Replace the required Hackney dependency with the optional Req adapter.
- Add a pluggable HTTP-client behaviour for remote downloads.
- Retain `Waffle.StorageBehavior` as a compatibility name for storage adapters.
  `Waffle.Storage` is a preferred name.
- Limit remote downloads to 50 MiB by default.
- Return structured `%Waffle.HTTPClient.Error{}` values for HTTP failures.
- Compile cleanly without optional Req or ExAws dependencies.
- Allow the temporary directory to be configured with `:tmp_dir`.
- Support RFC 6266 `filename*` parameters and reject unsafe filenames from
  remote `Content-Disposition` headers.
- Require Elixir 1.15 or later.

Applications that download remote URLs must add and configure Req:

```elixir
{:req, "~> 0.7"}
```

```elixir
config :waffle,
  http_client: Waffle.HTTPClient.Req
```

Configuration names changed as follows:

| Waffle 1.x        | Waffle 2.0              |
|-------------------|-------------------------|
| `recv_timeout`    | `receive_timeout_ms`    |
| `connect_timeout` | `connect_timeout_ms`    |
| `max_body_length` | `max_body_length_bytes` |
| `backoff_factor`  | `backoff_factor_ms`     |
| `backoff_max`     | `backoff_max_ms`        |

The first retry delay now equals `backoff_factor_ms`. In Waffle 1.x, it was
half of `backoff_factor` because retry counting started at zero.

Remote downloads previously always followed redirects. Waffle 2.0 adds
`max_redirects`, which defaults to `3`; set it to `nil` to disable redirects.

Request options also moved under the `:request` key. `max_retries` keeps its
name.

Before:

```elixir
config :waffle,
  recv_timeout: 5_000,
  connect_timeout: 10_000,
  max_body_length: :infinity,
  max_retries: 3,
  backoff_factor: 1_000,
  backoff_max: 30_000
```

After:

```elixir
config :waffle,
  http_client: Waffle.HTTPClient.Req,
  request: [
    max_redirects: 3,
    max_retries: 3,
    receive_timeout_ms: 5_000,
    connect_timeout_ms: 10_000,
    max_body_length_bytes: 50 * 1024 * 1024,
    backoff_factor_ms: 1_000,
    backoff_max_ms: 30_000
  ]
```

The new example shows the Waffle 2.0 defaults. Set
`max_body_length_bytes: nil` to preserve the previous unlimited behaviour.

Remote-download errors also changed shape.

Before:

```elixir
{:error, :timeout}
{:error, :recv_timeout}
{:error, :waffle_hackney_error}
{:error, {:waffle_hackney_error, response}}
```

After:

```elixir
@type remote_download_error ::
        {:error,
         %Waffle.HTTPClient.Error{
           error:
             :timeout
             | {:unexpected_status, Waffle.HTTPClient.status()}
             | :response_body_limit_exceeded
             | :http_client,
           error_context: term()
         }}
```

Connect and receive timeouts are now both reported as `:timeout`. Callers that
pattern-match on remote-download errors must update their matches.

S3 users who relied on Waffle providing Hackney must configure an ExAws HTTP
client. With ExAws 2.7 or newer:

```elixir
config :ex_aws,
  http_client: ExAws.Request.Req
```

Applications that use neither remote URL downloads nor S3 need no HTTP-client
dependency.
Assets 2
Loading