From 41c761f0af981bfc826b9481ee078010694f2188 Mon Sep 17 00:00:00 2001 From: Grant Date: Wed, 28 Oct 2020 11:10:19 -0400 Subject: [PATCH 1/2] Allow Tesla middleware to be configured To provide support for custom middleware, allow the `ExForce.Client.Tesla.build_client/2` method to take an additional param in it's opts argument defining middleware to run. The choice was made to allow users to provide their own instrumentation The middleware runs _before_ the compression/json encoding and _after_ the API version headers --- lib/ex_force/client/tesla/tesla.ex | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/ex_force/client/tesla/tesla.ex b/lib/ex_force/client/tesla/tesla.ex index 2968e1f..af4dc9c 100644 --- a/lib/ex_force/client/tesla/tesla.ex +++ b/lib/ex_force/client/tesla/tesla.ex @@ -29,6 +29,7 @@ defmodule ExForce.Client.Tesla do - `:headers`: set additional headers; default: `[{"user-agent", "#{@default_user_agent}"}]` - `:api_version`: use the given api_version; default: `"#{@default_api_version}"` - `:adapter`: use the given adapter with custom opts; default: `nil`, which causes Tesla to use the default adapter or the one set in config. + - `:middleware`: set additional middleware to use in the Tesla Client """ @impl ExForce.Client def build_client(instance_url_or_map, opts \\ [headers: [{"user-agent", @default_user_agent}]]) @@ -42,16 +43,18 @@ defmodule ExForce.Client.Tesla do end def build_client(instance_url, opts) when is_binary(instance_url) do - Tesla.client( - [ - {ExForce.Client.Tesla.Middleware, - {instance_url, Keyword.get(opts, :api_version, @default_api_version)}}, - {Tesla.Middleware.Compression, format: "gzip"}, - {Tesla.Middleware.JSON, engine: Jason}, - {Tesla.Middleware.Headers, Keyword.get(opts, :headers, [])} - ], - Keyword.get(opts, :adapter) - ) + additional_middleware = Keyword.get(opts, :middleware, []) + + middleware = [ + {ExForce.Client.Tesla.Middleware, + {instance_url, Keyword.get(opts, :api_version, @default_api_version)}}, + additional_middleware, + {Tesla.Middleware.Compression, format: "gzip"}, + {Tesla.Middleware.JSON, engine: Jason}, + {Tesla.Middleware.Headers, Keyword.get(opts, :headers, [])} + ] |> List.flatten + + Tesla.client(middleware, Keyword.get(opts, :adapter)) end @doc """ From 7ffa9c4a577e0617c7bca33544cff34da4253d24 Mon Sep 17 00:00:00 2001 From: Grant Date: Wed, 28 Oct 2020 12:06:50 -0400 Subject: [PATCH 2/2] Add specs around adding middleware --- test/ex_force/client/tesla_test.exs | 53 +++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 test/ex_force/client/tesla_test.exs diff --git a/test/ex_force/client/tesla_test.exs b/test/ex_force/client/tesla_test.exs new file mode 100644 index 0000000..4e3e7a8 --- /dev/null +++ b/test/ex_force/client/tesla_test.exs @@ -0,0 +1,53 @@ +defmodule ExForce.Client.TeslaTest do + use ExUnit.Case, async: false + alias ExForce.{Client, Request} + alias Plug.Conn + + defmodule TestMiddleware do + @behaviour Tesla.Middleware + + @impl Tesla.Middleware + def call(env, next, test_pid: test_pid, id: id) when is_pid(test_pid) do + send(test_pid, {:before, id}) + result = Tesla.run(env, next) + send(test_pid, {:after, id}) + + result + end + end + + setup do + %{bypass: Bypass.open()} + end + + test "it will use the custom middleware provided to it", %{bypass: bypass} do + 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.Client.Tesla.build_client(%{instance_url: bypass_url(bypass), access_token: "foo"}, + middleware: [ + {TestMiddleware, test_pid: self(), id: 1}, + {TestMiddleware, test_pid: self(), id: 2}, + {TestMiddleware, test_pid: self(), id: 3} + ] + ) + + {:ok, _response} = Client.request(client, %Request{url: "/foo", method: :get}) + + assert {:messages, + [ + before: 1, + before: 2, + before: 3, + after: 3, + after: 2, + after: 1 + ]} = Process.info(self(), :messages) + end + + defp bypass_url(bypass), do: "http://127.0.0.1:#{bypass.port}" +end