defmodule SCF.HTTP do
alias SCF.Auth
@common_params [
"Action",
"Region",
"Timestamp",
"Version",
"Token",
"Language"
]
@spec auth_post(params :: map) :: {:ok, map} | {:error, map}
@spec auth_post(params :: map, opts :: keyword) :: {:ok, map} | {:error, map}
def auth_post(params, opts \\ []) do
{common_params, body} = Map.split(params, @common_params)
headers = Enum.map(common_params, fn {key, value} -> {"X-TC-#{key}", value} end)
request(body, headers, opts)
end
@spec request(body :: map, headers :: [tuple], opts :: keyword) :: {:ok, map} | {:error, map}
def request(body, headers, opts) do
config = SCF.config()
host = config[:api_host]
url = "https://" <> host
encoded_body = Jason.encode!(body)
headers =
headers
|> put_new_header({"Host", host})
|> put_new_header({"Content-Type", "application/json"})
|> put_new_header({"X-TC-Version", config[:api_version]})
|> put_new_header({"X-TC-Timestamp", DateTime.utc_now() |> DateTime.to_unix()})
|> put_new_header({"X-TC-Region", config[:region]})
|> put_new_header({"X-TC-Language", config[:language]})
|> Enum.reject(fn {_key, value} -> is_nil(value) end)
authorization = Auth.authorization(encoded_body, headers, config)
options = [
method: :post,
url: url,
headers: [{"Authorization", authorization} | headers],
body: encoded_body,
opts: opts
]
[Tesla.Middleware.JSON]
|> Tesla.client(config.http_client[:adapter])
|> Tesla.request(options)
|> case do
{:ok, %{body: %{"Response" => %{"Error" => _} = response}}} ->
{:error, response}
{:ok, %{status: 200, body: %{"Response" => response}}} ->
{:ok, response}
{:ok, %{body: body}} ->
{:error, body}
end
end
@doc false
def put_new_header(headers, {key, value}) do
key_exists? =
Enum.find(headers, fn
{_key, nil} -> false
{^key, _value} -> true
_ -> false
end)
if key_exists? do
headers
else
[{key, value} | headers]
end
end
@doc false
def common_params do
@common_params
end
end