edgurgel / httpoison

Yet Another HTTP client for Elixir powered by hackney
https://hex.pm/packages/httpoison
MIT License
2.23k stars 340 forks source link

Optionally avoid url encoding params #258

Open axelson opened 7 years ago

axelson commented 7 years ago

Hi is it possible to avoid running URI.encode_query on the passed in params?

Currently the params are always being run through URI.encode_query in https://github.com/edgurgel/httpoison/blob/a4a7877/lib/httpoison/base.ex#L162:

   url =
      cond do
        not Keyword.has_key?(options, :params) -> url
        URI.parse(url).query                   -> url <> "&" <> URI.encode_query(options[:params])
        true                                   -> url <> "?" <> URI.encode_query(options[:params])
      end

I would like to not url-encode one of the params (because I need to avoid url-encoding the , character) for a particular API that I am working with. Do I have any alternatives beside running URI.encode_query on my other parameters and joining my non-encoded param manually with a &?

edgurgel commented 7 years ago

@axelson have you tried doing this approach you mentioned? Cause I'm worried that hackney will also try to url encode :/

axelson commented 7 years ago

@edgurgel currently I am inserting the parameter that I need (urls) directly onto the url

url = @base_url <> "?urls=" <> encode_urls_param(urls)
case @embedly_client.get(url) do

Where @embedly_client has use HTTPoison.Base.

It appears to be working, I'd just prefer a nicer API if possible. Also I haven't tested it with additional params, but I expect that would work as well (since it would fall under the last condition in the original code snippet I posted).

astjohn commented 6 years ago

This is also relevant when accessing the linkedIN v1 api.

https://api.linkedin.com/v1/people/~:(id,emailAddress,firstName,lastName,numConnections,pictureUrl)

LinkedIN won't register properly if the url is encoded. @axelson - any chance you can elaborate on your solution? Thanks!

axelson commented 6 years ago

@astjohn here's some more snippets if they're helpful

    base_path = "/api/v2"
    # Currently there is no way to avoid url encoding the entire params map so we need to manually encode the urls parameter (so that the individual url's are encoded, but the commas that separate the url's are not)
    # https://github.com/edgurgel/httpoison/issues/258
    query = "urls=" <> encode_urls_param(urls) <> "&secure=true"
    path = %URI{path: base_path, query: query} |> URI.to_string()

    case @embedly_client.get(path) do
      {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
        body |> Enum.map(&parse_response/1)
      response -> [handle_error_response(response)]
    end

Where @embedly_client is

defmodule Unfurler.EmbedlyClient do
  use HTTPoison.Base

  def process_url(path) do
    System.get_env("EMBEDLY_API_BASE_URL")
    |> URI.parse
    |> URI.merge(path)
    |> URI.to_string
  end

  def process_response_body(body) do
    body |> Poison.decode!
  end

  def process_request_options(options) do
    key = System.get_env("EMBEDLY_API_KEY")
    cond do
      is_map(options[:params]) ->
        put_in(options[:params][:key], key)
      true ->
        put_in(options[:params], %{key: key})
    end
  end

end
jeanparpaillon commented 5 years ago

Any idea on this ? I have the same problem (linkedin API). I can not find a solution playing with callbacks.

ryanwinchester commented 5 years ago

Somewhat related to #195