Skip to content

Commit

Permalink
Improve query parsing
Browse files Browse the repository at this point in the history
Return a { :error, msg } tuple instead of nil. Better handle some edge
cases.
  • Loading branch information
alco committed May 6, 2012
1 parent aee124d commit e31cca0
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 15 deletions.
32 changes: 18 additions & 14 deletions lib/uri.ex
Expand Up @@ -29,22 +29,26 @@ defmodule URI do
Returns nil if the query string is malformed.
"""
def decode_query(q) do
parts = Regex.split %r/&/, to_binary(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"
# If the string is blank, return an empty dict
empty_dict = Orddict.new
if Regex.match?(%r"^\s*$", q) do
empty_dict
else:
parts = Regex.split %r/&/, to_binary(q)
# Set up a try block to return quickly from List.foldl in case of an error
try do
List.foldl parts, empty_dict, fn(kvstr, dict) ->
pair = case Regex.split(%r/=/, kvstr) do
match: [ key, value ] when size(key) > 0
{ decode(key), decode(value) }
else:
throw { :error, "Malformed query string" }
end
Dict.Orddict.Record.put dict, pair
end
Dict.Orddict.Record.put dict, pair
catch: x
x
end
rescue: RuntimeError
nil
end
end

Expand Down
7 changes: 6 additions & 1 deletion test/elixir/uri_test.exs
Expand Up @@ -29,13 +29,18 @@ defmodule URITest do
end

test :decode_query do
error = { :error, "Malformed query string" }

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('list=works') == Orddict.new [{"list", "works"}]
assert URI.decode_query("garbage") == error
assert URI.decode_query("=value") == error

assert URI.decode_query("something=weird=happening") == nil
assert URI.decode_query("something=weird=happening") == error
assert URI.decode_query("something=weird%3Dhappening") == Orddict.new [{"something", "weird=happening"}]

end

test :decode do
Expand Down

0 comments on commit e31cca0

Please sign in to comment.