Merge pull request #332 from nilern/frontend-multi-query-params

Frontend: Multi-valued query params
This commit is contained in:
Tommi Reiman 2019-12-02 17:07:12 +02:00 committed by GitHub
commit 0faf2af876
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 13 deletions

View file

@ -17,6 +17,11 @@ We use [Break Versioning][breakver]. The version numbers follow a `<major>.<mino
### `reitit-core` ### `reitit-core`
* Added ability to mark individual routes as conflicting by using `:conflicting` route data. See [documentation](https://metosin.github.io/reitit/basics/route_conflicts.html). Fixes [#324](https://github.com/metosin/reitit/issues/324) * Added ability to mark individual routes as conflicting by using `:conflicting` route data. See [documentation](https://metosin.github.io/reitit/basics/route_conflicts.html). Fixes [#324](https://github.com/metosin/reitit/issues/324)
* Encode sequential and set values as multi-valued query params (e.g. `{:foo ["bar", "baz"]}` => foo=bar&foo=baz).
### `reitit-frontend`
* Decode multi-valued query params correctly into seqs (e.g. foo=bar&foo=baz => `{:foo ["bar", "baz"]}`).
## 0.3.10 (2019-10-8) ## 0.3.10 (2019-10-8)

View file

@ -239,14 +239,19 @@
[params] [params]
(maybe-map-values #(url-encode (into-string %)) params)) (maybe-map-values #(url-encode (into-string %)) params))
(defn- query-parameter [k v]
(str (form-encode (into-string k))
"="
(form-encode (into-string v))))
(defn query-string (defn query-string
"shallow transform of query parameters into query string" "shallow transform of query parameters into query string"
[params] [params]
(->> params (->> params
(map (fn [[k v]] (map (fn [[k v]]
(str (form-encode (into-string k)) (if (or (sequential? v) (set? v))
"=" (str/join "&" (map query-parameter (repeat k) v))
(form-encode (into-string v))))) (query-parameter k v))))
(str/join "&"))) (str/join "&")))
(defmacro goog-extend [type base-type ctor & methods] (defmacro goog-extend [type base-type ctor & methods]

View file

@ -3,7 +3,14 @@
[reitit.coercion :as coercion] [reitit.coercion :as coercion]
[reitit.coercion :as rc] [reitit.coercion :as rc]
[reitit.core :as r]) [reitit.core :as r])
(:import goog.Uri)) (:import goog.Uri
goog.Uri.QueryData))
(defn- query-param [^goog.Uri.QueryData q k]
(let [vs (.getValues q k)]
(if (< (alength vs) 2)
(aget vs 0)
(vec vs))))
(defn query-params (defn query-params
"Given goog.Uri, read query parameters into Clojure map." "Given goog.Uri, read query parameters into Clojure map."
@ -11,7 +18,7 @@
(let [q (.getQueryData uri)] (let [q (.getQueryData uri)]
(->> q (->> q
(.getKeys) (.getKeys)
(map (juxt keyword #(.get q %))) (map (juxt keyword #(query-param q %)))
(into {})))) (into {}))))
(defn match-by-path (defn match-by-path

View file

@ -51,13 +51,11 @@
{:a 1} "a=1" {:a 1} "a=1"
{:a nil} "a=" {:a nil} "a="
{:a :b :c "d"} "a=b&c=d" {:a :b :c "d"} "a=b&c=d"
{:a "b c"} "a=b+c")) {:a "b c"} "a=b+c"
{:a ["b" "c"]} "a=b&a=c"
; TODO: support seq values? {:a ["c" "b"]} "a=c&a=b"
;{:a ["b" "c"]} "a=b&a=c" {:a (seq [1 2])} "a=1&a=2"
;{:a ["c" "b"]} "a=c&a=b" {:a #{"c" "b"}} "a=b&a=c"))
;{:a (seq [1 2])} "a=1&a=2"
;{:a #{"c" "b"}} "a=b&a=c"
;; test from https://github.com/playframework/playframework -> UriEncodingSpec.scala ;; test from https://github.com/playframework/playframework -> UriEncodingSpec.scala

View file

@ -39,6 +39,16 @@
:path {}}}) :path {}}})
(rf/match-by-path router "/foo"))) (rf/match-by-path router "/foo")))
(is (= (r/map->Match
{:template "/foo"
:data {:name ::foo}
:path-params {}
:query-params {:mode ["foo", "bar"]}
:path "/foo"
:parameters {:query {:mode ["foo", "bar"]}
:path {}}})
(rf/match-by-path router "/foo?mode=foo&mode=bar")))
(is (= "/foo" (is (= "/foo"
(r/match->path (rf/match-by-name router ::foo)))) (r/match->path (rf/match-by-name router ::foo))))