Repository: phoenixframework/phoenix
Pull request #2258 (2017-04-20 08:34:42)

Fix current_path error when using nested query params
This fixes errors like this:

```
Request: GET /listings?filter[status]=draft
** (exit) an exception was raised:
    ** (Protocol.UndefinedError) protocol String.Chars not implemented for %{"status" => "draft"}
        (elixir) lib/string/chars.ex:3: String.Chars.impl_for!/1
        (elixir) lib/string/chars.ex:17: String.Chars.to_string/1
        (elixir) lib/uri.ex:105: URI.encode_kv_pair/1
        (elixir) lib/enum.ex:1293: anonymous fn/4 in Enum.map_join/3
        (stdlib) lists.erl:1263: :lists.foldl/3
        (elixir) lib/enum.ex:1772: Enum.map_join/3
        (phoenix) lib/phoenix/controller.ex:1288: Phoenix.Controller.current_path/2
        (web) lib/web/views/view_helpers.ex:36: Web.ViewHelpers.link/3
        (web) lib/web/templates/component/menu.html.slim:9: Web.ComponentView."menu.html"/1
        (web) lib/web/templates/layout/app.html.slim:28: Web.LayoutView."app.html"/1
        (phoenix) lib/phoenix/view.ex:332: Phoenix.View.render_to_iodata/3
        (phoenix) lib/phoenix/controller.ex:744: Phoenix.Controller.do_render/4
        (web) lib/web/controllers/listing_controller.ex:1: Web.ListingController.action/2
        (web) lib/web/controllers/listing_controller.ex:1: Web.ListingController.phoenix_controller_pipeline/2
        (web) lib/web/endpoint.ex:1: Web.Endpoint.instrument/4
        (phoenix) lib/phoenix/router.ex:277: Phoenix.Router.__call__/1
        (web) lib/plug/error_handler.ex:64: Web.Router.call/2
        (web) lib/web/endpoint.ex:1: Web.Endpoint.plug_builder_call/2
        (web) lib/plug/debugger.ex:123: Web.Endpoint."call (overridable 3)"/2
        (web) lib/web/endpoint.ex:1: Web.Endpoint.call/2
```


Patch:
diff --git a/lib/phoenix/controller.ex b/lib/phoenix/controller.ex
index 1c1bfaa4e..45c19d037 100644
--- a/lib/phoenix/controller.ex
+++ b/lib/phoenix/controller.ex
@@ -1271,6 +1271,9 @@ defmodule Phoenix.Controller do
       iex> current_path(conn, %{new: "param"})
       "/users/123?new=param"
 
+      iex> current_path(conn, %{filter: %{status: ["draft", "published"})
+      "/users/123?filter[status][]=draft&filter[status][]=published"
+
       iex> current_path(conn, %{})
       "/users/123"
   """
@@ -1281,7 +1284,7 @@ defmodule Phoenix.Controller do
     conn.request_path
   end
   def current_path(%Plug.Conn{} = conn, params) do
-    conn.request_path <> "?" <> URI.encode_query(params)
+    conn.request_path <> "?" <> Plug.Conn.Query.encode(params)
   end
 
   @doc ~S"""


Test patch:
diff --git a/test/phoenix/controller/controller_test.exs b/test/phoenix/controller/controller_test.exs
index 657dbd31d..4718fee69 100644
--- a/test/phoenix/controller/controller_test.exs
+++ b/test/phoenix/controller/controller_test.exs
@@ -562,6 +562,11 @@ defmodule Phoenix.Controller.ControllerTest do
       assert current_path(conn, %{three: 3}) == "/foo?three=3"
     end
 
+    test "current_path/2 allows custom nested query params" do
+      conn = build_conn_for_path("/")
+      assert current_path(conn, %{foo: %{bar: [:baz], baz: :qux}}) == "/?foo[bar][]=baz&foo[baz]=qux"
+    end
+
     test "current_url/1 with root path includes trailing slash" do
       conn = build_conn_for_path("/")
       assert current_url(conn) == "https://www.example.com/"