if Code.ensure_loaded?(:hackney) do defmodule Mixpanel.HTTP.Hackney do @moduledoc """ Adapter for [hackney](https://github.com/benoitc/hackney). Remember to add `{:hackney, "~> 1.20"}` to dependencies (and `:hackney` to applications in `mix.exs`). ## Examples ``` # set globally in config/config.exs config :mixpanel_api_ex, :http_adapter, Mixpanel.HTTP.Hackney ``` ## Adapter specific options - `:max_body_length` - Max response body size in bytes. Actual response may be bigger because hackney stops after the last chunk that surpasses `:max_body_length`. Defaults to `:infinity`. """ @behaviour Mixpanel.HTTP @impl Mixpanel.HTTP @spec get(url :: String.t(), headers :: [{String.t(), binary}], opts :: keyword) :: {:ok, status :: 200..599, headers :: [{String.t(), binary}], body :: term} | {:error, String.t()} def get(url, headers, opts) do request(:get, url, headers, "", opts) end @impl Mixpanel.HTTP @spec post( url :: String.t(), body :: binary, headers :: [{String.t(), binary}], opts :: keyword ) :: {:ok, status :: 200..599, headers :: [{String.t(), binary}], body :: term} | {:error, String.t()} def post(url, body, headers, opts) do request(:post, url, headers, body, opts) end defp request(method, url, headers, body, opts) do opts = opts |> Keyword.split([:insecure]) |> then(fn {opts, _} -> opts end) |> Enum.reduce([], fn {:insecure, true}, acc -> [:insecure | acc] end) case :hackney.request(method, url, headers, body, opts) do {:ok, status_code, headers} -> {:ok, status_code, headers, <<>>} {:ok, status_code, headers, client} -> max_length = Keyword.get(opts, :max_body_length, :infinity) case :hackney.body(client, max_length) do {:ok, body} -> {:ok, status_code, headers, body} {:error, reason} -> {:error, to_string(reason)} end {:ok, {:maybe_redirect, _status_code, _headers, _client}} -> {:error, "Redirect not supported"} {:error, reason} -> {:error, to_string(reason)} end end end end