Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested form-encoded params don't work #469

Closed
vereis opened this issue Feb 7, 2023 · 2 comments · Fixed by #470
Closed

Nested form-encoded params don't work #469

vereis opened this issue Feb 7, 2023 · 2 comments · Fixed by #470

Comments

@vereis
Copy link
Contributor

vereis commented Feb 7, 2023

Ahoy!

We're using HTTPoison to interface with Stripe's Metadata API and tried to do the following:

params = %{
  "amount" => "100"
  "currency" => "usd",
  "payment_method" => card_id,
  "description" => "Invoice #{invoice.id}",
  "confirm" => true,
  "metadata" => %{"hello" => "world", "foo" => "bar"}
  }

{:ok, response} =
  HTTPoison.post( "https://api.stripe.com/v1/payment_intents", {:form, Map.to_list(params)}, [], hackney: [ basic_auth: {api_token, ""} ])

And we noticed that this fails with the following:

(FunctionClauseError) no function clause matching in :hackney_bstr.to_binary/1

I think we can fix this by changing the following

{:form, form} -> form |> Enum.map(fn {k, v} -> "-F '#{k}=#{v}'" end) |> Enum.join(" ")

to:

def deconstruct_nested_params({k, v}) when is_list(v) or is_map(v) do
  for {nested_k, nested_v} <- v do
    deconstruct_nested_params({"#{k}[#{nested_k}]", nested_v})
  end
end

def deconstruct_nested_params({k, v}) do
  {k, v}
end

...

{:form, form} -> 
  form
  |> Enum.map(&deconstruct_nested_params/1)
  |> List.flatten()
  |> Enum.map(fn {k, v} when is_-> "-F '#{k}=#{v}'" end)
  |> Enum.join(" ")

I know the above code is gross, but if you're happy for a contribution I'd be glad to try and clean it up & put together a PR? ❤️

Also, do you have any thoughts about supporting maps as well as keyword lists as param keys? Since you're using Enum anyway, you can just say you support both which might make some dialyzer users happy.

Thanks again!

@edgurgel
Copy link
Owner

Hi @vereis ! First thanks for opening this issue!

Also, do you have any thoughts about supporting maps as well as keyword lists as param keys? Since you're using Enum anyway, you can just say you support both which might make some dialyzer users happy.

Definitely 👍

In regards to the nested form-encoded params there was some discussion in the past here: #121

But thinking about this again I suppose that it's harmless to accept such params given that today it simply errors out and this way of encoding nested data seems to be widely used. So please if you want send us a PR ❤️

Thanks!

@vereis
Copy link
Contributor Author

vereis commented Feb 15, 2023

Oops I did search for existing issues but somehow missed that, sorry for the dupe but glad you're willing to accept a PR ❤️

I'll submit a PR later today thank you!

tommasop added a commit to tommasop/gringotts that referenced this issue Jan 30, 2024
Allow nested form params:
edgurgel/httpoison#469
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants