defmodule Web3AptosEx.HTTPImpl do
@moduledoc """
the encapsulation of http
"""
require Logger
alias Web3AptosEx.HTTP
@retries 5
@behaviour HTTP
@doc """
+----------------------+
| json_rpc_constructer |
+----------------------+
"""
@impl HTTP
def json_rpc(method, id) when is_integer(id) do
%{method: method, jsonrpc: "2.0", id: id}
end
def json_rpc(method, params) do
%{method: method, params: params, jsonrpc: "2.0", id: 1}
end
@doc """
+-------------+
| get request |
+-------------+
"""
@impl HTTP
def get(url) do
do_get(url, @retries)
end
defp do_get(_url, retries) when retries == 0 do
{:error, "retires #{@retries} times and not success"}
end
defp do_get(url, retries) do
url
|> HTTPoison.get([])
|> handle_response()
|> case do
{:ok, body} ->
{:ok, body}
{:error, _} ->
Process.sleep(500)
do_get(url, retries - 1)
end
end
@doc """
+--------------+
| post request |
+--------------+
"""
@impl HTTP
def post(url, body) do
do_post(url, body, @retries)
end
@impl HTTP
def post(url, body, :urlencoded) do
do_post(url, body, @retries, :urlencoded)
end
defp do_post(_url, _body, retires) when retires == 0 do
{:error, "retires #{@retries} times and not success"}
end
defp do_post(url, body, retries) do
url
|> HTTPoison.post(
Poison.encode!(body),
[{"Content-Type", "application/json"}]
)
|> handle_response()
|> case do
{:ok, body} ->
{:ok, body}
{:error, _} ->
Process.sleep(500)
do_post(url, body, retries - 1)
end
end
defp do_post(_url, _body, retires, :urlencoded) when retires == 0 do
{:error, "retires #{@retries} times and not success"}
end
defp do_post(url, body, retries, :urlencoded) do
url
|> HTTPoison.post(
body,
[{"Content-Type", "application/x-www-form-urlencoded"}]
)
|> handle_response()
|> case do
{:ok, body} ->
{:ok, body}
{:error, _} ->
Process.sleep(500)
do_post(url, body, retries - 1)
end
end
# normal
defp handle_response({:ok, %HTTPoison.Response{status_code: status_code, body: body}})
when status_code in 200..299 do
case Poison.decode(body) do
{:ok, json_body} ->
{:ok, ExStructTranslator.to_atom_struct(json_body)}
{:error, payload} ->
Logger.error("Reason: #{inspect(payload)}")
{:error, :network_error}
end
end
# 404 or sth else
defp handle_response({:ok, %HTTPoison.Response{status_code: status_code, body: _}}) do
Logger.error("Reason: #{status_code} ")
{:error, :network_error}
end
defp handle_response(error) do
Logger.error("Reason: other_error")
error
end
end