Packages
mob_dev
0.5.13
0.6.23
0.6.22
0.6.21
0.6.20
0.6.19
0.6.18
0.6.17
0.6.16
0.6.15
0.6.14
0.6.13
0.6.12
0.6.11
0.6.10
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.17
0.5.16
0.5.15
0.5.14
0.5.13
0.5.12
0.5.11
0.5.10
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.0
0.3.37
0.3.35
0.3.34
0.3.33
0.3.28
0.3.26
0.3.23
0.3.21
0.3.19
0.3.18
0.3.17
0.3.16
0.3.15
0.3.14
0.3.13
0.3.12
0.3.11
0.3.10
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.18
0.2.17
0.2.15
0.2.14
0.2.13
0.2.12
0.2.11
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.0
Development tooling for the Mob mobile framework
Current section
Files
Jump to
Current section
Files
lib/mob_dev/google_play/http.ex
defmodule MobDev.GooglePlay.HTTP do
@moduledoc false
# Shared `:httpc` wrapper used by GooglePlay, CloudSetup, PlaySetup, and OAuth.
@type result :: {:ok, map()} | {:error, String.t()}
@spec get(String.t(), list()) :: result()
def get(url, headers), do: request(:get, url, headers, nil)
@spec post(String.t(), list(), String.t()) :: result()
def post(url, headers, body), do: request(:post, url, headers, body)
@spec put(String.t(), list(), String.t()) :: result()
def put(url, headers, body), do: request(:put, url, headers, body)
@spec json_headers(String.t()) :: list()
def json_headers(token) do
[{"authorization", "Bearer #{token}"}, {"content-type", "application/json"}]
end
@spec ensure_started!() :: :ok
def ensure_started! do
Application.ensure_all_started(:inets)
Application.ensure_all_started(:ssl)
:ok
end
@spec request(atom(), String.t(), list(), String.t() | nil) :: result()
def request(:get, url, headers, _body) do
host = URI.parse(url).host
httpc_headers = encode_headers(headers)
:httpc.request(
:get,
{to_charlist(url), httpc_headers},
[ssl: ssl_opts(host), timeout: 30_000, connect_timeout: 15_000],
body_format: :binary
)
|> decode_response()
end
def request(method, url, headers, body) do
{ct, rest} = pop_content_type(headers)
host = URI.parse(url).host
httpc_headers = encode_headers(rest)
body_bin = if is_binary(body), do: body, else: ""
:httpc.request(
method,
{to_charlist(url), httpc_headers, to_charlist(ct), body_bin},
[ssl: ssl_opts(host), timeout: 300_000, connect_timeout: 15_000],
body_format: :binary
)
|> decode_response()
end
defp decode_response({:ok, {{_, status, _}, _hdrs, resp}}) when status in 200..299 do
{:ok, Jason.decode!(resp)}
end
defp decode_response({:ok, {{_, status, _}, _hdrs, resp}}) do
msg =
case Jason.decode(resp) do
{:ok, %{"error" => %{"message" => m}}} -> m
{:ok, %{"error" => %{"errors" => [%{"message" => m} | _]}}} -> m
{:ok, %{"error_description" => m}} -> m
_ -> inspect(resp)
end
{:error, "HTTP #{status}: #{msg}"}
end
defp decode_response({:error, reason}) do
{:error, "HTTP request failed: #{inspect(reason)}"}
end
defp encode_headers(headers) do
Enum.map(headers, fn {k, v} -> {to_charlist(k), to_charlist(v)} end)
end
defp pop_content_type(headers) do
case Enum.split_with(headers, fn {k, _} -> String.downcase(k) == "content-type" end) do
{[{_, ct} | _], rest} -> {ct, rest}
{[], rest} -> {"application/json", rest}
end
end
defp ssl_opts(host) do
[
verify: :verify_peer,
cacerts: :public_key.cacerts_get(),
server_name_indication: to_charlist(host),
customize_hostname_check: [
match_fun: :public_key.pkix_verify_hostname_match_fun(:https)
]
]
end
end