Permalink
Browse files

Split parse_query utility into parse_query and parse_nested_query. pa…

…rse_nested_query now chooses the last value instead of returning an array of all of them.
  • Loading branch information...
1 parent c9b4159 commit 5c00dd698edb953b4bee432fa12a20ba69a067c1 @josh josh committed Feb 15, 2009
Showing with 65 additions and 43 deletions.
  1. +2 −2 lib/rack/request.rb
  2. +23 −11 lib/rack/utils.rb
  3. +40 −30 test/spec_rack_utils.rb
View
@@ -108,7 +108,7 @@ def GET
else
@env["rack.request.query_string"] = query_string
@env["rack.request.query_hash"] =
- Utils.parse_query(query_string)
+ Utils.parse_nested_query(query_string)
end
end
@@ -129,7 +129,7 @@ def POST
form_vars.sub!(/\0\z/, '')
@env["rack.request.form_vars"] = form_vars
- @env["rack.request.form_hash"] = Utils.parse_query(form_vars)
+ @env["rack.request.form_hash"] = Utils.parse_nested_query(form_vars)
begin
@env["rack.input"].rewind if @env["rack.input"].respond_to?(:rewind)
View
@@ -29,19 +29,39 @@ def unescape(s)
# and ';' characters. You can also use this to parse
# cookies by changing the characters used in the second
# parameter (which defaults to '&;').
-
def parse_query(qs, d = '&;')
params = {}
(qs || '').split(/[#{d}] */n).each do |p|
k, v = unescape(p).split('=', 2)
- normalize_params(params, k, v)
+
+ if cur = params[k]
+ if cur.class == Array
+ params[k] << v
+ else
+ params[k] = [cur, v]
+ end
+ else
+ params[k] = v
+ end
end
return params
end
module_function :parse_query
+ def parse_nested_query(qs, d = '&;')
+ params = {}
+
+ (qs || '').split(/[#{d}] */n).each do |p|
+ k, v = unescape(p).split('=', 2)
+ normalize_params(params, k, v)
+ end
+
+ return params
+ end
+ module_function :parse_nested_query
+
def normalize_params(params, name, v = nil)
name =~ %r([\[\]]*([^\[\]]+)\]*)
k = $1 || ''
@@ -50,15 +70,7 @@ def normalize_params(params, name, v = nil)
return if k.empty?
if after == ""
- if cur = params[k]
- if cur.is_a?(Array)
- params[k] << v
- else
- params[k] = [cur, v]
- end
- else
- params[k] = v
- end
+ params[k] = v
elsif after == "[]"
params[k] ||= []
raise TypeError unless params[k].is_a?(Array)
View
@@ -21,69 +21,79 @@
end
specify "should parse query strings correctly" do
- Rack::Utils.parse_query("foo").
+ Rack::Utils.parse_query("foo=bar").should.equal "foo" => "bar"
+ Rack::Utils.parse_query("foo=bar&foo=quux").
+ should.equal "foo" => ["bar", "quux"]
+ Rack::Utils.parse_query("foo=1&bar=2").
+ should.equal "foo" => "1", "bar" => "2"
+ Rack::Utils.parse_query("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F").
+ should.equal "my weird field" => "q1!2\"'w$5&7/z8)?"
+ end
+
+ specify "should parse nested query strings correctly" do
+ Rack::Utils.parse_nested_query("foo").
should.equal "foo" => nil
- Rack::Utils.parse_query("foo=").
+ Rack::Utils.parse_nested_query("foo=").
should.equal "foo" => ""
- Rack::Utils.parse_query("foo=bar").
+ Rack::Utils.parse_nested_query("foo=bar").
should.equal "foo" => "bar"
- Rack::Utils.parse_query("foo=bar&foo=quux").
- should.equal "foo" => ["bar", "quux"]
- Rack::Utils.parse_query("foo&foo=").
+ Rack::Utils.parse_nested_query("foo=bar&foo=quux").
+ should.equal "foo" => "quux"
+ Rack::Utils.parse_nested_query("foo&foo=").
should.equal "foo" => ""
- Rack::Utils.parse_query("foo=1&bar=2").
+ Rack::Utils.parse_nested_query("foo=1&bar=2").
should.equal "foo" => "1", "bar" => "2"
- Rack::Utils.parse_query("&foo=1&&bar=2").
+ Rack::Utils.parse_nested_query("&foo=1&&bar=2").
should.equal "foo" => "1", "bar" => "2"
- Rack::Utils.parse_query("foo&bar=").
+ Rack::Utils.parse_nested_query("foo&bar=").
should.equal "foo" => nil, "bar" => ""
- Rack::Utils.parse_query("foo=bar&baz=").
+ Rack::Utils.parse_nested_query("foo=bar&baz=").
should.equal "foo" => "bar", "baz" => ""
- Rack::Utils.parse_query("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F").
+ Rack::Utils.parse_nested_query("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F").
should.equal "my weird field" => "q1!2\"'w$5&7/z8)?"
- Rack::Utils.parse_query("foo[]").
+ Rack::Utils.parse_nested_query("foo[]").
should.equal "foo" => [nil]
- Rack::Utils.parse_query("foo[]=").
+ Rack::Utils.parse_nested_query("foo[]=").
should.equal "foo" => [""]
- Rack::Utils.parse_query("foo[]=bar").
+ Rack::Utils.parse_nested_query("foo[]=bar").
should.equal "foo" => ["bar"]
- Rack::Utils.parse_query("foo[]=1&foo[]=2").
+ Rack::Utils.parse_nested_query("foo[]=1&foo[]=2").
should.equal "foo" => ["1", "2"]
- Rack::Utils.parse_query("foo=bar&baz[]=1&baz[]=2&baz[]=3").
+ Rack::Utils.parse_nested_query("foo=bar&baz[]=1&baz[]=2&baz[]=3").
should.equal "foo" => "bar", "baz" => ["1", "2", "3"]
- Rack::Utils.parse_query("foo[]=bar&baz[]=1&baz[]=2&baz[]=3").
+ Rack::Utils.parse_nested_query("foo[]=bar&baz[]=1&baz[]=2&baz[]=3").
should.equal "foo" => ["bar"], "baz" => ["1", "2", "3"]
- Rack::Utils.parse_query("x[y][z]=1").
+ Rack::Utils.parse_nested_query("x[y][z]=1").
should.equal "x" => {"y" => {"z" => "1"}}
- Rack::Utils.parse_query("x[y][z][]=1").
+ Rack::Utils.parse_nested_query("x[y][z][]=1").
should.equal "x" => {"y" => {"z" => ["1"]}}
- Rack::Utils.parse_query("x[y][z]=1&x[y][z]=2").
- should.equal "x" => {"y" => {"z" => ["1", "2"]}}
- Rack::Utils.parse_query("x[y][z][]=1&x[y][z][]=2").
+ Rack::Utils.parse_nested_query("x[y][z]=1&x[y][z]=2").
+ should.equal "x" => {"y" => {"z" => "2"}}
+ Rack::Utils.parse_nested_query("x[y][z][]=1&x[y][z][]=2").
should.equal "x" => {"y" => {"z" => ["1", "2"]}}
- Rack::Utils.parse_query("x[y][][z]=1").
+ Rack::Utils.parse_nested_query("x[y][][z]=1").
should.equal "x" => {"y" => [{"z" => "1"}]}
- Rack::Utils.parse_query("x[y][][z][]=1").
+ Rack::Utils.parse_nested_query("x[y][][z][]=1").
should.equal "x" => {"y" => [{"z" => ["1"]}]}
- Rack::Utils.parse_query("x[y][][z]=1&x[y][][w]=2").
+ Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][w]=2").
should.equal "x" => {"y" => [{"z" => "1", "w" => "2"}]}
- Rack::Utils.parse_query("x[y][][v][w]=1").
+ Rack::Utils.parse_nested_query("x[y][][v][w]=1").
should.equal "x" => {"y" => [{"v" => {"w" => "1"}}]}
- Rack::Utils.parse_query("x[y][][z]=1&x[y][][v][w]=2").
+ Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][v][w]=2").
should.equal "x" => {"y" => [{"z" => "1", "v" => {"w" => "2"}}]}
- Rack::Utils.parse_query("x[y][][z]=1&x[y][][z]=2").
+ Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][z]=2").
should.equal "x" => {"y" => [{"z" => "1"}, {"z" => "2"}]}
- Rack::Utils.parse_query("x[y][][z]=1&x[y][][w]=a&x[y][][z]=2&x[y][][w]=3").
+ Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][w]=a&x[y][][z]=2&x[y][][w]=3").
should.equal "x" => {"y" => [{"z" => "1", "w" => "a"}, {"z" => "2", "w" => "3"}]}
- lambda { Rack::Utils.parse_query("foo[bar]=1&foo[]=1") }.
+ lambda { Rack::Utils.parse_nested_query("foo[bar]=1&foo[]=1") }.
should.raise TypeError
end

0 comments on commit 5c00dd6

Please sign in to comment.