mirror of
https://github.com/metosin/reitit.git
synced 2025-12-28 04:18:24 +00:00
Welcome segment-router!
This commit is contained in:
parent
102fd35f04
commit
5d7670de60
3 changed files with 95 additions and 33 deletions
|
|
@ -2,6 +2,7 @@
|
|||
(:require [meta-merge.core :refer [meta-merge]]
|
||||
[clojure.string :as str]
|
||||
[reitit.trie :as trie]
|
||||
[reitit.segment :as segment]
|
||||
[reitit.impl :as impl #?@(:cljs [:refer [Route]])])
|
||||
#?(:clj
|
||||
(:import (reitit.impl Route))))
|
||||
|
|
@ -260,6 +261,47 @@
|
|||
(if-let [match (impl/fast-get lookup name)]
|
||||
(match params)))))))
|
||||
|
||||
(defn segment-router
|
||||
"Creates a special prefix-tree style segment router from resolved routes and optional
|
||||
expanded options. See [[router]] for available options"
|
||||
([routes]
|
||||
(segment-router routes {}))
|
||||
([routes opts]
|
||||
(let [compiled (compile-routes routes opts)
|
||||
names (find-names routes opts)
|
||||
[pl nl] (reduce
|
||||
(fn [[pl nl] [p {:keys [name] :as data} result]]
|
||||
(let [{:keys [params] :as route} (impl/create [p data result])
|
||||
f #(if-let [path (impl/path-for route %)]
|
||||
(->Match p data result % path)
|
||||
(->PartialMatch p data result % params))]
|
||||
[(segment/insert pl p (->Match p data result nil nil))
|
||||
(if name (assoc nl name f) nl)]))
|
||||
[nil {}] compiled)
|
||||
lookup (impl/fast-map nl)]
|
||||
^{:type ::router}
|
||||
(reify
|
||||
Router
|
||||
(router-name [_]
|
||||
:segment-router)
|
||||
(routes [_]
|
||||
compiled)
|
||||
(options [_]
|
||||
opts)
|
||||
(route-names [_]
|
||||
names)
|
||||
(match-by-path [_ path]
|
||||
(if-let [match (segment/lookup pl path)]
|
||||
(-> (:data match)
|
||||
(assoc :params (:params match))
|
||||
(assoc :path path))))
|
||||
(match-by-name [_ name]
|
||||
(if-let [match (impl/fast-get lookup name)]
|
||||
(match nil)))
|
||||
(match-by-name [_ name params]
|
||||
(if-let [match (impl/fast-get lookup name)]
|
||||
(match params)))))))
|
||||
|
||||
(defn single-static-path-router
|
||||
"Creates a fast router of 1 static route(s) and optional
|
||||
expanded options. See [[router]] for available options"
|
||||
|
|
|
|||
|
|
@ -39,11 +39,14 @@
|
|||
(some #(-lookup (impl/fast-get children' %) ps (assoc params % p)) wilds)
|
||||
(-catch-all catch-all data params p ps))))))))
|
||||
|
||||
(defn insert [root path data]
|
||||
(-insert (or root (segment)) (impl/segments path) (map->Match {:data data})))
|
||||
|
||||
(defn create [paths]
|
||||
(reduce
|
||||
(fn [segment [p data]]
|
||||
(-insert segment (impl/segments p) (map->Match {:data data})))
|
||||
(segment) paths))
|
||||
(insert segment p data))
|
||||
nil paths))
|
||||
|
||||
(defn lookup [segment ^String path]
|
||||
(-lookup segment (.split path "/") {}))
|
||||
|
|
|
|||
|
|
@ -9,41 +9,57 @@
|
|||
|
||||
(testing "routers handling wildcard paths"
|
||||
(are [r name]
|
||||
(let [router (r/router ["/api" ["/ipa" ["/:size" ::beer]]] {:router r})]
|
||||
(is (= name (r/router-name router)))
|
||||
(is (= [["/api/ipa/:size" {:name ::beer} nil]]
|
||||
(r/routes router)))
|
||||
(is (= true (map? (r/options router))))
|
||||
(is (= (r/map->Match
|
||||
{:template "/api/ipa/:size"
|
||||
:data {:name ::beer}
|
||||
:path "/api/ipa/large"
|
||||
:params {:size "large"}})
|
||||
(r/match-by-path router "/api/ipa/large")))
|
||||
(is (= (r/map->Match
|
||||
{:template "/api/ipa/:size"
|
||||
:data {:name ::beer}
|
||||
:path "/api/ipa/large"
|
||||
:params {:size "large"}})
|
||||
(r/match-by-name router ::beer {:size "large"})))
|
||||
(is (= nil (r/match-by-name router "ILLEGAL")))
|
||||
(is (= [::beer] (r/route-names router)))
|
||||
(testing "wild"
|
||||
|
||||
(testing "name-based routing with missing parameters"
|
||||
(is (= (r/map->PartialMatch
|
||||
{:template "/api/ipa/:size"
|
||||
:data {:name ::beer}
|
||||
:required #{:size}
|
||||
:params nil})
|
||||
(r/match-by-name router ::beer)))
|
||||
(is (= true (r/partial-match? (r/match-by-name router ::beer))))
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"^missing path-params for route /api/ipa/:size -> \#\{:size\}$"
|
||||
(r/match-by-name! router ::beer)))))
|
||||
(testing "simple"
|
||||
(let [router (r/router ["/api" ["/ipa" ["/:size" ::beer]]] {:router r})]
|
||||
(is (= name (r/router-name router)))
|
||||
(is (= [["/api/ipa/:size" {:name ::beer} nil]]
|
||||
(r/routes router)))
|
||||
(is (= true (map? (r/options router))))
|
||||
(is (= (r/map->Match
|
||||
{:template "/api/ipa/:size"
|
||||
:data {:name ::beer}
|
||||
:path "/api/ipa/large"
|
||||
:params {:size "large"}})
|
||||
(r/match-by-path router "/api/ipa/large")))
|
||||
(is (= (r/map->Match
|
||||
{:template "/api/ipa/:size"
|
||||
:data {:name ::beer}
|
||||
:path "/api/ipa/large"
|
||||
:params {:size "large"}})
|
||||
(r/match-by-name router ::beer {:size "large"})))
|
||||
(is (= nil (r/match-by-name router "ILLEGAL")))
|
||||
(is (= [::beer] (r/route-names router)))
|
||||
|
||||
(testing "name-based routing with missing parameters"
|
||||
(is (= (r/map->PartialMatch
|
||||
{:template "/api/ipa/:size"
|
||||
:data {:name ::beer}
|
||||
:required #{:size}
|
||||
:params nil})
|
||||
(r/match-by-name router ::beer)))
|
||||
(is (= true (r/partial-match? (r/match-by-name router ::beer))))
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"^missing path-params for route /api/ipa/:size -> \#\{:size\}$"
|
||||
(r/match-by-name! router ::beer))))))
|
||||
|
||||
(testing "complex"
|
||||
(let [router (r/router
|
||||
[["/:abba" ::abba]
|
||||
["/abba/1" ::abba1]
|
||||
["/:abba/:dabba/doo" ::doo]
|
||||
["/abba/:dabba/boo" ::boo]] {:router r})
|
||||
matches #(-> router (r/match-by-path %) :data :name)]
|
||||
(is (= ::abba (matches "/abba")))
|
||||
(is (= ::abba1 (matches "/abba/1")))
|
||||
(is (= ::doo (matches "/abba/1/doo")))
|
||||
(is (= ::boo (matches "/abba/1/boo"))))))
|
||||
|
||||
r/linear-router :linear-router
|
||||
r/prefix-tree-router :prefix-tree-router
|
||||
r/segment-router :segment-router
|
||||
r/mixed-router :mixed-router))
|
||||
|
||||
(testing "routers handling static paths"
|
||||
|
|
@ -80,6 +96,7 @@
|
|||
r/single-static-path-router :single-static-path-router
|
||||
r/linear-router :linear-router
|
||||
r/prefix-tree-router :prefix-tree-router
|
||||
r/segment-router :segment-router
|
||||
r/mixed-router :mixed-router))
|
||||
|
||||
(testing "route coercion & compilation"
|
||||
|
|
|
|||
Loading…
Reference in a new issue