From 9bff9db2d401051ce224bbb0007de490da732593 Mon Sep 17 00:00:00 2001 From: Martin Klepsch Date: Mon, 12 Feb 2024 12:30:54 +0200 Subject: [PATCH] attempt adding parsing of query params to match-by-path in reitit.core --- modules/reitit-core/src/reitit/core.cljc | 2 ++ modules/reitit-core/src/reitit/impl.cljc | 30 +++++++++++++++++++ .../reitit-frontend/src/reitit/frontend.cljs | 1 + test/cljc/reitit/core_test.cljc | 6 ++++ 4 files changed, 39 insertions(+) diff --git a/modules/reitit-core/src/reitit/core.cljc b/modules/reitit-core/src/reitit/core.cljc index 96264581..bdc56710 100644 --- a/modules/reitit-core/src/reitit/core.cljc +++ b/modules/reitit-core/src/reitit/core.cljc @@ -112,6 +112,7 @@ (if-let [match (match-by-path path)] (-> (:data match) (assoc :path-params (:params match)) + (assoc :query-params (impl/query-params path)) (assoc :path path)))) (match-by-name [_ name] (if-let [match (impl/fast-get lookup name)] @@ -198,6 +199,7 @@ (if-let [match (and match-by-path (match-by-path path))] (-> (:data match) (assoc :path-params (:params match)) + (assoc :query-params (impl/query-params path)) (assoc :path path)))) (match-by-name [_ name] (if-let [match (impl/fast-get lookup name)] diff --git a/modules/reitit-core/src/reitit/impl.cljc b/modules/reitit-core/src/reitit/impl.cljc index 9afd570a..aaa838e6 100644 --- a/modules/reitit-core/src/reitit/impl.cljc +++ b/modules/reitit-core/src/reitit/impl.cljc @@ -286,6 +286,36 @@ [params] (maybe-map-values #(url-encode (into-string %)) params)) +;; NOTE something like lambdaisland/url could help streamline this +(do + #?@(:clj [(defn query-params [url] + ;; this impl is straight from chatgpt and probably not right + (let [url-parts (clojure.string/split url #"\?") + query (second url-parts) + params (and query (clojure.string/split query #"&"))] + (reduce (fn [acc param] + (let [[key value] (clojure.string/split param #"=" 2) + decoded-key (URLDecoder/decode key "UTF-8") + decoded-value (URLDecoder/decode (or value "") "UTF-8")] + (assoc acc decoded-key decoded-value))) + {} + params)))] + + :cljs [(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 + "Given goog.Uri, read query parameters into a Clojure map." + [^goog.Uri uri] + (let [q (.getQueryData uri)] + (->> q + (.getKeys) + (map (juxt keyword #(query-param q %))) + (into {}))))])) + (defn- query-parameter [k v] (str (form-encode (into-string k)) "=" diff --git a/modules/reitit-frontend/src/reitit/frontend.cljs b/modules/reitit-frontend/src/reitit/frontend.cljs index ba122802..a44106e5 100644 --- a/modules/reitit-frontend/src/reitit/frontend.cljs +++ b/modules/reitit-frontend/src/reitit/frontend.cljs @@ -63,6 +63,7 @@ (throw e)))) coercion/coerce!)] (if-let [match (r/match-by-path router (.getPath uri))] + ;; query-params already part of match here (TODO ensure getPath includes query) (let [q (query-params uri) fragment (when (.hasFragment uri) (.getFragment uri)) diff --git a/test/cljc/reitit/core_test.cljc b/test/cljc/reitit/core_test.cljc index ab93cce6..26a946f2 100644 --- a/test/cljc/reitit/core_test.cljc +++ b/test/cljc/reitit/core_test.cljc @@ -435,3 +435,9 @@ (deftest routing-bug-test-538 (let [router (r/router [["/:a"] ["/:b"]] {:conflicts nil})] (is (nil? (r/match-by-path router ""))))) + +(deftest query-string-support + (let [router (r/router [["/endpoint"]]) + match (r/match-by-path router "/endpoint?foo=bar&foo=baz&some=123")] + (is (= ["bar" "baz"] (:foo (:query-params match)))) + (is (= ["123"] (:some (:query-params match))))))