Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Fix for wrap-nested-params and multi-valued parameters without '[]' #23

Closed
wants to merge 2 commits into from

3 participants

@christophermaier

(sorry about the previous pull request... I missed a commit somehow)

I recently had to use a multiple select box on an HTML form, but didn't end the parameter name with "[]". wrap-params correctly transforms "foo=bar&foo=baz" into {"foo" ["bar" "baz"]}, but because the parameter was "foo" and not "foo[]", wrap-nested-params turned it into {"foo" "baz"}, eating all but the last value.

While this can be "fixed" by just calling the parameter "foo[]" from the beginning, it makes that a special case; you don't have to think about the brackets and whatnot when using the 'with-groups' macro in Hiccup, for instance (can't speak for other libraries like Enlive, though). In any event, wrap-nested-params was removing legitimate parameter values.

There is probably a better way to go about this; I just added another key to the middleware options map for a "multi-value-suffix" that defaults to "[]", in keeping with using the parse-nested-keys default parse function. Basically, if a multi-valued parameter is detected whose name doesn't end in the specified suffix, it gets added in the param-pairs function, making it appear "correct" to the rest of the machinery. It works, though.

Thanks,
Chris

christophermaier added some commits
@christophermaier christophermaier Add test showing failure of nested-params middleware on multi-valued …
…parameters that don't end in '[]', produced by e.g., multiple select elements.

For example, the query string "foo=bar&foo=baz".
f99a96b
@christophermaier christophermaier Add multi-value-suffix option to properly handle parameters that are …
…multi-valued, but don't end with "[]".
55b3204
@weavejester
Collaborator

As you say, there is probably a better solution for this than adding an additional option. I'll look into a fix for this.

@timewarrior

Hi
I am also facing this issue.
{"fooz" [{"baz" {"foo" "bar1"}} {"baz" {"foo" "bar2"}}]} is getting converted to {"fooz" {"baz" {"foo" "bar2"}}} losing the last value. For now I have disabled wrap-nested-params from my code. I would really appreciate if there was some fix for this.

Thanks
Anand

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 29, 2011
  1. @christophermaier

    Add test showing failure of nested-params middleware on multi-valued …

    christophermaier authored
    …parameters that don't end in '[]', produced by e.g., multiple select elements.
    
    For example, the query string "foo=bar&foo=baz".
  2. @christophermaier

    Add multi-value-suffix option to properly handle parameters that are …

    christophermaier authored
    …multi-valued, but don't end with "[]".
This page is out of date. Refresh to see the latest.
View
25 ring-core/src/ring/middleware/nested_params.clj
@@ -25,11 +25,18 @@
(defn- param-pairs
"Return a list of name-value pairs for a parameter map."
- [params]
+ [params multi-value-suffix]
(mapcat
(fn [[name value]]
(if (sequential? value)
- (for [v value] [name v])
+ ;; If the parameter is multi-valued, but does not end with the appropriate suffix
+ ;; ("[]" in the default 'parse-nested-keys' system), it will be appended here
+ ;; to allow the rest of the middleware functions to operate on it appropriately.
+ (let [name (if-not (.endsWith (str name) multi-value-suffix)
+ (str name multi-value-suffix)
+ name)]
+ (for [v value]
+ [name v]))
[[name value]]))
params))
@@ -37,12 +44,12 @@
"Takes a flat map of parameters and turns it into a nested map of
parameters, using the function parse to split the parameter names
into keys."
- [params parse]
+ [params parse multi-value-suffix]
(reduce
(fn [m [k v]]
(assoc-nested m (parse k) v))
{}
- (param-pairs params)))
+ (param-pairs params multi-value-suffix)))
(defn wrap-nested-params
"Middleware to converts a flat map of parameters into a nested map.
@@ -56,9 +63,15 @@
=> {\"foo\" {\"bar\" \"baz\"}}
{\"foo[]\" \"bar\"}
- => {\"foo\" [\"bar\"]}"
+ => {\"foo\" [\"bar\"]}
+
+ The string in the :multi-value-suffix option determines what a parameter with
+ multiple values should end in. If a multi-valued parameter is present, but does
+ not have this suffix, it is treated as though it does. Defaults to \"[]\",
+ corresponding to the parse-nested-keys function."
[handler & [opts]]
(fn [request]
(let [parse (:key-parser opts parse-nested-keys)
- request (update-in request [:params] nest-params parse)]
+ multi-value-suffix (:multi-value-suffix opts "[]")
+ request (update-in request [:params] nest-params parse multi-value-suffix)]
(handler request))))
View
5 ring-core/test/ring/middleware/nested_params_test.clj
@@ -15,4 +15,7 @@
{"foo[]" "bar"} {"foo" ["bar"]}
{"foo[]" ["bar" "baz"]} {"foo" ["bar" "baz"]}
{"a[x][]" ["b"], "a[x][][y]" "c"} {"a" {"x" ["b" {"y" "c"}]}}
- {"a[][x]" "c", "a[][y]" "d"} {"a" [{"x" "c"} {"y" "d"}]}))))
+ {"a[][x]" "c", "a[][y]" "d"} {"a" [{"x" "c"} {"y" "d"}]}))
+ (testing "properly handle multi-valued parameters that don't end with '[]' (created by e.g., multiple select elements)"
+ (are [p r] (= (handler {:params p}) r)
+ {"foo" ["bar" "baz"]} {"foo" ["bar" "baz"]}))))
Something went wrong with that request. Please try again.