diff --git a/server/lib/coflux/handlers/logs.ex b/server/lib/coflux/handlers/logs.ex index f0c04fa9..833d5a84 100644 --- a/server/lib/coflux/handlers/logs.ex +++ b/server/lib/coflux/handlers/logs.ex @@ -79,7 +79,7 @@ defmodule Coflux.Handlers.Logs do {:ok, req, opts} end - {:error, :invalid_json} -> + {:error, :invalid_json, req} -> req = json_error_response(req, "invalid_json") {:ok, req, opts} end diff --git a/server/lib/coflux/handlers/metrics.ex b/server/lib/coflux/handlers/metrics.ex index 619fc33a..2ddc4db0 100644 --- a/server/lib/coflux/handlers/metrics.ex +++ b/server/lib/coflux/handlers/metrics.ex @@ -78,7 +78,7 @@ defmodule Coflux.Handlers.Metrics do {:ok, req, opts} end - {:error, :invalid_json} -> + {:error, :invalid_json, req} -> req = json_error_response(req, "invalid_json") {:ok, req, opts} end diff --git a/server/lib/coflux/handlers/utils.ex b/server/lib/coflux/handlers/utils.ex index 440bd4bb..9925c9d1 100644 --- a/server/lib/coflux/handlers/utils.ex +++ b/server/lib/coflux/handlers/utils.ex @@ -189,11 +189,18 @@ defmodule Coflux.Handlers.Utils do end def read_json_body(req) do + {:ok, data, req} = read_full_body(req) + + case Jason.decode(data) do + {:ok, result} -> {:ok, result, req} + {:error, _} -> {:error, :invalid_json, req} + end + end + + defp read_full_body(req, acc \\ []) do case :cowboy_req.read_body(req) do - {:ok, data, req} -> - with {:ok, result} <- Jason.decode(data) do - {:ok, result, req} - end + {:ok, data, req} -> {:ok, IO.iodata_to_binary([acc | [data]]), req} + {:more, data, req} -> read_full_body(req, [acc | [data]]) end end @@ -206,48 +213,48 @@ defmodule Coflux.Handlers.Utils do end def read_arguments(req, required_specs, optional_specs \\ %{}) do - {:ok, body, req} = read_json_body(req) - - {values, errors} = - Enum.reduce( - %{true: required_specs, false: optional_specs}, - {%{}, %{}}, - fn {required, specs}, {values, errors} -> - Enum.reduce(specs, {values, errors}, fn {key, spec}, {values, errors} -> - {field, parser} = - case spec do - {field, parser} -> {field, parser} - field when is_binary(field) -> {field, &default_parser/1} - end - - case Map.fetch(body, field) do - {:ok, nil} when not required -> - {values, errors} - - {:ok, value} -> - case parser.(value) do - {:ok, value} -> - {Map.put(values, key, value), errors} - - {:error, error} -> - {values, merge_error(errors, key, error)} + with {:ok, body, req} <- read_json_body(req) do + {values, errors} = + Enum.reduce( + %{true: required_specs, false: optional_specs}, + {%{}, %{}}, + fn {required, specs}, {values, errors} -> + Enum.reduce(specs, {values, errors}, fn {key, spec}, {values, errors} -> + {field, parser} = + case spec do + {field, parser} -> {field, parser} + field when is_binary(field) -> {field, &default_parser/1} end - :error -> - if required do - {values, merge_error(errors, key, :required)} - else + case Map.fetch(body, field) do + {:ok, nil} when not required -> {values, errors} - end - end - end) - end - ) - if Enum.empty?(errors) do - {:ok, values, req} - else - {:error, errors, req} + {:ok, value} -> + case parser.(value) do + {:ok, value} -> + {Map.put(values, key, value), errors} + + {:error, error} -> + {values, merge_error(errors, key, error)} + end + + :error -> + if required do + {values, merge_error(errors, key, :required)} + else + {values, errors} + end + end + end) + end + ) + + if Enum.empty?(errors) do + {:ok, values, req} + else + {:error, errors, req} + end end end