Skip to content

Commit

Permalink
Support maps when posting forms
Browse files Browse the repository at this point in the history
  • Loading branch information
vereis authored and edgurgel committed Mar 2, 2023
1 parent 0b96488 commit 3a436f1
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
4 changes: 4 additions & 0 deletions lib/httpoison/base.ex
Expand Up @@ -995,6 +995,7 @@ defmodule HTTPoison.Base do
{:form,
Enum.flat_map(body, fn
{k, [{_k, _v} | _rest] = v} -> flatten_nested_body(v, k)
{k, v} when is_map(v) -> flatten_nested_body(v, k)
{k, v} -> [{k, v}]
end)}
end
Expand All @@ -1006,6 +1007,9 @@ defmodule HTTPoison.Base do
defp flatten_nested_body(body, parent_key) do
flattened_body =
Enum.reduce(body, [], fn
{key, nested_key_values}, acc when is_map(nested_key_values) ->
flatten_nested_body(nested_key_values, "#{parent_key}[#{key}]") ++ acc

{key, [{_key, _value} | _rest] = nested_key_values}, acc ->
flatten_nested_body(nested_key_values, "#{parent_key}[#{key}]") ++ acc

Expand Down
31 changes: 30 additions & 1 deletion test/httpoison_test.exs
Expand Up @@ -82,7 +82,7 @@ defmodule HTTPoisonTest do
)
end

test "post nested form data" do
test "post nested form data when given as keyword list" do
assert_response(
HTTPoison.post(
"localhost:4002/post",
Expand All @@ -105,6 +105,35 @@ defmodule HTTPoisonTest do
)
end

test "post nested form data when given as map (no order guaranteed)" do
assert_response(
HTTPoison.post(
"localhost:4002/post",
{:form, %{not_nested: [1, 2], nested: %{foo: "bar", again: %{hello: "world"}}}},
%{"Content-type" => "application/x-www-form-urlencoded"}
),
fn %HTTPoison.Response{request: request} = response ->
assert {:form, body} = request.body

assert [{:not_nested, [1, 2]}, {"nested[foo]", "bar"}, {"nested[again][hello]", "world"}]
|> MapSet.new()
|> MapSet.equal?(MapSet.new(body))

Regex.match?(~r/"not_nested".*\x01\x02/, response.body)
Regex.match?(~r/"nested\[foo\]".*"bar"/, response.body)
Regex.match?(~r/"nested\[again\]\[hello\]".*"world"/, response.body)

assert {:ok,
"curl -X POST -H 'Content-type: application/x-www-form-urlencoded'" <> form_params} =
Request.to_curl(response.request)

assert form_params =~ "-F 'not_nested=\x01\x02'"
assert form_params =~ "-F 'nested[foo]=bar'"
assert form_params =~ "-F 'nested[again][hello]=world'"
end
)
end

test "put" do
assert_response(HTTPoison.put("localhost:4002/put", "test"), fn response ->
assert Request.to_curl(response.request) ==
Expand Down

0 comments on commit 3a436f1

Please sign in to comment.