diff --git a/modules/reitit-core/src/reitit/impl.cljc b/modules/reitit-core/src/reitit/impl.cljc index 70c44fe8..3607d81b 100644 --- a/modules/reitit-core/src/reitit/impl.cljc +++ b/modules/reitit-core/src/reitit/impl.cljc @@ -15,6 +15,31 @@ [clojure.set :as set]) (:import #?(:clj (java.util.regex Pattern)))) +(defn wild? [s] + (contains? #{\: \*} (first (str s)))) + +(defn catch-all? [s] + (= \* (first (str s)))) + +(defn wild-param [s] + (let [ss (str s)] + (if (= \: (first ss)) + (keyword (subs ss 1))))) + +(defn catch-all-param [s] + (let [ss (str s)] + (if (= \* (first ss)) + (keyword ss)))) + +(defn wild-or-catch-all-param? [x] + (boolean (or (wild-param x) (catch-all-param x)))) + +(defn segments [^String path] + (into [] (.split path "/" 666))) + +(defn contains-wilds? [path] + (boolean (some wild-or-catch-all-param? (segments path)))) + ;; ;; https://github.com/pedestal/pedestal/blob/master/route/src/io/pedestal/http/route/path.clj ;; @@ -65,48 +90,6 @@ (when-let [m (re-matches path-re path)] (zipmap path-params (rest m)))))) -;; -;; (c) https://github.com/pedestal/pedestal/blob/master/route/src/io/pedestal/http/route/prefix_tree.clj -;; - -(defn wild? [s] - (contains? #{\: \*} (first s))) - -(defn wild-param? - "Return true if a string segment starts with a wildcard string." - [segment] - (= \: (first segment))) - -(defn catch-all-param? - "Return true if a string segment starts with a catch-all string." - [segment] - (= \* (first segment))) - -(defn partition-wilds - "Given a path-spec string, return a seq of strings with wildcards - and catch-alls separated into their own strings. Eats the forward - slash following a wildcard." - [path-spec] - (let [groups (partition-by wild? (str/split path-spec #"/")) - first-groups (butlast groups) - last-group (last groups)] - (flatten - (conj (mapv #(if (wild? (first %)) - % - (str (str/join "/" %) "/")) - first-groups) - (if (wild? (first last-group)) - last-group - (str/join "/" last-group)))))) - -(defn contains-wilds? - "Return true if the given path-spec contains any wildcard params or - catch-alls." - [path-spec] - (let [parts (partition-wilds path-spec)] - (or (> (count parts) 1) - (wild? (first parts))))) - ;; ;; Routing (c) Metosin ;; @@ -129,14 +112,6 @@ :path-params :params}) (map->Route $)))) -(defn segments [path] - (let [ss (-> (str/split path #"/") rest vec)] - (if (str/ends-with? path "/") - (conj ss "") ss))) - -(defn- catch-all? [segment] - (= \* (first segment))) - (defn wild-route? [[path]] (contains-wilds? path)) diff --git a/modules/reitit-core/src/reitit/trie.cljc b/modules/reitit-core/src/reitit/trie.cljc index a0a14776..6f2208d3 100644 --- a/modules/reitit-core/src/reitit/trie.cljc +++ b/modules/reitit-core/src/reitit/trie.cljc @@ -1,5 +1,6 @@ (ns reitit.trie - (:require [reitit.impl :as impl])) + (:require [reitit.impl :as impl] + [clojure.string :as str])) ;; ;; original https://github.com/pedestal/pedestal/blob/master/route/src/io/pedestal/http/route/prefix_tree.clj @@ -116,24 +117,41 @@ tree node." [segment data] (cond - (impl/wild-param? segment) + (impl/wild-param segment) (wild-node segment (keyword (subs segment 1)) nil data) - (impl/catch-all-param? segment) + (impl/catch-all-param segment) (catch-all-node segment (keyword (subs segment 1)) nil data) :else (static-node segment nil data))) +(defn partition-wilds + "Given a path-spec string, return a seq of strings with wildcards + and catch-alls separated into their own strings. Eats the forward + slash following a wildcard." + [path-spec] + (let [groups (partition-by impl/wild? (str/split path-spec #"/")) + first-groups (butlast groups) + last-group (last groups)] + (flatten + (conj (mapv #(if (impl/wild? (first %)) + % + (str (str/join "/" %) "/")) + first-groups) + (if (impl/wild? (first last-group)) + last-group + (str/join "/" last-group)))))) + (defn- new-node "Given a path-spec and a payload object, return a new tree node. If the path-spec contains wildcards or catch-alls, will return parent node of a tree (linked list)." [path-spec data] (if (impl/contains-wilds? path-spec) - (let [parts (impl/partition-wilds path-spec)] + (let [parts (partition-wilds path-spec)] (reduce (fn [child segment] - (when (impl/catch-all-param? segment) + (when (impl/catch-all-param segment) (throw (ex-info "catch-all may only appear at the end of a path spec" {:patch-spec path-spec}))) (-> (make-node segment nil) @@ -187,7 +205,7 @@ (set-data node data) ;; handle case where path-spec is a wildcard param - (impl/wild-param? path-spec) + (impl/wild-param path-spec) (let [lcs (calc-lcs segment path-spec) common (subs path-spec 0 lcs)] (if (= common segment) @@ -200,7 +218,7 @@ ;; in the case where path-spec is a catch-all, node should always be nil. ;; getting here means we have an invalid route specification - (impl/catch-all-param? path-spec) + (impl/catch-all-param path-spec) (throw (ex-info "route conflict" {:node node :path-spec path-spec