Skip to content

Commit

Permalink
Improve JSON encoding and decoding
Browse files Browse the repository at this point in the history
  • Loading branch information
lnikkila committed Mar 13, 2017
1 parent a7e3b57 commit e3b714c
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 9 deletions.
40 changes: 36 additions & 4 deletions lib/exquickbooks/json_endpoint.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ defmodule ExQuickBooks.JSONEndpoint do
send_request: 1
]

alias ExQuickBooks.Request
alias HTTPoison.Response

@json_headers [
{"Accept", "application/json"},
{"Content-Type", "application/json"}
Expand All @@ -21,12 +24,41 @@ defmodule ExQuickBooks.JSONEndpoint do
end
end

def send_json_request(request) do
def send_json_request(request = %Request{}) do
new_body = encode_body(request.body)
new_headers = merge_headers(@json_headers, request.headers)
new_request = %{request | headers: new_headers}

with {:ok, response} <- send_request(new_request) do
Poison.Parser.parse(response.body)
%{request | body: new_body, headers: new_headers}
|> send_request
|> parse_response
end

defp encode_body(body) when is_binary(body) do
body
end
defp encode_body(body) do
Poison.Encoder.encode(body, [])
end

defp parse_response({ok_error, response = %Response{}}) do
is_json =
response
|> parse_content_type
|> String.starts_with?("application/json")

if is_json do
{ok_error, Poison.Parser.parse!(response.body)}
else
{ok_error, response}
end
end
defp parse_response(non_response_result) do
non_response_result
end

defp parse_content_type(%Response{headers: headers}) do
Enum.find_value(headers, "text/plain", fn({header, value}) ->
if String.downcase(header) == "content-type", do: value
end)
end
end
45 changes: 40 additions & 5 deletions test/exquickbooks/json_endpoint_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,52 @@ defmodule ExQuickBooks.JSONEndpointTest do
} = take_request()
end

test "send_json_request/1 parses the JSON response" do
test "send_json_request/1 encodes non-binary request bodies" do
request(:get, "path", %{foo: true}) |> send_json_request

# Note that IO lists are also accepted.
assert %{body: body} = take_request()
assert to_string(body) == ~S({"foo":true})
end

test "send_json_request/1 doesn't encode binary request bodies" do
request(:get, "path", "foo") |> send_json_request

assert %{
body: "foo"
} = take_request()
end

test "send_json_request/1 parses JSON responses" do
send_response %HTTPoison.Response{
body: ~S({"foo": true}),
headers: [{"Content-Type", "application/json"}],
status_code: 200
}

result =
request(:get, "path")
|> send_json_request
assert {:ok, %{"foo" => true}} =
request(:get, "path") |> send_json_request
end

test "send_json_request/1 parses JSON error responses" do
send_response %HTTPoison.Response{
body: ~S({"foo": true}),
headers: [{"Content-Type", "application/json"}],
status_code: 400
}

assert {:error, %{"foo" => true}} =
request(:get, "path") |> send_json_request
end

test "send_json_request/1 doesn't parse non-JSON responses" do
send_response %HTTPoison.Response{
body: "foo",
headers: [{"Content-Type", "text/plain"}],
status_code: 200
}

assert result == {:ok, %{"foo" => true}}
assert {:ok, %HTTPoison.Response{body: "foo"}} =
request(:get, "path") |> send_json_request
end
end

0 comments on commit e3b714c

Please sign in to comment.