Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 19 additions & 6 deletions ring-core/src/ring/middleware/nested_params.clj
Expand Up @@ -25,24 +25,31 @@

(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))

(defn- nest-params
"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.
Expand All @@ -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))))
5 changes: 4 additions & 1 deletion ring-core/test/ring/middleware/nested_params_test.clj
Expand Up @@ -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"]}))))