ring-clojure / ring

Clojure HTTP server abstraction
MIT License
3.77k stars 520 forks source link

Weak abstraction for form encoding/decoding #316

Closed cch1 closed 6 years ago

cch1 commented 6 years ago

This is unfortunate:

(form-decode (form-encode {:a ["A" "B"]})) => {"a" ["A" "B"]}

but

(form-decode (form-encode {:a ["B"]})) => {"a" "B"}

It's particularly unfortunate since ring's own middleware can handle the singleton collection just fine:

((wrap-params (wrap-nested-params identity)) {:query-string "a[]=b"}) => {:query-string "a[]=b", :form-params {}, :params {"a" ["b"]}, :query-params {"a[]" "b"}}

One unobtrusive "solution" would be to include a helper function to rename collection parameters to the standard supported by wrap-nested-params.

weavejester commented 6 years ago

Why is it unfortunate? The conversion is inherently lossy. Both {"a" "B"} and {"a" ["B"]} translate to a=B.

cch1 commented 6 years ago

It's unfortunate because there are encoding conventions that are not lossy, such as {"a" ["B"]} encoding to a[]=B or a[0]=B. Some frameworks (e.g. Rails, PHP) support one or the other of these conventions. And clj-http library implements both approaches, so they do have some general acceptance. The interactions between wrap-nested-params and wrap-params make it a bit dicey for me to attempt a PR, but if you have a preferred approach and guidelines, I could try one.

weavejester commented 6 years ago

Those conventions are additional syntax on top of form encoding. I'm not opposed to adding something like a encode-nested-params and decode-nested-paramsfunction to ring.middleware.nested-params.