defmodule ArweaveSdkEx.Utils.ExHttp do @moduledoc """ the encapsulation of http """ require Logger @retries 5 @doc """ +----------------------+ | json_rpc_constructer | +----------------------+ """ @spec json_rpc(String.t(), integer()) :: map() def json_rpc(method, id) when is_integer(id) do %{method: method, jsonrpc: "2.0", id: id} end @spec json_rpc(String.t(), map()) :: map() def json_rpc(method, params) do %{method: method, params: params, jsonrpc: "2.0", id: 1} end @doc """ +-------------+ | get request | +-------------+ """ @spec get(any) :: {:error, String.t()} | {:ok, any} def get(url) do do_get(url, @retries) end @spec get_once(any) :: {:error, String.t()} | {:ok, any} def get_once(url) do url |> HTTPoison.get([]) |> handle_response() |> case do {:ok, body} -> {:ok, body} {:error, reason} -> {:error, reason} end end def get_with_redirect(url) do :get |> HTTPoison.request(url, "", [], [hackney: [{:follow_redirect, true}]]) |> handle_response_spec() |> case do {:ok, body} -> {:ok, body} {:error, _} -> Process.sleep(500) do_get(url, @retries - 1) end 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 | +--------------+ """ @spec post(String.t(), map()) :: {:error, String.t()} | {:ok, any} def post(url, body) do do_post(url, body, @retries) end @spec post(String.t(), map(), atom()) :: {:error, String.t()} | {:ok, any} 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, 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 defp handle_response_spec({:ok, %{status_code: 200}} = payload) do payload end # 404 or sth else defp handle_response_spec(others), do: handle_response(others) end