-
Notifications
You must be signed in to change notification settings - Fork 6
/
api.ex
49 lines (42 loc) · 1.45 KB
/
api.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
defmodule ExOkex.Api do
@moduledoc """
API Base
"""
@type path :: String.t()
@type config :: ExOkex.Config.t()
@type params :: map
@type status_code :: integer
@type body :: term
@type error_reason :: :rate_limited | term
@type response :: {:ok, term} | {:error, error_reason} | {:error, body, status_code}
@spec url(path, config) :: String.t()
def url(path, config), do: config.api_url <> path
@spec query_string(path, params) :: String.t()
def query_string(path, params) when map_size(params) == 0, do: path
def query_string(path, params) do
query = Enum.map_join(params, "&", fn {key, val} -> "#{key}=#{val}" end)
path <> "?" <> query
end
@spec parse_response(
{:ok, HTTPoison.Response.t() | HTTPoison.AsyncResponse.t()}
| {:error, HTTPoison.Error.t()}
) :: response
def parse_response(response) do
case response do
{:ok, %HTTPoison.Response{body: body, status_code: status_code}} ->
case status_code do
code when code in 200..299 -> {:ok, Jason.decode!(body)}
429 -> {:error, :rate_limited}
_ -> parse_error_body(body, status_code)
end
{:error, %HTTPoison.Error{reason: reason}} ->
{:error, reason}
end
end
defp parse_error_body(body, status_code) do
case Jason.decode(body) do
{:ok, json} -> {:error, {json["code"], json["message"]}, status_code}
{:error, _} -> {:error, body, status_code}
end
end
end