From 96a4d76e3c0321a2adddc9dbb3fa1415b3da5db3 Mon Sep 17 00:00:00 2001 From: Eduardo Gurgel Date: Sun, 18 May 2014 16:11:10 +1200 Subject: [PATCH] Support multiple values same key on /get --- lib/httparrot/general_request_info.ex | 23 ++++++++++++++++++++++- test/general_request_info_test.exs | 21 +++++++++++++++++++-- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/lib/httparrot/general_request_info.ex b/lib/httparrot/general_request_info.ex index e80189a..bc15750 100644 --- a/lib/httparrot/general_request_info.ex +++ b/lib/httparrot/general_request_info.ex @@ -6,8 +6,29 @@ defmodule HTTParrot.GeneralRequestInfo do {{ip, _port}, req} = :cowboy_req.peer(req) ip = :inet_parse.ntoa(ip) |> to_string - if args == [], do: args = [{}] + args = flatten_dict(args) {[args: args, headers: headers, url: url, origin: ip], req} end + + @doc """ + Group by keys and if duplicated keys, aggregate them as a list + + iex> flatten_dict([a: "v1", a: "v2", b: "v3"]) + %{a: ["v1", "v2"], b: "v3"} + """ + @spec flatten_dict(list) :: map + def flatten_dict([]), do: %{} + def flatten_dict(args) do + Enum.group_by(args, %{}, fn {k, _} -> k end) + |> Enum.traverse(fn {k1, v1} -> + values = Enum.map(v1, fn {_, v2} -> v2 end) + |> Enum.reverse + |> flatten_if_list_of_one + {k1, values} + end) + end + + defp flatten_if_list_of_one([h]), do: h + defp flatten_if_list_of_one(list), do: list end diff --git a/test/general_request_info_test.exs b/test/general_request_info_test.exs index 9cbd32b..67a40c9 100644 --- a/test/general_request_info_test.exs +++ b/test/general_request_info_test.exs @@ -11,6 +11,8 @@ defmodule HTTParrot.GeneralRequestInfoTest do unload :cowboy_req end + doctest HTTParrot.GeneralRequestInfo + test "returns a list of args, headers, url and original ip" do qs_vals = [{"a", "b"}] headers = [header1: "value 1", header2: "value 2"] @@ -21,7 +23,22 @@ defmodule HTTParrot.GeneralRequestInfoTest do expect(:cowboy_req, :url, 1, {url, :req4}) expect(:cowboy_req, :peer, 1, {{ip, :host}, :req5}) - assert retrieve(:req1) == {[args: qs_vals, headers: headers, url: url, origin: "127.1.2.3"], :req5} + assert retrieve(:req1) == {[args: %{"a" => "b"}, headers: headers, url: url, origin: "127.1.2.3"], :req5} + + assert validate :cowboy_req + end + + test "returns a list of args with duplicated keys, headers, url and original ip" do + qs_vals = [{"a", "b"}, {"a", "c"}] + headers = [header1: "value 1", header2: "value 2"] + ip = {127, 1, 2, 3} + url = "http://localhost/get?a=b&a=c" + expect(:cowboy_req, :qs_vals, 1, {qs_vals, :req2}) + expect(:cowboy_req, :headers, 1, {headers, :req3}) + expect(:cowboy_req, :url, 1, {url, :req4}) + expect(:cowboy_req, :peer, 1, {{ip, :host}, :req5}) + + assert retrieve(:req1) == {[args: %{"a" => ["b", "c"]}, headers: headers, url: url, origin: "127.1.2.3"], :req5} assert validate :cowboy_req end @@ -36,7 +53,7 @@ defmodule HTTParrot.GeneralRequestInfoTest do expect(:cowboy_req, :url, 1, {url, :req4}) expect(:cowboy_req, :peer, 1, {{ip, :host}, :req5}) - assert retrieve(:req1) == {[args: [{}], headers: headers, url: url, origin: "127.1.2.3"], :req5} + assert retrieve(:req1) == {[args: %{}, headers: headers, url: url, origin: "127.1.2.3"], :req5} assert validate :cowboy_req end