# `StaticMaps.Plug`
[🔗](https://gitlab.com/tristanperalta/staticmaps/blob/v0.1.0/lib/static_maps/plug.ex#L2)

Serves maps from signed URLs, for browsers and CDNs to cache.

Compiled only when `:plug` is a dependency. Mount it where no session or CSRF plug
touches its responses, since a response that sets a cookie is not cached by a CDN:

    forward "/maps", StaticMaps.Plug,
      secret: {MyApp.Config, :map_secret, []},
      source: StaticMaps.Source.OSM,
      icons: %{office: File.read!("priv/office.svg")}

and build URLs with `path/3`, using the same secret:

    StaticMaps.Plug.path("/maps", [center: {14.5547, 121.0244}, zoom: 15], secret: secret)

## Options

  * `:secret` — at least 32 bytes, or `{module, function, args}` returning them, to
    read runtime configuration. Required.
  * `:cache` — `:max_age` (86 400), `:s_maxage` (2 592 000),
    `:stale_while_revalidate` (86 400) and `:immutable` (`false`) for successful
    responses; `false` sends `no-store` instead.
  * `:max_size` (`{1280, 1280}`), `:max_scale` (2), `:max_markers` (100) — limits on
    every request, signed or not.
  * `:max_concurrency` — renders in progress at once; defaults to the number of
    schedulers.
  * `:source`, `:attribution` — passed to `StaticMaps.render/1`, and never read from a
    request.
  * `:background` — the default background; a URL built with `:background` overrides it.
  * `:icons` — named marker icons, `%{name => svg_or_image_bytes}`, for markers given
    `icon: :name`. A URL names an icon; it never carries one.

## Responses

| Situation | Status | `Cache-Control` |
|---|---|---|
| Rendered | `200` | the `:cache` settings |
| `If-None-Match` matches | `304` | the `:cache` settings |
| Bad or missing signature | `403` | `no-store` |
| Signed, but over a limit or invalid | `400` | `no-store` |
| A tile failed | `503` | `no-store` |
| Not `GET` or `HEAD` | `405` | `no-store` |

A `304` is answered straight after the signature check, without rendering or
fetching a tile. Identical requests that arrive during a render wait for it rather
than starting their own.

# `path`

```elixir
@spec path(String.t(), keyword(), keyword()) :: String.t()
```

The signed path of a map, under `prefix`, where the Plug is mounted.

`render_opts` are the options `StaticMaps.render/1` takes, except `:source`,
`:attribution` and `:on_tile_error`, which the Plug decides. A marker's `:icon` is the
name of an icon registered with the Plug. The same options always give the same path.

Options: `:secret`, as for the Plug, and `:format`, `:png` (default) or `:jpeg`.
Raises `ArgumentError` for render options a URL cannot carry.

---

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