# `locus_http_download`
[🔗](https://github.com/g-andrade/locus/blob/2.3.15/src/locus_http_download.erl#L24)

Downloads a file using HTTP(S) without blocking the caller.

# `body`

```erlang
-type body() :: binary().
```

# `event`

```erlang
-type event() ::
          event_request_sent() |
          event_download_dismissed() |
          event_download_redirected() |
          event_download_failed_to_start() |
          event_download_started() |
          event_download_finished().
```

# `event_download_dismissed`

```erlang
-type event_download_dismissed() :: {download_dismissed, full_http_response()}.
```

# `event_download_failed_to_start`

```erlang
-type event_download_failed_to_start() ::
          {download_failed_to_start, reason_for_download_failing_to_start()}.
```

# `event_download_finished`

```erlang
-type event_download_finished() ::
          {download_finished, BodySize :: non_neg_integer(), {ok, TrailingHeaders :: headers()}} |
          {download_finished, BodySize :: non_neg_integer(), {error, term()}} |
          {download_finished, BodySize :: non_neg_integer(), {error, timeout}}.
```

# `event_download_redirected`

```erlang
-type event_download_redirected() :: {download_redirected, redirection()}.
```

# `event_download_started`

```erlang
-type event_download_started() :: {download_started, headers()}.
```

# `event_request_sent`

```erlang
-type event_request_sent() :: {request_sent, url(), headers()}.
```

# `full_http_response`

```erlang
-type full_http_response() :: {http, response_status(), headers(), body()}.
```

# `headers`

```erlang
-type headers() :: [{string(), string()}].
```

# `msg`

```erlang
-type msg() ::
          {event, event()} |
          {finished, {success, success()}} |
          {finished, dismissed} |
          {finished, {error, term()}}.
```

# `opt`

```erlang
-type opt() ::
          {connect_timeout, timeout()} |
          {download_start_timeout, timeout()} |
          {idle_download_timeout, timeout()} |
          insecure |
          {insecure, boolean()} |
          {censor_query, CensoredKeys :: [atom()]}.
```

# `reason_for_download_failing_to_start`

```erlang
-type reason_for_download_failing_to_start() ::
          full_http_response() |
          too_many_redirections |
          {invalid_redirection, term()} |
          {error, term()} |
          timeout.
```

# `redirection`

```erlang
-type redirection() :: #{url := url(), permanence := permanent | temporary}.
```

# `response_status`

```erlang
-type response_status() :: {100..999, binary()}.
```

# `state`

```erlang
-opaque state()
```

# `success`

```erlang
-type success() :: #{headers := headers(), body := binary()}.
```

# `url`

```erlang
-type url() :: string().
```

# `code_change`

```erlang
-spec code_change(term(), state(), term()) -> {ok, state()}.
```

# `handle_call`

```erlang
-spec handle_call(term(), {pid(), reference()}, state()) -> {stop, unexpected_call, state()}.
```

# `handle_cast`

```erlang
-spec handle_cast(term(), state()) -> {stop, unexpected_cast, state()}.
```

# `handle_info`

```erlang
-spec handle_info(term(), state()) ->
                     {noreply, state()} | {stop, normal, state()} | {stop, unexpected_info, state()}.
```

# `init`

```erlang
-spec init([InitArg, ...]) -> {ok, state()}
              when
                  InitArg :: OwnerPid | URL | Headers | Opts,
                  OwnerPid :: pid(),
                  URL :: url(),
                  Headers :: headers(),
                  Opts :: [opt()].
```

# `start_link`

```erlang
-spec start_link(url(), headers(), [opt()]) -> {ok, pid()}.
```

# `terminate`

```erlang
-spec terminate(term(), state()) -> ok.
```

# `validate_opts`

```erlang
-spec validate_opts(proplists:proplist()) ->
                       {ok, {[opt()], proplists:proplist()}} | {error, BadOpt :: term()}.
```

---

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