Current section

Files

Jump to
ex_link_header lib builder builder.ex
Raw

lib/builder/builder.ex

defmodule ExLinkHeader.Builder do
alias ExLinkHeader.BuildError
@moduledoc """
HTTP link header builder
"""
def build(%ExLinkHeader{} = h) do
{_, acc} = Enum.map_reduce(Map.keys(h), [],
fn(k, acc) ->
entry = Map.get(h, k)
case dobuild(entry, k) do
v when is_binary(v) -> {v, [v | acc]}
_ -> {nil, acc}
end
end
)
Enum.join(acc, ", ")
end
defp build_attributes(attributes) do
case concatenate(attributes) do
"" -> ""
v when is_binary(v) -> "; " <> v
_ -> ""
end
end
defp build_scheme(scheme) do
case scheme do
v when is_atom(v) -> Atom.to_string(v)
v when is_binary(v) -> v
_ -> raise BuildError, "Invalid scheme format/type"
end
end
defp build_url(scheme, host, path, params) do
q = URI.encode_query(params)
url = case path do
"" -> scheme <> "://" <> host
p when is_binary(p) -> scheme <> "://" <> host <> URI.encode(path)
:nil -> scheme <> host
_ -> scheme <> host
end
url = case q do
"" -> url
v when is_binary(v) -> url <> "?" <> v
_ -> url
end
url
end
defp dobuild(%ExLinkHeaderEntry{host: nil} = _h, _relation), do: :error
defp dobuild(%ExLinkHeaderEntry{host: ""} = _h, _relation), do: :error
defp dobuild(%ExLinkHeaderEntry{} = h, relation) do
h = Map.put(h, :scheme, build_scheme(h.scheme))
url = build_url(h.scheme, h.host, h.path, h.params)
attributes = build_attributes(h.attributes)
"<" <> url <> ">; rel=\"" <> Atom.to_string(relation) <> "\"" <> attributes
end
defp dobuild(_any, _whatever), do: :error
defp concatenate(%{} = map) do
Enum.map_join(Map.keys(map), "; ", fn(key) ->
val = case Map.get(map, key) do
v when is_integer(v) -> Integer.to_string(v)
v when is_atom(v) -> Atom.to_string(v)
v when is_binary(v) -> v
_ -> raise BuildError, "Invalid query param value"
end
Atom.to_string(key) <> "=\"" <> val <> "\""
end)
end
end