Repository: tallarium/reverse_proxy_plug (elixir)

Issue:
[TEST] The client adapter does not support streaming responses. Please use :buffer response mode.
I'm receiving the error during tests:
 The client adapter does not support streaming responses. Please use :buffer response mode.
 
 But I don't understand how to specify that streaming mode is supported.
 
Config:
`config :reverse_proxy_plug, :http_client, ReverseProxyPlug.HTTPClient.Adapters.HTTPoison`

Elixir version: 1.16.1



Pull request description:
ensure adapter module is loaded before proceeding
fixes #193 

After 3476177d1d524abbac73af30c25c701d84d20eba, first released in 2.4.0, we now check for the existence of a function (`stream_response/1`) during module load.

The previous code would have always checked to ensure `HTTPoison` was loaded using `Code.ensure_loaded/1`.

Use `Code.ensure_loaded/1` to ensure that the module is loaded or raise an exception if it cannot be loaded, and rewrite `ensure_http_client` so that it happens in all cases.

(`Code.ensure_loaded!` was first available in 1.12. When the next major version is released, the current case statement will be cleaned up in favour of this)

Patch:
diff --git a/lib/reverse_proxy_plug.ex b/lib/reverse_proxy_plug.ex
index 1f25668..8784e1b 100644
--- a/lib/reverse_proxy_plug.ex
+++ b/lib/reverse_proxy_plug.ex
@@ -400,19 +400,21 @@ defmodule ReverseProxyPlug do
   end
 
   defp ensure_http_client(opts) do
-    client = opts[:client] || Application.get_env(:reverse_proxy_plug, :http_client)
-
-    cond do
-      not is_nil(client) ->
-        Keyword.put(opts, :client, client)
-
-      Code.ensure_loaded?(HTTPClient.Adapters.HTTPoison) and is_nil(client) ->
-        Keyword.put(opts, :client, HTTPClient.Adapters.HTTPoison)
+    module =
+      opts[:client] || Application.get_env(:reverse_proxy_plug, :http_client) ||
+        HTTPClient.Adapters.HTTPoison
+
+    client =
+      case Code.ensure_loaded(module) do
+        {:module, module} ->
+          module
+
+        {:error, reason} ->
+          raise ArgumentError,
+                "could not load module #{inspect(module)} due to reason #{inspect(reason)}"
+      end
 
-      true ->
-        raise ArgumentError,
-              ":client option or :reverse_proxy_plug, :http_client global config must be set"
-    end
+    Keyword.put(opts, :client, client)
   end
 
   defp ensure_response_mode_compatibility(opts) do


Test patch:
diff --git a/test/reverse_proxy_plug_test.exs b/test/reverse_proxy_plug_test.exs
index 7110bf9..7bf091a 100644
--- a/test/reverse_proxy_plug_test.exs
+++ b/test/reverse_proxy_plug_test.exs
@@ -36,6 +36,10 @@ defmodule ReverseProxyPlugTest do
 
   setup :verify_on_exit!
 
+  defmodule MyCustomAdapter do
+    # Used for adapter configuration testing
+  end
+
   test "receives buffer response" do
     headers = [{"host", "example.com"}, {"content-length", "42"}]
 
@@ -721,6 +725,22 @@ defmodule ReverseProxyPlugTest do
              )
 
     assert adapter == opts[:client]
+
+    # Raises if the module is invalid
+
+    Application.put_env(
+      :reverse_proxy_plug,
+      :http_client,
+      Nonsense
+    )
+
+    assert_raise ArgumentError, fn ->
+      ReverseProxyPlug.init(
+        upstream: "",
+        error_callback: {__MODULE__, :error_handler, []},
+        response_mode: :buffer
+      )
+    end
   end
 
   test_stream_and_buffer "recycles cookies from connection" do