defmodule ExImaginary do
@moduledoc """
Provides functions to generate secure Imginary URLs.
"""
defp config do
%{
host: Application.get_env(:ex_imaginary, :host),
url_signature_key: Application.get_env(:ex_imaginary, :url_signature_key),
token: Application.get_env(:ex_imaginary, :token)
}
end
defp sign(url_signature_key, path, query) do
mac = :crypto.mac(:hmac, :sha256, url_signature_key, path <> query)
Base.url_encode64(mac, padding: false)
end
@doc """
Generates a secure Imginary URL given:
* `path` - The URL path of the image operation.
* `params` - (optional) A map containing Imgaginary API parameters used to manipulate the image.
* `config` - (optional) A map containing Imganiry source config:
* `:host` - The Imaginary host.
* `:token` - The token for API authorization.
* `:url_signature_key` - The url signature key used to verify the API url signature.
## Examples
iex> ExImaginary.url "/resize", %{nocrop: true, type: "jpeg", url: "https://raw.githubusercontent.com/mrdotb/i/master/mcdo.jpg"}
"http://localhost:9000/resize?nocrop=true&type=jpeg&url=https%3A%2F%2Fraw.githubusercontent.com%2Fmrdotb%2Fi%2Fmaster%2Fmcdo.jpg"
iex> ExImaginary.url "/thumbnail", %{url: "https://raw.githubusercontent.com/mrdotb/i/master/mcdo.jpg"}
"http://localhost:9000/thumbnail?url=https%3A%2F%2Fraw.githubusercontent.com%2Fmrdotb%2Fi%2Fmaster%2Fmcdo.jpg"
"""
def url(path, params \\ %{}, config \\ config()) do
query = encode_query(params, config.token)
url = "#{config.host}#{path}?#{query}"
url
|> maybe_sign_url(path, query, config.url_signature_key)
end
defp encode_query(params, nil), do: URI.encode_query(params)
defp encode_query(params, token) do
params
|> Map.put(:token, token)
|> URI.encode_query()
end
defp maybe_sign_url(url, _path, _query, nil), do: url
defp maybe_sign_url(url, path, query, url_signature_key) do
signature = sign(url_signature_key, path, query)
if query == "" do
"#{url}?sign=#{signature}"
else
"#{url}&sign=#{signature}"
end
end
end