From fa9646602fca5f21275f31c59dccf2868846d0fc Mon Sep 17 00:00:00 2001 From: Alexei Sholik Date: Sun, 6 May 2012 13:28:24 +0300 Subject: [PATCH] Implement decode_query in URI --- lib/uri.ex | 27 +++++++++++++++++++++++++++ test/elixir/uri_test.exs | 9 +++++++++ 2 files changed, 36 insertions(+) diff --git a/lib/uri.ex b/lib/uri.ex index b95b5d67e70..6d797485285 100644 --- a/lib/uri.ex +++ b/lib/uri.ex @@ -21,6 +21,33 @@ defmodule URI do """ def encode_query(l), do: Enum.join(Enum.map(l, pair(&1)), "&") + @doc """ + Given a query string of the form "key1=value1&key=value2...", produces an + orddict with one entry for each key-value pair. Each key and value will be a + binary. It also does percent-unescaping of both keys and values. + + Returns nil if the query string is malformed. + """ + def decode_query(q) do + parts = Regex.split %r/&/, q + # Set up a try block to return quickly from List.foldl in case of an error + try do + List.foldl parts, Orddict.new, fn(kvstr, dict) -> + pair = case Regex.split(%r/=/, kvstr) do + match: [ key, value ] + { decode(key), decode(value) } + match: [ key ] + { decode(key), "" } + else: + raise "bad query" + end + Dict.Orddict.Record.put dict, pair + end + rescue: RuntimeError + nil + end + end + defp pair({k, v}) do encode(to_binary(k)) <> "=" <> encode(to_binary(v)) end diff --git a/test/elixir/uri_test.exs b/test/elixir/uri_test.exs index da30ee7fdc8..7b357e68083 100644 --- a/test/elixir/uri_test.exs +++ b/test/elixir/uri_test.exs @@ -28,6 +28,15 @@ defmodule URITest do assert URI.encode_query([{:foo, 'bar'}]) == "foo=bar" end + test :decode_query do + assert URI.decode_query("q=search%20query&cookie=ab%26cd&block%20buster=") == + Orddict.new [{"block buster", ""}, {"cookie", "ab&cd"}, {"q", "search query"}] + assert URI.decode_query("") == Orddict.new + + assert URI.decode_query("something=weird=happening") == nil + assert URI.decode_query("something=weird%3Dhappening") == Orddict.new [{"something", "weird=happening"}] + end + test :decode do data_to_be_decoded = "%26%3C%3E%22+%E3%82%86%E3%82%93%E3%82%86%E3%82%93" assert URI.decode(data_to_be_decoded) == "&<>\" ゆんゆん"