@@ -50,6 +50,12 @@ def load_env_key(env, key)
50
50
# @private
51
51
POST_PARAM_METHODS = [ 'POST' , 'PUT' , 'DELETE' ] . freeze
52
52
53
+ if defined? Rack ::Utils ::ParameterTypeError
54
+ ParameterTypeError = Rack ::Utils ::ParameterTypeError
55
+ else
56
+ ParameterTypeError = TypeError
57
+ end
58
+
53
59
# Load parameters into the (Rack) env from the Servlet API.
54
60
# using javax.servlet.http.HttpServletRequest#getParameterMap
55
61
def load_parameters
@@ -65,7 +71,7 @@ def load_parameters
65
71
@servlet_env . getParameterMap . each do |key , val | # String, String[]
66
72
val = [ '' ] if val . nil? # e.g. buggy Jetty 6
67
73
val = [ '' ] if val . length == 1 && val [ 0 ] . nil?
68
-
74
+
69
75
if ( q_vals = query_values ( key ) ) || get_only
70
76
if q_vals . length != val . length
71
77
# some are GET params some POST params
@@ -93,6 +99,20 @@ def load_parameters
93
99
@env [ FORM_HASH ] = form_hash
94
100
end
95
101
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
+
96
116
# Store the parameter into the given Hash.
97
117
# By default this is performed in a Rack compatible way and thus
98
118
# some parameter values might get "lost" - it only accepts multiple
@@ -102,12 +122,33 @@ def load_parameters
102
122
# @param val the value(s) in a array-like structure
103
123
# @param hash the Hash to store the name, value pair
104
124
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 ]
109
129
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
111
152
end
112
153
end
113
154
@@ -149,6 +190,12 @@ def parse_query_string
149
190
Java ::JavaxServletHttp ::HttpUtils . parseQueryString ( query_string )
150
191
end
151
192
193
+ def mark_parameter_error ( msg )
194
+ raise ParameterTypeError , msg
195
+ rescue ParameterTypeError => e
196
+ @parameter_error = e
197
+ end
198
+
152
199
end
153
200
end
154
201
end
0 commit comments