summary refs log tree commit
path: root/lib/rack/query_parser.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rack/query_parser.rb')
-rw-r--r--lib/rack/query_parser.rb39
1 files changed, 28 insertions, 11 deletions
diff --git a/lib/rack/query_parser.rb b/lib/rack/query_parser.rb
index 17b77128..fce1ce91 100644
--- a/lib/rack/query_parser.rb
+++ b/lib/rack/query_parser.rb
@@ -1,5 +1,11 @@
+# frozen_string_literal: true
+
+require_relative 'core_ext/regexp'
+
 module Rack
   class QueryParser
+    using ::Rack::RegexpExtensions
+
     DEFAULT_SEP = /[&;] */n
     COMMON_SEP = { ";" => /[;] */n, ";," => /[;,] */n, "&" => /[&] */n }
 
@@ -36,7 +42,7 @@ module Rack
 
       (qs || '').split(d ? (COMMON_SEP[d] || /[#{d}] */n) : DEFAULT_SEP).each do |p|
         next if p.empty?
-        k, v = p.split('='.freeze, 2).map!(&unescaper)
+        k, v = p.split('=', 2).map!(&unescaper)
 
         if cur = params[k]
           if cur.class == Array
@@ -61,8 +67,8 @@ module Rack
       return {} if qs.nil? || qs.empty?
       params = make_params
 
-      (qs || '').split(d ? (COMMON_SEP[d] || /[#{d}] */n) : DEFAULT_SEP).each do |p|
-        k, v = p.split('='.freeze, 2).map! { |s| unescape(s) }
+      qs.split(d ? (COMMON_SEP[d] || /[#{d}] */n) : DEFAULT_SEP).each do |p|
+        k, v = p.split('=', 2).map! { |s| unescape(s) }
 
         normalize_params(params, k, v, param_depth_limit)
       end
@@ -79,22 +85,22 @@ module Rack
       raise RangeError if depth <= 0
 
       name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
-      k = $1 || ''.freeze
-      after = $' || ''.freeze
+      k = $1 || ''
+      after = $' || ''
 
       if k.empty?
-        if !v.nil? && name == "[]".freeze
+        if !v.nil? && name == "[]"
           return Array(v)
         else
           return
         end
       end
 
-      if after == ''.freeze
+      if after == ''
         params[k] = v
-      elsif after == "[".freeze
+      elsif after == "["
         params[name] = v
-      elsif after == "[]".freeze
+      elsif after == "[]"
         params[k] ||= []
         raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
         params[k] << v
@@ -102,8 +108,7 @@ module Rack
         child_key = $1
         params[k] ||= []
         raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
-        first_key = child_key.gsub(/[\[\]]/, ' ').split.first
-        if params_hash_type?(params[k].last) && !params[k].last.key?(first_key)
+        if params_hash_type?(params[k].last) && !params_hash_has_key?(params[k].last, child_key)
           normalize_params(params[k].last, child_key, v, depth - 1)
         else
           params[k] << normalize_params(make_params, child_key, v, depth - 1)
@@ -135,6 +140,18 @@ module Rack
       obj.kind_of?(@params_class)
     end
 
+    def params_hash_has_key?(hash, key)
+      return false if /\[\]/.match?(key)
+
+      key.split(/[\[\]]+/).inject(hash) do |h, part|
+        next h if part == ''
+        return false unless params_hash_type?(h) && h.key?(part)
+        h[part]
+      end
+
+      true
+    end
+
     def unescape(s)
       Utils.unescape(s)
     end