r/routes & r/compiled-routes

This commit is contained in:
Tommi Reiman 2018-07-18 12:17:16 +03:00
parent 1291ae0bcc
commit d6d2ee478c
6 changed files with 66 additions and 46 deletions

View file

@ -4,6 +4,7 @@
* **BREAKING**: the router option key to extract body format has been renamed: `:extract-request-format` => `:reitit.coercion/extract-request-format` * **BREAKING**: the router option key to extract body format has been renamed: `:extract-request-format` => `:reitit.coercion/extract-request-format`
* should only concern you if you are not using [Muuntaja](https://github.com/metosin/muuntaja). * should only concern you if you are not using [Muuntaja](https://github.com/metosin/muuntaja).
* the `r/routes` returns just the path + data tuples as documented, not the compiled route results. To get the compiled results, use `r/compiled-routes` instead.
## `reitit-swagger-ui` ## `reitit-swagger-ui`

View file

@ -99,12 +99,16 @@
(defn- compile-routes [routes opts] (defn- compile-routes [routes opts]
(into [] (keep #(compile-route % opts) routes))) (into [] (keep #(compile-route % opts) routes)))
(defn- uncompile-routes [routes]
(mapv (comp vec (partial take 2)) routes))
(defn route-info [route] (defn route-info [route]
(select-keys (impl/create route) [:path :path-parts :path-params :result :data])) (select-keys (impl/create route) [:path :path-parts :path-params :result :data]))
(defprotocol Router (defprotocol Router
(router-name [this]) (router-name [this])
(routes [this]) (routes [this])
(compiled-routes [this])
(options [this]) (options [this])
(route-names [this]) (route-names [this])
(match-by-path [this path]) (match-by-path [this path])
@ -145,10 +149,10 @@
(defn linear-router (defn linear-router
"Creates a linear-router from resolved routes and optional "Creates a linear-router from resolved routes and optional
expanded options. See [[router]] for available options" expanded options. See [[router]] for available options"
([routes] ([compiled-routes]
(linear-router routes {})) (linear-router compiled-routes {}))
([routes opts] ([compiled-routes opts]
(let [names (find-names routes opts) (let [names (find-names compiled-routes opts)
[pl nl] (reduce [pl nl] (reduce
(fn [[pl nl] [p {:keys [name] :as data} result]] (fn [[pl nl] [p {:keys [name] :as data} result]]
(let [{:keys [path-params] :as route} (impl/create [p data result]) (let [{:keys [path-params] :as route} (impl/create [p data result])
@ -157,8 +161,9 @@
(->PartialMatch p data result % path-params))] (->PartialMatch p data result % path-params))]
[(conj pl route) [(conj pl route)
(if name (assoc nl name f) nl)])) (if name (assoc nl name f) nl)]))
[[] {}] routes) [[] {}] compiled-routes)
lookup (impl/fast-map nl)] lookup (impl/fast-map nl)
routes (uncompile-routes compiled-routes)]
^{:type ::router} ^{:type ::router}
(reify (reify
Router Router
@ -166,6 +171,8 @@
:linear-router) :linear-router)
(routes [_] (routes [_]
routes) routes)
(compiled-routes [_]
compiled-routes)
(options [_] (options [_]
opts) opts)
(route-names [_] (route-names [_]
@ -186,30 +193,33 @@
(defn lookup-router (defn lookup-router
"Creates a lookup-router from resolved routes and optional "Creates a lookup-router from resolved routes and optional
expanded options. See [[router]] for available options" expanded options. See [[router]] for available options"
([routes] ([compiled-routes]
(lookup-router routes {})) (lookup-router compiled-routes {}))
([routes opts] ([compiled-routes opts]
(when-let [wilds (seq (filter impl/wild-route? routes))] (when-let [wilds (seq (filter impl/wild-route? compiled-routes))]
(throw (throw
(ex-info (ex-info
(str "can't create :lookup-router with wildcard routes: " wilds) (str "can't create :lookup-router with wildcard routes: " wilds)
{:wilds wilds {:wilds wilds
:routes routes}))) :routes compiled-routes})))
(let [names (find-names routes opts) (let [names (find-names compiled-routes opts)
[pl nl] (reduce [pl nl] (reduce
(fn [[pl nl] [p {:keys [name] :as data} result]] (fn [[pl nl] [p {:keys [name] :as data} result]]
[(assoc pl p (->Match p data result {} p)) [(assoc pl p (->Match p data result {} p))
(if name (if name
(assoc nl name #(->Match p data result % p)) (assoc nl name #(->Match p data result % p))
nl)]) [{} {}] routes) nl)]) [{} {}] compiled-routes)
data (impl/fast-map pl) data (impl/fast-map pl)
lookup (impl/fast-map nl)] lookup (impl/fast-map nl)
routes (uncompile-routes compiled-routes)]
^{:type ::router} ^{:type ::router}
(reify Router (reify Router
(router-name [_] (router-name [_]
:lookup-router) :lookup-router)
(routes [_] (routes [_]
routes) routes)
(compiled-routes [_]
compiled-routes)
(options [_] (options [_]
opts) opts)
(route-names [_] (route-names [_]
@ -226,10 +236,10 @@
(defn segment-router (defn segment-router
"Creates a special prefix-tree style segment router from resolved routes and optional "Creates a special prefix-tree style segment router from resolved routes and optional
expanded options. See [[router]] for available options" expanded options. See [[router]] for available options"
([routes] ([compiled-routes]
(segment-router routes {})) (segment-router compiled-routes {}))
([routes opts] ([compiled-routes opts]
(let [names (find-names routes opts) (let [names (find-names compiled-routes opts)
[pl nl] (reduce [pl nl] (reduce
(fn [[pl nl] [p {:keys [name] :as data} result]] (fn [[pl nl] [p {:keys [name] :as data} result]]
(let [{:keys [path-params] :as route} (impl/create [p data result]) (let [{:keys [path-params] :as route} (impl/create [p data result])
@ -238,8 +248,9 @@
(->PartialMatch p data result % path-params))] (->PartialMatch p data result % path-params))]
[(segment/insert pl p (->Match p data result nil nil)) [(segment/insert pl p (->Match p data result nil nil))
(if name (assoc nl name f) nl)])) (if name (assoc nl name f) nl)]))
[nil {}] routes) [nil {}] compiled-routes)
lookup (impl/fast-map nl)] lookup (impl/fast-map nl)
routes (uncompile-routes compiled-routes)]
^{:type ::router} ^{:type ::router}
(reify (reify
Router Router
@ -247,6 +258,8 @@
:segment-router) :segment-router)
(routes [_] (routes [_]
routes) routes)
(compiled-routes [_]
compiled-routes)
(options [_] (options [_]
opts) opts)
(route-names [_] (route-names [_]
@ -266,24 +279,27 @@
(defn single-static-path-router (defn single-static-path-router
"Creates a fast router of 1 static route(s) and optional "Creates a fast router of 1 static route(s) and optional
expanded options. See [[router]] for available options" expanded options. See [[router]] for available options"
([routes] ([compiled-routes]
(single-static-path-router routes {})) (single-static-path-router compiled-routes {}))
([routes opts] ([compiled-routes opts]
(when (or (not= (count routes) 1) (some impl/wild-route? routes)) (when (or (not= (count compiled-routes) 1) (some impl/wild-route? compiled-routes))
(throw (throw
(ex-info (ex-info
(str ":single-static-path-router requires exactly 1 static route: " routes) (str ":single-static-path-router requires exactly 1 static route: " compiled-routes)
{:routes routes}))) {:routes compiled-routes})))
(let [[n :as names] (find-names routes opts) (let [[n :as names] (find-names compiled-routes opts)
[[p data result] :as compiled] routes [[p data result] :as compiled] compiled-routes
p #?(:clj (.intern ^String p) :cljs p) p #?(:clj (.intern ^String p) :cljs p)
match (->Match p data result {} p)] match (->Match p data result {} p)
routes (uncompile-routes compiled-routes)]
^{:type ::router} ^{:type ::router}
(reify Router (reify Router
(router-name [_] (router-name [_]
:single-static-path-router) :single-static-path-router)
(routes [_] (routes [_]
routes) routes)
(compiled-routes [_]
compiled-routes)
(options [_] (options [_]
opts) opts)
(route-names [_] (route-names [_]
@ -303,20 +319,23 @@
static routes and [[segment-router]] for wildcard routes. All static routes and [[segment-router]] for wildcard routes. All
routes should be non-conflicting. Takes resolved routes and optional routes should be non-conflicting. Takes resolved routes and optional
expanded options. See [[router]] for options." expanded options. See [[router]] for options."
([routes] ([compiled-routes]
(mixed-router routes {})) (mixed-router compiled-routes {}))
([routes opts] ([compiled-routes opts]
(let [{wild true, lookup false} (group-by impl/wild-route? routes) (let [{wild true, lookup false} (group-by impl/wild-route? compiled-routes)
->static-router (if (= 1 (count lookup)) single-static-path-router lookup-router) ->static-router (if (= 1 (count lookup)) single-static-path-router lookup-router)
wildcard-router (segment-router wild opts) wildcard-router (segment-router wild opts)
static-router (->static-router lookup opts) static-router (->static-router lookup opts)
names (find-names routes opts)] names (find-names compiled-routes opts)
routes (uncompile-routes compiled-routes)]
^{:type ::router} ^{:type ::router}
(reify Router (reify Router
(router-name [_] (router-name [_]
:mixed-router) :mixed-router)
(routes [_] (routes [_]
routes) routes)
(compiled-routes [_]
compiled-routes)
(options [_] (options [_]
opts) opts)
(route-names [_] (route-names [_]
@ -354,21 +373,21 @@
(let [{:keys [router] :as opts} (meta-merge default-router-options opts) (let [{:keys [router] :as opts} (meta-merge default-router-options opts)
routes (resolve-routes raw-routes opts) routes (resolve-routes raw-routes opts)
conflicting (conflicting-routes routes) conflicting (conflicting-routes routes)
routes (compile-routes routes opts) compiled-routes (compile-routes routes opts)
wilds? (boolean (some impl/wild-route? routes)) wilds? (boolean (some impl/wild-route? compiled-routes))
all-wilds? (every? impl/wild-route? routes) all-wilds? (every? impl/wild-route? compiled-routes)
router (cond router (cond
router router router router
(and (= 1 (count routes)) (not wilds?)) single-static-path-router (and (= 1 (count compiled-routes)) (not wilds?)) single-static-path-router
conflicting linear-router conflicting linear-router
(not wilds?) lookup-router (not wilds?) lookup-router
all-wilds? segment-router all-wilds? segment-router
:else mixed-router)] :else mixed-router)]
(when-let [validate (:validate opts)] (when-let [validate (:validate opts)]
(validate routes opts)) (validate compiled-routes opts))
(when-let [conflicts (:conflicts opts)] (when-let [conflicts (:conflicts opts)]
(when conflicting (conflicts conflicting))) (when conflicting (conflicts conflicting)))
(router routes opts)))) (router compiled-routes opts))))

View file

@ -93,6 +93,6 @@
(if-let [endpoint (some->> c (keep transform-endpoint) (seq) (into {}))] (if-let [endpoint (some->> c (keep transform-endpoint) (seq) (into {}))]
[(path->template p) endpoint]))] [(path->template p) endpoint]))]
(if id (if id
(let [paths (->> router (r/routes) (filter accept-route) (map transform-path) (into {}))] (let [paths (->> router (r/compiled-routes) (filter accept-route) (map transform-path) (into {}))]
{:status 200 {:status 200
:body (meta-merge swagger {:paths paths})}))))) :body (meta-merge swagger {:paths paths})})))))

View file

@ -14,7 +14,7 @@
(testing "simple" (testing "simple"
(let [router (r/router ["/api" ["/ipa" ["/:size" ::beer]]] {:router r})] (let [router (r/router ["/api" ["/ipa" ["/:size" ::beer]]] {:router r})]
(is (= name (r/router-name router))) (is (= name (r/router-name router)))
(is (= [["/api/ipa/:size" {:name ::beer} nil]] (is (= [["/api/ipa/:size" {:name ::beer}]]
(r/routes router))) (r/routes router)))
(is (map? (r/options router))) (is (map? (r/options router)))
(is (= (r/map->Match (is (= (r/map->Match
@ -76,7 +76,7 @@
(are [r name] (are [r name]
(let [router (r/router ["/api" ["/ipa" ["/large" ::beer]]] {:router r})] (let [router (r/router ["/api" ["/ipa" ["/large" ::beer]]] {:router r})]
(is (= name (r/router-name router))) (is (= name (r/router-name router)))
(is (= [["/api/ipa/large" {:name ::beer} nil]] (is (= [["/api/ipa/large" {:name ::beer}]]
(r/routes router))) (r/routes router)))
(is (map? (r/options router))) (is (map? (r/options router)))
(is (= (r/map->Match (is (= (r/map->Match
@ -141,7 +141,7 @@
["/api/pong" {:name ::pong ["/api/pong" {:name ::pong
:path "/api/pong", :path "/api/pong",
:roles #{:admin}}]] :roles #{:admin}}]]
(map butlast (r/routes router))))) (r/routes router))))
(testing "route match contains compiled handler" (testing "route match contains compiled handler"
(is (= 2 @compile-times)) (is (= 2 @compile-times))

View file

@ -166,7 +166,7 @@
(is (= [::i1 ::i3 :ok ::i3 ::i1] (app "/api"))) (is (= [::i1 ::i3 :ok ::i3 ::i1] (app "/api")))
(testing "routes contain list of actually applied interceptors" (testing "routes contain list of actually applied interceptors"
(is (= [::i1 ::i3 ::api] (->> (r/routes router) (is (= [::i1 ::i3 ::api] (->> (r/compiled-routes router)
first first
last last
:interceptors :interceptors

View file

@ -178,7 +178,7 @@
(is (= [::mw1 ::mw3 :ok ::mw3 ::mw1] (app "/api"))) (is (= [::mw1 ::mw3 :ok ::mw3 ::mw1] (app "/api")))
(testing "routes contain list of actually applied mw" (testing "routes contain list of actually applied mw"
(is (= [::mw1 ::mw3] (->> (r/routes router) (is (= [::mw1 ::mw3] (->> (r/compiled-routes router)
first first
last last
:middleware :middleware