diff --git a/lib/open_api_spex/cast_parameters.ex b/lib/open_api_spex/cast_parameters.ex index 1155cb79..bd44fe8b 100644 --- a/lib/open_api_spex/cast_parameters.ex +++ b/lib/open_api_spex/cast_parameters.ex @@ -39,7 +39,12 @@ defmodule OpenApiSpex.CastParameters do end defp get_params_by_location(conn, :query, _) do - Plug.Conn.fetch_query_params(conn).query_params + params = Plug.Conn.fetch_query_params(conn).query_params + + Enum.reduce(params, %{}, fn param, acc -> + {updated_key, updated_value} = parse_query_param(param) + Map.update(acc, updated_key, updated_value, &[&1 | updated_value]) + end) end defp get_params_by_location(conn, :path, _) do @@ -61,6 +66,14 @@ defmodule OpenApiSpex.CastParameters do do: {property_name, value} end + defp parse_query_param({key, value}) when is_list(value) do + {"#{key}[]", value} + end + + defp parse_query_param(param) do + param + end + defp create_location_schema(parameters, components) do { %Schema{ diff --git a/test/operation2_test.exs b/test/operation2_test.exs index 9eeba145..e308b56c 100644 --- a/test/operation2_test.exs +++ b/test/operation2_test.exs @@ -50,6 +50,12 @@ defmodule OpenApiSpex.Operation2Test do @user_index %Operation{ operationId: "UserController.index", parameters: [ + Operation.parameter( + :"ids[]", + :query, + %Schema{type: :array, items: %Schema{type: :integer}}, + "Filter by user ids" + ), Operation.parameter(:name, :query, :string, "Filter by user name"), Operation.parameter(:age, :query, :integer, "Filter by user age"), %Reference{"$ref": "#/components/parameters/member"}, @@ -299,13 +305,21 @@ defmodule OpenApiSpex.Operation2Test do end test "casts valid query params and respects defaults" do - valid_query_params = %{"name" => "Rubi", "age" => "31", "member" => "true"} + valid_query_params = %{"ids[]" => 1, "name" => "Rubi", "age" => "31", "member" => "true"} assert {:ok, conn} = do_index_cast(valid_query_params) - assert conn.params == %{age: 31, member: true, name: "Rubi", include_archived: false} + + assert conn.params == %{ + "ids[]": [1], + age: 31, + member: true, + name: "Rubi", + include_archived: false + } end test "casts valid query params and overrides defaults" do valid_query_params = %{ + "ids[]" => 1, "name" => "Rubi", "age" => "31", "member" => "true", @@ -313,15 +327,29 @@ defmodule OpenApiSpex.Operation2Test do } assert {:ok, conn} = do_index_cast(valid_query_params) - assert conn.params == %{age: 31, member: true, name: "Rubi", include_archived: true} + + assert conn.params == %{ + "ids[]": [1], + age: 31, + member: true, + name: "Rubi", + include_archived: true + } end test "cast valid query params with replace_params: false" do - valid_query_params = %{"name" => "Rubi", "age" => "31", "member" => "true"} + valid_query_params = %{"ids[]" => 1, "name" => "Rubi", "age" => "31", "member" => "true"} assert {:ok, conn} = do_index_cast(valid_query_params, replace_params: false) - assert Plug.Conn.fetch_query_params(conn).params == valid_query_params + + assert Plug.Conn.fetch_query_params(conn).params == %{ + "ids" => ["1"], + "name" => "Rubi", + "age" => "31", + "member" => "true" + } assert conn.private.open_api_spex.params == %{ + "ids[]": [1], age: 31, member: true, name: "Rubi", @@ -330,9 +358,9 @@ defmodule OpenApiSpex.Operation2Test do end test "casts valid query params without applying defaults" do - valid_query_params = %{"name" => "Rubi", "age" => "31", "member" => "true"} + valid_query_params = %{"ids[]" => 1, "name" => "Rubi", "age" => "31", "member" => "true"} assert {:ok, conn} = do_index_cast(valid_query_params, apply_defaults: false) - assert conn.params == %{age: 31, member: true, name: "Rubi"} + assert conn.params == %{"ids[]": [1], age: 31, member: true, name: "Rubi"} end test "validate invalid data type for query param" do diff --git a/test/plug/cast_test.exs b/test/plug/cast_test.exs index 22b7e78f..2df5cf53 100644 --- a/test/plug/cast_test.exs +++ b/test/plug/cast_test.exs @@ -38,6 +38,18 @@ defmodule OpenApiSpex.Plug.CastTest do assert OpenApiSpex.params(conn) == %{validParam: true} end + test "ids[] param" do + conn = + :get + |> Plug.Test.conn("/api/users?ids[]=123") + |> OpenApiSpexTest.Router.call([]) + + assert conn.status == 200 + assert conn.private.open_api_spex.params == conn.params + + assert OpenApiSpex.params(conn) == %{"ids[]": [123]} + end + test "valid param with replace_params false" do conn = :get diff --git a/test/support/user_controller.ex b/test/support/user_controller.ex index b4522f66..6aeb8526 100644 --- a/test/support/user_controller.ex +++ b/test/support/user_controller.ex @@ -41,7 +41,13 @@ defmodule OpenApiSpexTest.UserController do List all users """ @doc parameters: [ - validParam: [in: :query, type: :boolean, description: "Valid Param", example: true] + validParam: [in: :query, type: :boolean, description: "Valid Param", example: true], + "ids[]": [ + in: :query, + type: %Schema{type: :array, items: %Schema{type: :integer}}, + description: "User IDs", + example: 123 + ] ], responses: [ ok: {"User List Response", "application/json", Schemas.UsersResponse}