StaticMaps.Source.HTTP behaviour (staticmaps v0.1.0)

Copy Markdown View Source

A source that fetches each tile from a URL.

use StaticMaps.Source.HTTP and implement url/2 and StaticMaps.Source.info/1; this module supplies fetch/2 and fetch_cacheable/3:

defmodule MyApp.Tiles do
  use StaticMaps.Source.HTTP

  @impl true
  def url(%{z: z, x: x, y: y}, _opts), do: "https://tiles.example.com/#{z}/#{x}/#{y}.png"

  @impl true
  def info(_opts), do: %{attribution: "© Example", tile_size: 256, zoom: 0..19, scales: [1]}
end

To add headers a server needs, such as an API key, implement headers/2. To replace how tiles are fetched entirely, override fetch_cacheable/3: it is the one function every fetch goes through, cached or not. fetch/2 cannot be overridden, because the cache never calls it, so an override there would be silently skipped.

Every request:

  • sends User-Agent: StaticMaps/<version> (+<contact>), with the contact from config :staticmaps, contact: "…", which no source or option can replace;
  • has a connect timeout and a receive timeout;
  • is retried with backoff on connection errors and on 408, 429, 500, 502, 503 and 504, honouring Retry-After up to a limit and giving up rather than waiting longer;
  • counts as a tile only when the response is 200 with an image/* content type.

Configuration

config :staticmaps, :http,
  connect_timeout: 5_000,
  receive_timeout: 10_000,
  max_retries: 2,
  retry_base: 500,
  max_retry_after: 10_000

retry_base is the first backoff in milliseconds, doubling on each retry. max_retry_after is the longest Retry-After the fetcher will wait, in milliseconds.

Summary

Callbacks

Extra request headers for tile; none by default. A user-agent here is ignored.

The URL of tile.

Functions

Fetches url and returns the body of a 200 image response.

Like get/1, but conditional on validators, and returns how long the response may be cached.

The User-Agent sent with every tile request.

Callbacks

headers(tile, opts)

@callback headers(StaticMaps.Source.tile(), opts :: keyword()) :: [
  {String.t(), String.t()}
]

Extra request headers for tile; none by default. A user-agent here is ignored.

url(tile, opts)

@callback url(StaticMaps.Source.tile(), opts :: keyword()) :: String.t()

The URL of tile.

Functions

get(url)

@spec get(String.t()) :: {:ok, binary()} | {:error, term()}

Fetches url and returns the body of a 200 image response.

Errors are {:http_status, status}, {:not_an_image, content_type}, or {:transport, reason} for a connection that failed or timed out.

get_cacheable(url, validators, headers \\ [])

@spec get_cacheable(String.t(), StaticMaps.Source.validators(), [
  {String.t(), String.t()}
]) ::
  {:ok, binary(), StaticMaps.Source.cache_meta()}
  | {:not_modified, StaticMaps.Source.cache_meta()}
  | {:error, term()}

Like get/1, but conditional on validators, and returns how long the response may be cached.

With an :etag or :last_modified from an earlier response, the request carries If-None-Match or If-Modified-Since, and a 304 returns {:not_modified, meta}. See StaticMaps.Source.cache_meta/0 for meta. headers are sent too, except any user-agent.

user_agent()

@spec user_agent() :: String.t()

The User-Agent sent with every tile request.