Current section
Files
Jump to
Current section
Files
lib/connection/http_client.ex
defmodule FinTex.Connection.HTTPClient do
@moduledoc false
alias FinTex.Config.Identifier
use ExActor.GenServer
import Logger
defstart start_link(_) do
debug "Starting #{inspect __MODULE__}"
HTTPotion.start
initial_state nil
end
defcall send_request(url, body, options \\ []), from: from, timeout: :infinity do
debug("#{inspect self}: sending request to URL #{url}")
ssl_options = Application.get_env(:fintex, :ssl_options, [])
ssl_options = case ssl_options do
[] ->
[]
_ ->
%URI{:host => host} = URI.parse(url)
hostname = to_char_list(host)
{verify_fun, initial_user_state} = Dict.get(ssl_options, :verify_fun)
Dict.merge(
[
verify_fun: {
verify_fun,
List.keyreplace(initial_user_state, :check_hostname, 0, {:check_hostname, hostname})
},
server_name_indication: hostname
],
ssl_options
)
end
ibrowse = Dict.merge [ssl_options: ssl_options], Application.get_env(:fintex, :ibrowse, [])
options = [ignore_response: false] |> Dict.merge options
%HTTPotion.AsyncResponse{id: async_id} = HTTPotion.post(
url,
body: body,
headers: [
"Content-Type": "text/plain",
"Connection": "keep-alive",
"User-Agent": Identifier.user_agent_name
],
stream_to: self,
ibrowse: ibrowse,
timeout: 10_000
)
if options[:ignore_response], do: GenServer.reply(from, :ok)
new_state {from, async_id, options}
end
defhandleinfo %HTTPotion.AsyncHeaders{id: id, status_code: status_code},
state: {_, async_id, _}, when: id == async_id and (status_code
in 200..299 or status_code in [302, 304]), export: false do
noreply
end
defhandleinfo %HTTPotion.AsyncHeaders{id: id, status_code: status_code},
state: {from, async_id, options}, export: false, when: id == async_id do
msg = "#{__MODULE__}: Request failed with HTTP status code #{status_code}."
error msg
if !options[:ignore_response] do
GenServer.reply(from, {:error, msg})
raise RuntimeError, message: msg
end
noreply
end
defhandleinfo %HTTPotion.AsyncChunk{id: id, chunk: chunk},
state: {from, async_id, options}, export: false, when: id == async_id do
if !options[:ignore_response], do: GenServer.reply(from, {:ok, to_string(chunk)})
noreply
end
defhandleinfo %HTTPotion.AsyncEnd{id: id},
state: {_, async_id, _}, export: false, when: id == async_id do
new_state nil
end
# Stops the server on timeout message
defhandleinfo :timeout, do: stop_server(:normal)
defhandleinfo _, do: noreply
end