@@ -50,6 +50,12 @@ def load_env_key(env, key)
5050 # @private
5151 POST_PARAM_METHODS = [ 'POST' , 'PUT' , 'DELETE' ] . freeze
5252
53+ if defined? Rack ::Utils ::ParameterTypeError
54+ ParameterTypeError = Rack ::Utils ::ParameterTypeError
55+ else
56+ ParameterTypeError = TypeError
57+ end
58+
5359 # Load parameters into the (Rack) env from the Servlet API.
5460 # using javax.servlet.http.HttpServletRequest#getParameterMap
5561 def load_parameters
@@ -65,7 +71,7 @@ def load_parameters
6571 @servlet_env . getParameterMap . each do |key , val | # String, String[]
6672 val = [ '' ] if val . nil? # e.g. buggy Jetty 6
6773 val = [ '' ] if val . length == 1 && val [ 0 ] . nil?
68-
74+
6975 if ( q_vals = query_values ( key ) ) || get_only
7076 if q_vals . length != val . length
7177 # some are GET params some POST params
@@ -93,6 +99,20 @@ def load_parameters
9399 @env [ FORM_HASH ] = form_hash
94100 end
95101
102+ def []( key )
103+ value = super ( key )
104+ if key . eql? QUERY_HASH
105+ if @parameter_error ||= nil
106+ raise @parameter_error
107+ end
108+ end
109+ value
110+ end
111+ public :[]
112+
113+ # @private
114+ KEY_SEP = /([^\[ \] ]*)(?:\[ (.*?)\] )?/
115+
96116 # Store the parameter into the given Hash.
97117 # By default this is performed in a Rack compatible way and thus
98118 # some parameter values might get "lost" - it only accepts multiple
@@ -102,12 +122,33 @@ def load_parameters
102122 # @param val the value(s) in a array-like structure
103123 # @param hash the Hash to store the name, value pair
104124 def store_parameter ( key , val , hash )
105- # Rack::Utils.parse_nested_query behaviour
106- # for 'foo=bad&foo=bar' does { 'foo' => 'bar' }
107- if key [ - 2 , 2 ] == '[]' # foo[]=f1&foo[]=f2
108- hash [ key [ 0 ...- 2 ] ] = val . to_a # String[ ]
125+ # emulating Rack::Utils.parse_nested_query behavior
126+
127+ if match = key . match ( KEY_SEP )
128+ n_key = match [ 1 ] ; sub = match [ 2 ]
109129 else
110- hash [ key ] = val [ val . length - 1 ] # last
130+ n_key = key ; sub = nil # normalized-key[ sub-key ]
131+ end
132+
133+ if sub
134+ if sub . empty? # e.g. foo[]=1&foo[]=2
135+ if arr = hash [ n_key ]
136+ return mark_parameter_error "expected Array (got #{ arr . class } ) for param `#{ n_key } '" unless arr . is_a? ( Array )
137+ hash [ n_key ] = arr + val . to_a ; return
138+ end
139+ hash [ n_key ] = val . to_a # String[]
140+ else # foo[bar]=rrr&foo[baz]=zzz
141+ v = val [ val . length - 1 ] # last
142+ if hsh = hash [ n_key ]
143+ return mark_parameter_error "expected Hash (got #{ hsh . class } ) for param `#{ n_key } '" unless hsh . is_a? ( Hash )
144+ hsh [ sub ] = v
145+ else
146+ hash [ n_key ] = { sub => v }
147+ end
148+ end
149+ else
150+ # for 'foo=bad&foo=bar' does { 'foo' => 'bar' }
151+ hash [ n_key ] = val [ val . length - 1 ] # last
111152 end
112153 end
113154
@@ -149,6 +190,12 @@ def parse_query_string
149190 Java ::JavaxServletHttp ::HttpUtils . parseQueryString ( query_string )
150191 end
151192
193+ def mark_parameter_error ( msg )
194+ raise ParameterTypeError , msg
195+ rescue ParameterTypeError => e
196+ @parameter_error = e
197+ end
198+
152199 end
153200 end
154201 end
0 commit comments