diff --git a/lib/ex_force.ex b/lib/ex_force.ex index e5752c1..df51d61 100644 --- a/lib/ex_force.ex +++ b/lib/ex_force.ex @@ -14,6 +14,21 @@ defmodule ExForce do end ``` + Configure default settings for the Tesla client (currently the only + client supported) in config/config.exs (optional). + + ```elixir + # config/config.exs + + config :ex_force, ExForce.Client.Tesla, + api_version: "43.0", + adapter: {Tesla.Adapter.Hackney, [recv_timeout: 1_000]}, + append_middleware: [ + Tesla.Middleware.Telemetry, + {Tesla.Middleware.Timeout, timeout: :timer.seconds(1)} + ] + ``` + Check out [Choosing a Tesla Adapter](https://github.com/chulkilee/ex_force/wiki/Choosing-a-Tesla-Adapter). ## Usage diff --git a/lib/ex_force/client/tesla/tesla.ex b/lib/ex_force/client/tesla/tesla.ex index 3fb960c..e4b0e23 100644 --- a/lib/ex_force/client/tesla/tesla.ex +++ b/lib/ex_force/client/tesla/tesla.ex @@ -41,19 +41,23 @@ defmodule ExForce.Client.Tesla do end def build_client(instance_url, opts) when is_binary(instance_url) do - Tesla.client( + adapter = get_from_opts_or_config(opts, :adapter) + headers = get_headers(opts) + + middleware = [ {ExForce.Client.Tesla.Middleware, - {instance_url, Keyword.get(opts, :api_version, @default_api_version)}}, + {instance_url, get_from_opts_or_config(opts, :api_version, @default_api_version)}}, {Tesla.Middleware.Compression, format: "gzip"}, {Tesla.Middleware.JSON, engine: Jason}, - {Tesla.Middleware.Headers, get_headers(opts)} - ], - Keyword.get(opts, :adapter) - ) + {Tesla.Middleware.Headers, headers} + ] ++ get_from_opts_or_config(opts, :append_middleware, []) + + Tesla.client(middleware, adapter) end - defp get_headers(opts), do: Keyword.get(opts, :headers, [{"user-agent", @default_user_agent}]) + defp get_headers(opts), + do: get_from_opts_or_config(opts, :headers, [{"user-agent", @default_user_agent}]) @doc """ Returns a `Tesla` client for `ExForce.OAuth` functions @@ -65,16 +69,18 @@ defmodule ExForce.Client.Tesla do """ @impl ExForce.Client def build_oauth_client(instance_url, opts \\ []) do - Tesla.client( + adapter = get_from_opts_or_config(opts, :adapter) + + middleware = [ + {Tesla.Middleware.DecodeJson, engine: Jason}, {Tesla.Middleware.BaseUrl, instance_url}, {Tesla.Middleware.Compression, format: "gzip"}, Tesla.Middleware.FormUrlencoded, - {Tesla.Middleware.DecodeJson, engine: Jason}, {Tesla.Middleware.Headers, get_headers(opts)} - ], - Keyword.get(opts, :adapter) - ) + ] ++ get_from_opts_or_config(opts, :append_middleware, []) + + Tesla.client(middleware, adapter) end @doc """ @@ -87,6 +93,15 @@ defmodule ExForce.Client.Tesla do |> cast_response() end + defp get_from_opts_or_config(opts, key, default \\ nil) do + from_opts = Keyword.get(opts, key) + + app_config = Application.get_env(:ex_force, __MODULE__, []) + from_app_config = Keyword.get(app_config, key) + + from_opts || from_app_config || default + end + defp cast_tesla_request(%Request{} = request) do request |> convert_struct(Tesla.Env) diff --git a/test/config_test.exs b/test/config_test.exs new file mode 100644 index 0000000..d6fe71e --- /dev/null +++ b/test/config_test.exs @@ -0,0 +1,59 @@ +defmodule ExForce.ConfigTest do + # Must be set to async: false since this is manipulating global application config + use ExUnit.Case, async: false + + alias ExForce.{ + Client, + Request + } + + alias Plug.Conn + + test "build_client/2 - custom config" do + bypass = Bypass.open() + bypass_url = "http://127.0.0.1:#{bypass.port}" + + api_version = "456.0" + + custom_middleware = [ + Tesla.Middleware.Telemetry, + {Tesla.Middleware.Timeout, timeout: :timer.seconds(1)} + ] + + custom_middleware_representation = [ + {Tesla.Middleware.Telemetry, :call, [[]]}, + {Tesla.Middleware.Timeout, :call, [[timeout: 1000]]} + ] + + Application.put_env(:ex_force, ExForce.Client.Tesla, + api_version: api_version, + append_middleware: custom_middleware + ) + + on_exit(fn -> Application.delete_env(:ex_force, ExForce.Client.Tesla) end) + + Bypass.expect_once(bypass, "GET", "/foo", fn conn -> + conn + |> Conn.put_resp_content_type("application/json") + |> Conn.resp(200, ~w({"hello": "world"})) + end) + + client = ExForce.build_client(bypass_url) + + assert %Tesla.Client{ + adapter: nil, + fun: nil, + post: [], + pre: + [ + {ExForce.Client.Tesla.Middleware, :call, [{^bypass_url, ^api_version}]}, + {Tesla.Middleware.Compression, :call, [[format: "gzip"]]}, + {Tesla.Middleware.JSON, :call, [[engine: Jason]]}, + {Tesla.Middleware.Headers, :call, [[{"user-agent", "ex_force"}]]} + ] ++ ^custom_middleware_representation + } = client + + assert {:ok, %{status: 200, body: %{"hello" => "world"}}} = + Client.request(client, %Request{url: "/foo", method: :get}) + end +end diff --git a/test/ex_force/oauth_test.exs b/test/ex_force/oauth_test.exs index 2e9d763..e9fe5df 100644 --- a/test/ex_force/oauth_test.exs +++ b/test/ex_force/oauth_test.exs @@ -335,10 +335,10 @@ defmodule ExForce.OAuthTest do fun: nil, post: [], pre: [ + {Tesla.Middleware.DecodeJson, :call, [[engine: Jason]]}, {Tesla.Middleware.BaseUrl, :call, ["http://257.0.0.0:0"]}, {Tesla.Middleware.Compression, :call, [[format: "gzip"]]}, {Tesla.Middleware.FormUrlencoded, :call, [[]]}, - {Tesla.Middleware.DecodeJson, :call, [[engine: Jason]]}, {Tesla.Middleware.Headers, :call, [[{"user-agent", "agent"}]]} ] }