Skip to content
This repository was archived by the owner on Jan 30, 2019. It is now read-only.
This repository was archived by the owner on Jan 30, 2019. It is now read-only.

Allow repeated keys in query params #13

@favila

Description

@favila

(This is a strawman proposal.)

Query parameters in uris allow keys to be repeated. It would be nice if this were supported as many services make use of this, e.g. default query param parsing in PHP and ring.middleware.params.

I propose that if the value in query map is a seq, repeat the key in the serialized uri for each value in the seq. Likewise on deserialization emit a vector of values for the key.

E.g.

(-> (url "http://example.org?a=foo&a=bar") (:query))
; => {"a" ["foo" "bar"]}
(str (-> (url "http://example.org") (assoc :a ["foo" "bar"]))
; => "http://example.org?a=foo&a=bar"

The problem with this is that the cardinality of query param values in parsed urls will depend on the query string.

Other approaches I've seen paper over this difference by using a custom type that pretends all keys have scalar values unless you do something special to ask for the other values for a key (e.g. many Python libraries use a "MultiDict" with a special .getall(k) method). This could be done in clojure with a custom type for query parameters that returns the last seen value for lookups, but has some extra protocol that returns a vector. (However if you go down this route you no longer have a simple library.)

Another possibility is to force the user to be explicit about which query params are cardinality-many. This could be done with different url functions, examples:

(-> (multi-query-url "http://example?a=foo&a=bar&b=baz") :query)
;=> {"a" ["foo" "bar"] "b" ["baz"]}
(-> (multi-query-url "http://example?a=foo&a=bar&b=baz" #{"a"}) :query)
;=> {"a" ["foo" "bar"] "b" "baz"}
(-> (multi-query-url "http://example?a=foo&a=bar&b=baz" (complement #{"a"})) :query)
;=> {"a" "bar" "b" ["baz"]}
;;;  (A subset of) PHP style:
(-> (multi-query-url "http://example?a[]=foo&a[]=bar&b=baz" #(.endsWith % "[]")) :query)
;=> {"a" ["foo" "bar"] "b" "baz"}

Thoughts?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions