diff --git a/modules/reitit-core/src/reitit/exception.cljc b/modules/reitit-core/src/reitit/exception.cljc new file mode 100644 index 00000000..52470c0c --- /dev/null +++ b/modules/reitit-core/src/reitit/exception.cljc @@ -0,0 +1,7 @@ +(ns reitit.exception) + +(defn fail! + ([message] + (throw (ex-info message {:type ::exeption}))) + ([message data] + (throw (ex-info message (assoc data :type ::exeption))))) diff --git a/modules/reitit-core/src/reitit/trie.cljc b/modules/reitit-core/src/reitit/trie.cljc index 78b4ca49..23228689 100644 --- a/modules/reitit-core/src/reitit/trie.cljc +++ b/modules/reitit-core/src/reitit/trie.cljc @@ -1,6 +1,7 @@ (ns reitit.trie (:refer-clojure :exclude [compile]) - (:require [clojure.string :as str]) + (:require [clojure.string :as str] + [reitit.exception :as ex]) #?(:clj (:import [reitit Trie Trie$Match Trie$Matcher] (java.net URLDecoder)))) @@ -49,7 +50,7 @@ (if (= to (count s)) (concat ss (-static from to)) (case (get s to) - \{ (let [to' (or (str/index-of s "}" to) (throw (ex-info (str "Unbalanced brackets: " (pr-str s)) {})))] + \{ (let [to' (or (str/index-of s "}" to) (ex/fail! (str "Unclosed brackets: " (pr-str s))))] (if (= \* (get s (inc to))) (recur (concat ss (-static from to) (-catch-all (inc to) to')) (inc to') (inc to')) (recur (concat ss (-static from to) (-wild to to')) (inc to') (inc to')))) @@ -131,7 +132,7 @@ (instance? Wild path) (let [next (first ps)] (if (or (instance? Wild next) (instance? CatchAll next)) - (throw (ex-info (str "Two following wilds: " path ", " next) {})) + (ex/fail! (str "Two following wilds: " path ", " next)) (update-in node [:wilds path] (fn [n] (-insert (or n (-node {})) ps data))))) (instance? CatchAll path) @@ -169,11 +170,12 @@ #?(:cljs (defn decode [path start end percent?] - (if percent? (js/decodeURIComponent (subs path start end)) path))) + (let [param (subs path start end)] + (if percent? (js/decodeURIComponent param) param)))) (defn data-matcher [data] #?(:clj (Trie/dataMatcher data) - :cljs (let [match (->Match data nil)] + :cljs (let [match (->Match data {})] (reify Matcher (match [_ i max _] (if (= i max) @@ -264,10 +266,8 @@ (for [[p c] wilds] (let [p (:value p) ends (ends c)] - (if (seq (rest ends)) - (throw - (ex-info - (str "Trie compliation error: wild " p " has two terminators: " ends) {})) + (if (next ends) + (ex/fail! (str "Trie compliation error: wild " p " has two terminators: " ends)) (wild-matcher p (ffirst ends) (compile c)))))) (into (for [[p c] catch-all] (catch-all-matcher (:value p) (:data c)))))] (cond @@ -283,10 +283,7 @@ #?(:clj (if-let [match ^Trie$Match (Trie/lookup ^Trie$Matcher matcher ^String path)] (->Match (.data match) (.params match))) :cljs (if-let [match (match matcher 0 (count path) path)] - (let [params (if-let [path-params (:path-params match)] - (persistent! path-params) - {})] - (assoc match :path-params params))))) + (->Match (:data match) (:path-params match))))) ;; ;; spike diff --git a/test/cljc/reitit/core_test.cljc b/test/cljc/reitit/core_test.cljc index 96a48277..4c80611e 100644 --- a/test/cljc/reitit/core_test.cljc +++ b/test/cljc/reitit/core_test.cljc @@ -101,7 +101,8 @@ ["/{a/jabba}/{a.b/dabba}/{a.b.c/doo}/{a.b.c.d/daa}/{*foo/bar}" ::wild] ["/files/file-{name}.html" ::html] ["/files/file-{name}.json" ::json] - ["/{eskon}/{saum}/pium\u2215paum" ::loru]] + ["/{eskon}/{saum}/pium\u2215paum" ::loru] + ["/extra-end}s-are/ok" ::bracket]] {:router r}) by-path #(-> router (r/match-by-path %) ((juxt (comp :name :data) :path-params)))] (is (= [::abba {:abba "abba"}] (by-path "/abba"))) @@ -119,13 +120,14 @@ (by-path "/olipa/kerran/avaruus/vaan/ei/toista/kertaa"))) (is (= [::html {:name "10"}] (by-path "/files/file-10.html"))) (is (= [::loru {:eskon "viitan", :saum "aa"}] (by-path "/viitan/aa/pium\u2215paum"))) - (is (= [nil nil] (by-path "/ei/osu/pium/paum"))))) + (is (= [nil nil] (by-path "/ei/osu/pium/paum"))) + (is (= [::bracket {}] (by-path "/extra-end}s-are/ok"))))) (testing "invalid syntax fails fast" - (testing "unbalanced brackets" + (testing "unclosed brackets" (is (thrown-with-msg? ExceptionInfo - #"^Unbalanced brackets" + #"^Unclosed brackets" (r/router ["/kikka/{kukka"])))) (testing "multiple terminators" (is (thrown-with-msg?