diff --git a/lib/plug/conn.ex b/lib/plug/conn.ex index d046ce2e..e538d489 100644 --- a/lib/plug/conn.ex +++ b/lib/plug/conn.ex @@ -1470,8 +1470,8 @@ defmodule Plug.Conn do function; it is entirely possible (likely, even) that the server will only do the actual upgrade later in the connection lifecycle. - If the adapter does not support the requested protocol this function will raise an - `ArgumentError`. The underlying adapter may also signal errors in the provided arguments by + If the adapter does not support the requested protocol, or if it returns any other error + for the requested upgrade, this function will raise an `ArgumentError`. The underlying adapter may also signal errors in the provided arguments by raising; consult the corresponding adapter documentation for details. """ @spec upgrade_adapter(t, atom, term) :: t @@ -1485,6 +1485,10 @@ defmodule Plug.Conn do {:error, :not_supported} -> raise ArgumentError, "upgrade to #{protocol} not supported by #{inspect(adapter)}" + + {:error, reason} -> + raise ArgumentError, + "upgrade to #{protocol} failed in #{inspect(adapter)}: #{inspect(reason)}" end end diff --git a/test/plug/conn_test.exs b/test/plug/conn_test.exs index f93a182b..7e288168 100644 --- a/test/plug/conn_test.exs +++ b/test/plug/conn_test.exs @@ -499,6 +499,21 @@ defmodule Plug.ConnTest do ) end + defmodule UpgradeErrorAdapter do + def upgrade(_payload, _protocol, _args), do: {:error, :bad_args} + end + + test "upgrade_adapter/3 raises an error on failed upgrades" do + assert_raise( + ArgumentError, + "upgrade to websocket failed in Plug.ConnTest.UpgradeErrorAdapter: :bad_args", + fn -> + %{conn(:get, "/foo") | adapter: {UpgradeErrorAdapter, nil}} + |> upgrade_adapter(:websocket, opt: :bad) + end + ) + end + test "upgrade_adapter/3 will raise if the response is sent before upgrading" do assert_raise(Plug.Conn.AlreadySentError, fn -> conn(:get, "/foo")