# `Image.Plug.Cache`
[🔗](https://github.com/elixir-image/image_plug/blob/v0.1.0/lib/image/plug/cache.ex#L1)

HTTP-cache helpers used by `Image.Plug`.

This module is pure. It computes a stable ETag from the source's
`etag_seed` and the normalised pipeline's fingerprint, evaluates
`If-None-Match` for conditional GETs, and produces a default
`Cache-Control` directive.

The ETag is a strong validator computed as:

    base64url(sha256(meta.etag_seed <> "|" <> pipeline_fingerprint <> "|" <> chosen_format))

Because the pipeline is normalised first, two URLs that differ
only in option order produce the same ETag — bandwidth-friendly
and cache-friendly.

# `cache_info`

```elixir
@type cache_info() :: %{
  :etag =&gt; String.t(),
  :cache_control =&gt; String.t(),
  optional(:last_modified) =&gt; DateTime.t(),
  optional(:vary) =&gt; [String.t()]
}
```

The shape returned by `compute/3`. The plug attaches these to the
conn before the body is sent.

# `compute`

```elixir
@spec compute(map(), Image.Plug.Pipeline.t(), atom()) :: cache_info()
```

Computes cache headers for a given source meta + normalised
pipeline + chosen output format.

### Arguments

* `meta` is the `Image.Plug.SourceResolver.meta` map.

* `pipeline` is the (normalised) `Image.Plug.Pipeline`.

* `chosen_format` is an atom describing the actual output format
  selected by the encoder (e.g. `:webp` even when the request was
  `format=auto`). Caller passes this so that two requests choosing
  different formats get different ETags.

### Returns

* A `t:cache_info/0` map.

# `fingerprint`

```elixir
@spec fingerprint(Image.Plug.Pipeline.t()) :: binary()
```

Computes a stable fingerprint for a normalised pipeline. Used by
`etag/3` and exposed for tests.

# `fresh?`

```elixir
@spec fresh?(Plug.Conn.t(), String.t()) :: boolean()
```

Returns true when the request's `If-None-Match` header matches the
computed ETag (i.e. we should respond 304).

Accepts the bare ETag form and the `W/"..."` weak form, since some
intermediaries strip the surrounding quotes.

---

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