mirror of
https://github.com/metosin/reitit.git
synced 2025-12-17 00:11:11 +00:00
Ensure extra query-string params aren't removed by coercion
This commit is contained in:
parent
5f10465533
commit
21e5840f13
4 changed files with 70 additions and 19 deletions
|
|
@ -178,6 +178,12 @@
|
||||||
(-response-coercer [_ schema]
|
(-response-coercer [_ schema]
|
||||||
(-coercer schema :response transformers :encode opts))
|
(-coercer schema :response transformers :encode opts))
|
||||||
(-query-string-coercer [_ schema]
|
(-query-string-coercer [_ schema]
|
||||||
(-coercer schema :string transformers :encode opts))))))
|
;; TODO: Create encoding function that only does encode, no decoding and validation?
|
||||||
|
(-coercer (mu/open-schema schema)
|
||||||
|
:string
|
||||||
|
;; Tune transformer to not strip extra keys
|
||||||
|
{:string {:default (-transformer string-transformer-provider (assoc opts :strip-extra-keys false))}}
|
||||||
|
:encode
|
||||||
|
opts))))))
|
||||||
|
|
||||||
(def coercion (create default-options))
|
(def coercion (create default-options))
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,13 @@
|
||||||
(is (= "/olipa/kerran?x=a&x=b"
|
(is (= "/olipa/kerran?x=a&x=b"
|
||||||
(-> router
|
(-> router
|
||||||
(r/match-by-name! ::route {:a "olipa", :b "kerran"})
|
(r/match-by-name! ::route {:a "olipa", :b "kerran"})
|
||||||
(r/match->path {:x [:a :b]}))))))
|
(r/match->path {:x [:a :b]}))))
|
||||||
|
|
||||||
|
(is (= "/olipa/kerran?x=a&x=b&extra=extra-param"
|
||||||
|
(-> router
|
||||||
|
(r/match-by-name! ::route {:a "olipa", :b "kerran"})
|
||||||
|
(r/match->path {:x [:a :b]
|
||||||
|
:extra "extra-param"}))))))
|
||||||
|
|
||||||
(testing "custom encode/string for a collection"
|
(testing "custom encode/string for a collection"
|
||||||
(let [router (r/router ["/:a/:b"
|
(let [router (r/router ["/:a/:b"
|
||||||
|
|
@ -183,6 +189,13 @@
|
||||||
(r/match-by-name! ::route {:a "olipa", :b "kerran"})
|
(r/match-by-name! ::route {:a "olipa", :b "kerran"})
|
||||||
(r/match->path {:x [:a :b]}))))
|
(r/match->path {:x [:a :b]}))))
|
||||||
|
|
||||||
|
(testing "extra query-string parameters aren't removed by coercion"
|
||||||
|
(is (= "/olipa/kerran?x=a%2Cb&extra=extra-param"
|
||||||
|
(-> router
|
||||||
|
(r/match-by-name! ::route {:a "olipa", :b "kerran"})
|
||||||
|
(r/match->path {:x [:a :b]
|
||||||
|
:extra "extra-param"})))))
|
||||||
|
|
||||||
(is (= {:query {:x [:a :b]}}
|
(is (= {:query {:x [:a :b]}}
|
||||||
(-> (r/match-by-path router "/olipa/kerran")
|
(-> (r/match-by-path router "/olipa/kerran")
|
||||||
(assoc :query-params {:x "a,b"})
|
(assoc :query-params {:x "a,b"})
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,30 @@
|
||||||
(ns reitit.frontend.easy-test
|
(ns reitit.frontend.easy-test
|
||||||
(:require [clojure.test :refer [deftest testing is are async]]
|
(:require [clojure.string :as str]
|
||||||
|
[clojure.test :refer [are async deftest is testing]]
|
||||||
|
[goog.events :as gevents]
|
||||||
|
[reitit.coercion.malli :as rcm]
|
||||||
[reitit.core :as r]
|
[reitit.core :as r]
|
||||||
[reitit.frontend.easy :as rfe]
|
[reitit.frontend.easy :as rfe]
|
||||||
[reitit.frontend.history :as rfh]
|
[reitit.frontend.history :as rfh]))
|
||||||
[goog.events :as gevents]))
|
|
||||||
|
|
||||||
(def browser (exists? js/window))
|
(def browser (exists? js/window))
|
||||||
|
|
||||||
(def router (r/router ["/"
|
(def router (r/router ["/"
|
||||||
["" ::frontpage]
|
["" ::frontpage]
|
||||||
["foo" ::foo]
|
["foo" ::foo]
|
||||||
["bar/:id" ::bar]]))
|
["bar/:id"
|
||||||
|
{:name ::bar
|
||||||
|
:coercion rcm/coercion
|
||||||
|
:parameters {:query [:map
|
||||||
|
[:q {:optional true}
|
||||||
|
[:keyword
|
||||||
|
{:decode/string (fn [s]
|
||||||
|
(if (string? s)
|
||||||
|
(keyword (if (str/starts-with? s "__")
|
||||||
|
(subs s 2)
|
||||||
|
s))
|
||||||
|
s))
|
||||||
|
:encode/string (fn [k] (str "__" (name k)))}]]]}}]]))
|
||||||
|
|
||||||
;; TODO: Only tests fragment history, also test HTML5?
|
;; TODO: Only tests fragment history, also test HTML5?
|
||||||
|
|
||||||
|
|
@ -38,10 +52,11 @@
|
||||||
;; 0. /
|
;; 0. /
|
||||||
3 (do (is (= "/" url)
|
3 (do (is (= "/" url)
|
||||||
"go back")
|
"go back")
|
||||||
(rfe/navigate ::bar {:path-params {:id 1}}))
|
(rfe/navigate ::bar {:path-params {:id 1}
|
||||||
|
:query-params {:q "x"}}))
|
||||||
;; 0. /
|
;; 0. /
|
||||||
;; 1. /bar/1
|
;; 1. /bar/1
|
||||||
4 (do (is (= "/bar/1" url)
|
4 (do (is (= "/bar/1?q=__x" url)
|
||||||
"push-state 2")
|
"push-state 2")
|
||||||
(rfe/replace-state ::bar {:id 2}))
|
(rfe/replace-state ::bar {:id 2}))
|
||||||
;; 0. /
|
;; 0. /
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,28 @@
|
||||||
[reitit.core :as r]
|
[reitit.core :as r]
|
||||||
[reitit.frontend.history :as rfh]
|
[reitit.frontend.history :as rfh]
|
||||||
[reitit.frontend.test-utils :refer [capture-console]]
|
[reitit.frontend.test-utils :refer [capture-console]]
|
||||||
[goog.events :as gevents]))
|
[goog.events :as gevents]
|
||||||
|
[reitit.coercion.malli :as rcm]
|
||||||
|
[clojure.string :as str]))
|
||||||
|
|
||||||
(def browser (exists? js/window))
|
(def browser (exists? js/window))
|
||||||
|
|
||||||
(def router (r/router ["/"
|
(def router (r/router ["/"
|
||||||
["" ::frontpage]
|
["" ::frontpage]
|
||||||
["foo" ::foo]
|
["foo" ::foo]
|
||||||
["bar/:id" ::bar]]))
|
["bar/:id"
|
||||||
|
{:name ::bar
|
||||||
|
:coercion rcm/coercion
|
||||||
|
:parameters {:query [:map
|
||||||
|
[:q {:optional true}
|
||||||
|
[:keyword
|
||||||
|
{:decode/string (fn [s]
|
||||||
|
(if (string? s)
|
||||||
|
(keyword (if (str/starts-with? s "__")
|
||||||
|
(subs s 2)
|
||||||
|
s))
|
||||||
|
s))
|
||||||
|
:encode/string (fn [k] (str "__" (name k)))}]]]}}]]))
|
||||||
|
|
||||||
(deftest fragment-history-test
|
(deftest fragment-history-test
|
||||||
(when browser
|
(when browser
|
||||||
|
|
@ -24,9 +38,12 @@
|
||||||
(rfh/href history ::foo)))
|
(rfh/href history ::foo)))
|
||||||
(is (= "#/bar/5"
|
(is (= "#/bar/5"
|
||||||
(rfh/href history ::bar {:id 5})))
|
(rfh/href history ::bar {:id 5})))
|
||||||
(is (= "#/bar/5?q=x"
|
(testing "query string coercion doesn't strip extra keys"
|
||||||
|
(is (= "#/bar/5?extra=a"
|
||||||
|
(rfh/href history ::bar {:id 5} {:extra "a"}))))
|
||||||
|
(is (= "#/bar/5?q=__x"
|
||||||
(rfh/href history ::bar {:id 5} {:q "x"})))
|
(rfh/href history ::bar {:id 5} {:q "x"})))
|
||||||
(is (= "#/bar/5?q=x#foo"
|
(is (= "#/bar/5?q=__x#foo"
|
||||||
(rfh/href history ::bar {:id 5} {:q "x"} "foo")))
|
(rfh/href history ::bar {:id 5} {:q "x"} "foo")))
|
||||||
(let [{:keys [value messages]} (capture-console
|
(let [{:keys [value messages]} (capture-console
|
||||||
(fn []
|
(fn []
|
||||||
|
|
@ -58,11 +75,11 @@
|
||||||
(.back js/window.history))
|
(.back js/window.history))
|
||||||
4 (do (is (= "/" url)
|
4 (do (is (= "/" url)
|
||||||
"go back")
|
"go back")
|
||||||
(rfh/push-state history ::bar {:id 1}))
|
(rfh/push-state history ::bar {:id 1} {:extra "a"}))
|
||||||
5 (do (is (= "/bar/1" url)
|
5 (do (is (= "/bar/1?extra=a" url)
|
||||||
"push-state 2")
|
"push-state 2")
|
||||||
(rfh/replace-state history ::bar {:id 2}))
|
(rfh/replace-state history ::bar {:id 2} {:q "x"}))
|
||||||
6 (do (is (= "/bar/2" url)
|
6 (do (is (= "/bar/2?q=__x" url)
|
||||||
"replace-state")
|
"replace-state")
|
||||||
(.back js/window.history))
|
(.back js/window.history))
|
||||||
7 (do (is (= "/" url)
|
7 (do (is (= "/" url)
|
||||||
|
|
@ -84,7 +101,7 @@
|
||||||
(rfh/href history ::foo)))
|
(rfh/href history ::foo)))
|
||||||
(is (= "/bar/5"
|
(is (= "/bar/5"
|
||||||
(rfh/href history ::bar {:id 5})))
|
(rfh/href history ::bar {:id 5})))
|
||||||
(is (= "/bar/5?q=x"
|
(is (= "/bar/5?q=__x"
|
||||||
(rfh/href history ::bar {:id 5} {:q "x"})))
|
(rfh/href history ::bar {:id 5} {:q "x"})))
|
||||||
(let [{:keys [value messages]} (capture-console
|
(let [{:keys [value messages]} (capture-console
|
||||||
(fn []
|
(fn []
|
||||||
|
|
@ -119,8 +136,8 @@
|
||||||
(rfh/push-state history ::bar {:id 1}))
|
(rfh/push-state history ::bar {:id 1}))
|
||||||
5 (do (is (= "/bar/1" url)
|
5 (do (is (= "/bar/1" url)
|
||||||
"push-state 2")
|
"push-state 2")
|
||||||
(rfh/replace-state history ::bar {:id 2}))
|
(rfh/replace-state history ::bar {:id 2} {:q "x"}))
|
||||||
6 (do (is (= "/bar/2" url)
|
6 (do (is (= "/bar/2?q=__x" url)
|
||||||
"replace-state")
|
"replace-state")
|
||||||
(.back js/window.history))
|
(.back js/window.history))
|
||||||
7 (do (is (= "/" url)
|
7 (do (is (= "/" url)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue