diff --git a/lib/reverse_proxy/runner.ex b/lib/reverse_proxy/runner.ex index 566796c..118de9f 100644 --- a/lib/reverse_proxy/runner.ex +++ b/lib/reverse_proxy/runner.ex @@ -25,6 +25,39 @@ defmodule ReverseProxy.Runner do |> process_response(conn) end + @spec get_body(Conn.t) :: String.t + def get_body(conn) do + case conn.body_params do + %Plug.Conn.Unfetched{aspect: :body_params} -> + case Conn.read_body(conn) do + {:ok, body, _conn} -> + body + {:more, body, conn} -> + {:stream, + Stream.resource( + fn -> {body, conn} end, + fn + {body, conn} -> + {[body], conn} + nil -> + {:halt, nil} + conn -> + case Conn.read_body(conn) do + {:ok, body, _conn} -> + {[body], nil} + {:more, body, conn} -> + {[body], conn} + end + end, + fn _ -> nil end + ) + } + end + _ -> # this makes the assumption that we are dealing with JSON + Poison.encode!(conn.body_params) + end + end + @spec prepare_request(String.t, Conn.t) :: {Atom.t, String.t, String.t, @@ -42,30 +75,7 @@ defmodule ReverseProxy.Runner do method = conn.method |> String.downcase |> String.to_atom url = "#{prepare_server(conn.scheme, server)}#{conn.request_path}?#{conn.query_string}" headers = conn.req_headers - body = case Conn.read_body(conn) do - {:ok, body, _conn} -> - body - {:more, body, conn} -> - {:stream, - Stream.resource( - fn -> {body, conn} end, - fn - {body, conn} -> - {[body], conn} - nil -> - {:halt, nil} - conn -> - case Conn.read_body(conn) do - {:ok, body, _conn} -> - {[body], nil} - {:more, body, conn} -> - {[body], conn} - end - end, - fn _ -> nil end - ) - } - end + body = get_body(conn) {method, url, body, headers} end diff --git a/mix.exs b/mix.exs index 1e9739a..95244d1 100644 --- a/mix.exs +++ b/mix.exs @@ -25,6 +25,7 @@ defmodule ReverseProxy.Mixfile do [{:plug, "~> 1.2"}, {:cowboy, "~> 1.0"}, {:httpoison, "~> 0.9"}, + {:poison, "~> 3.1"}, {:earmark, "~> 1.0", only: :dev}, {:ex_doc, "~> 0.14", only: :dev}, diff --git a/mix.lock b/mix.lock index e9859ab..eb2eead 100644 --- a/mix.lock +++ b/mix.lock @@ -17,7 +17,7 @@ "mime": {:hex, :mime, "1.0.1", "05c393850524767d13a53627df71beeebb016205eb43bfbd92d14d24ec7a1b51", [:mix], []}, "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], []}, "plug": {:hex, :plug, "1.2.2", "cfbda521b54c92ab8ddffb173fbaabed8d8fc94bec07cd9bb58a84c1c501b0bd", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, optional: true]}, {:mime, "~> 1.0", [hex: :mime, optional: false]}]}, - "poison": {:hex, :poison, "3.0.0", "625ebd64d33ae2e65201c2c14d6c85c27cc8b68f2d0dd37828fde9c6920dd131", [:mix], []}, + "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [], [], "hexpm"}, "ranch": {:hex, :ranch, "1.2.1", "a6fb992c10f2187b46ffd17ce398ddf8a54f691b81768f9ef5f461ea7e28c762", [:make], []}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.0", "edee20847c42e379bf91261db474ffbe373f8acb56e9079acb6038d4e0bf414f", [:make, :rebar], []}, "ssl_verify_hostname": {:hex, :ssl_verify_hostname, "1.0.5"}} diff --git a/test/fixtures/body.exs b/test/fixtures/body.exs new file mode 100644 index 0000000..9bbfbdb --- /dev/null +++ b/test/fixtures/body.exs @@ -0,0 +1,9 @@ +defmodule ReverseProxyTest.Body do + def request(_method, _url, body, _headers, _opts \\ []) do + {:ok, %{ + :headers => [], + :status_code => 200, + :body => body + }} + end +end diff --git a/test/reverse_proxy/runner_test.exs b/test/reverse_proxy/runner_test.exs index 11fc33a..9b74541 100644 --- a/test/reverse_proxy/runner_test.exs +++ b/test/reverse_proxy/runner_test.exs @@ -69,6 +69,26 @@ defmodule ReverseProxy.RunnerTest do assert conn.resp_body == "8000001" end + def parse(conn, opts \\ []) do + opts = opts + |> Keyword.put_new(:parsers, [:json]) + |> Keyword.put_new(:json_decoder, Poison) + Plug.Parsers.call(conn, Plug.Parsers.init(opts)) + end + + test "retrieve/3 - body parsed with Poison" do + conn = + conn(:post, "/", "{\"test\": \"data\"}") + |> put_req_header("content-type", "application/json") + |> parse() + |> ReverseProxy.Runner.retreive( + ["localhost"], + ReverseProxyTest.Body + ) + + assert conn.resp_body == "{\"test\":\"data\"}" + end + test "retrieve/3 - chunked response" do conn = conn(:get, "/")