mirror of
https://github.com/metosin/reitit.git
synced 2025-12-19 17:21:10 +00:00
:params => :path-params
This commit is contained in:
parent
9f60b2f56d
commit
54b24be28e
15 changed files with 78 additions and 79 deletions
|
|
@ -46,14 +46,14 @@ Optionally, the parts can be required separately:
|
||||||
; #Match{:template "/api/ping"
|
; #Match{:template "/api/ping"
|
||||||
; :data {:name ::ping}
|
; :data {:name ::ping}
|
||||||
; :result nil
|
; :result nil
|
||||||
; :params {}
|
; :path-params {}
|
||||||
; :path "/api/ping"}
|
; :path "/api/ping"}
|
||||||
|
|
||||||
(r/match-by-name router ::order {:id 2})
|
(r/match-by-name router ::order {:id 2})
|
||||||
; #Match{:template "/api/orders/:id",
|
; #Match{:template "/api/orders/:id",
|
||||||
; :data {:name ::order},
|
; :data {:name ::order},
|
||||||
; :result nil,
|
; :result nil,
|
||||||
; :params {:id 2},
|
; :path-params {:id 2},
|
||||||
; :path "/api/orders/2"}
|
; :path "/api/orders/2"}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,14 +53,14 @@ Routing:
|
||||||
; #Match{:template "/api/ping"
|
; #Match{:template "/api/ping"
|
||||||
; :data {:name ::ping}
|
; :data {:name ::ping}
|
||||||
; :result nil
|
; :result nil
|
||||||
; :params {}
|
; :path-params {}
|
||||||
; :path "/api/ping"}
|
; :path "/api/ping"}
|
||||||
|
|
||||||
(r/match-by-path router "/api/orders/1")
|
(r/match-by-path router "/api/orders/1")
|
||||||
; #Match{:template "/api/orders/:id"
|
; #Match{:template "/api/orders/:id"
|
||||||
; :data {:name ::order-by-id}
|
; :data {:name ::order-by-id}
|
||||||
; :result nil
|
; :result nil
|
||||||
; :params {:id "1"}
|
; :path-params {:id "1"}
|
||||||
; :path "/api/orders/1"}
|
; :path "/api/orders/1"}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -74,14 +74,14 @@ Reverse-routing:
|
||||||
; #Match{:template "/api/ping"
|
; #Match{:template "/api/ping"
|
||||||
; :data {:name ::ping}
|
; :data {:name ::ping}
|
||||||
; :result nil
|
; :result nil
|
||||||
; :params {}
|
; :path-params {}
|
||||||
; :path "/api/ping"}
|
; :path "/api/ping"}
|
||||||
|
|
||||||
(r/match-by-name router ::order-by-id)
|
(r/match-by-name router ::order-by-id)
|
||||||
; #PartialMatch{:template "/api/orders/:id"
|
; #PartialMatch{:template "/api/orders/:id"
|
||||||
; :data {:name :user/order-by-id}
|
; :data {:name :user/order-by-id}
|
||||||
; :result nil
|
; :result nil
|
||||||
; :params nil
|
; :path-params nil
|
||||||
; :required #{:id}}
|
; :required #{:id}}
|
||||||
|
|
||||||
(r/partial-match? (r/match-by-name router ::order-by-id))
|
(r/partial-match? (r/match-by-name router ::order-by-id))
|
||||||
|
|
@ -91,7 +91,7 @@ Reverse-routing:
|
||||||
; #Match{:template "/api/orders/:id",
|
; #Match{:template "/api/orders/:id",
|
||||||
; :data {:name ::order-by-id},
|
; :data {:name ::order-by-id},
|
||||||
; :result nil,
|
; :result nil,
|
||||||
; :params {:id 2},
|
; :path-params {:id 2},
|
||||||
; :path "/api/orders/2"}
|
; :path "/api/orders/2"}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -141,6 +141,6 @@ Reverse-routing:
|
||||||
; :get {:handler #object[user$handler]}
|
; :get {:handler #object[user$handler]}
|
||||||
; :name ::ping}
|
; :name ::ping}
|
||||||
; :result #Methods{...}
|
; :result #Methods{...}
|
||||||
; :params nil
|
; :path-params nil
|
||||||
; :path "/api/ping"}
|
; :path "/api/ping"}
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ Matching a route:
|
||||||
; #Match{:template "/api/ping"
|
; #Match{:template "/api/ping"
|
||||||
; :data {:name :user/ping}
|
; :data {:name :user/ping}
|
||||||
; :result nil
|
; :result nil
|
||||||
; :params {}
|
; :path-params {}
|
||||||
; :path "/api/ping"}
|
; :path "/api/ping"}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -46,7 +46,7 @@ If not all path-parameters are set, a `PartialMatch` is returned:
|
||||||
; #PartialMatch{:template "/api/user/:id",
|
; #PartialMatch{:template "/api/user/:id",
|
||||||
; :data {:name :user/user},
|
; :data {:name :user/user},
|
||||||
; :result nil,
|
; :result nil,
|
||||||
; :params nil,
|
; :path-params nil,
|
||||||
; :required #{:id}}
|
; :required #{:id}}
|
||||||
|
|
||||||
(r/partial-match? (r/match-by-name router ::user))
|
(r/partial-match? (r/match-by-name router ::user))
|
||||||
|
|
@ -61,7 +61,7 @@ With provided path-parameters:
|
||||||
; :data {:name :user/user}
|
; :data {:name :user/user}
|
||||||
; :path "/api/user/1"
|
; :path "/api/user/1"
|
||||||
; :result nil
|
; :result nil
|
||||||
; :params {:id "1"}}
|
; :path-params {:id "1"}}
|
||||||
```
|
```
|
||||||
|
|
||||||
There is also a exception throwing version:
|
There is also a exception throwing version:
|
||||||
|
|
|
||||||
|
|
@ -33,5 +33,5 @@ Match provides the route information:
|
||||||
; :data {:name :user/user}
|
; :data {:name :user/user}
|
||||||
; :path "/api/user/1"
|
; :path "/api/user/1"
|
||||||
; :result nil
|
; :result nil
|
||||||
; :params {:id "1"}}
|
; :path-params {:id "1"}}
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -28,14 +28,14 @@ The expanded route data can be retrieved from a router with `routes` and is retu
|
||||||
; #Match{:template "/ping"
|
; #Match{:template "/ping"
|
||||||
; :data {:name :user/ping}
|
; :data {:name :user/ping}
|
||||||
; :result nil
|
; :result nil
|
||||||
; :params {}
|
; :path-params {}
|
||||||
; :path "/ping"}
|
; :path "/ping"}
|
||||||
|
|
||||||
(r/match-by-name router ::ping)
|
(r/match-by-name router ::ping)
|
||||||
; #Match{:template "/ping"
|
; #Match{:template "/ping"
|
||||||
; :data {:name :user/ping}
|
; :data {:name :user/ping}
|
||||||
; :result nil
|
; :result nil
|
||||||
; :params {}
|
; :path-params {}
|
||||||
; :path "/ping"}
|
; :path "/ping"}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -92,6 +92,6 @@ By default, `reitit/Expand` protocol is used to expand the route arguments. It e
|
||||||
; #Match{:template "/ping"
|
; #Match{:template "/ping"
|
||||||
; :data {:name :user/ping}
|
; :data {:name :user/ping}
|
||||||
; :result nil
|
; :result nil
|
||||||
; :params {}
|
; :path-params {}
|
||||||
; :path "/ping"}
|
; :path "/ping"}
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ Successful coercion:
|
||||||
; :coercion <<:spec>>
|
; :coercion <<:spec>>
|
||||||
; :parameters {:path ::path-params}},
|
; :parameters {:path ::path-params}},
|
||||||
; :result {:path #object[reitit.coercion$request_coercer$]},
|
; :result {:path #object[reitit.coercion$request_coercer$]},
|
||||||
; :params {:company "metosin", :user-id "123"},
|
; :path-params {:company "metosin", :user-id "123"},
|
||||||
; :parameters {:path {:company "metosin", :user-id 123}}
|
; :parameters {:path {:company "metosin", :user-id 123}}
|
||||||
; :path "/metosin/users/123"}
|
; :path "/metosin/users/123"}
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ Match with the parsed `:params` as Strings:
|
||||||
; #Match{:template "/:company/users/:user-id",
|
; #Match{:template "/:company/users/:user-id",
|
||||||
; :data {:name :user/user-view},
|
; :data {:name :user/user-view},
|
||||||
; :result nil,
|
; :result nil,
|
||||||
; :params {:company "metosin", :user-id "123"},
|
; :path-params {:company "metosin", :user-id "123"},
|
||||||
; :path "/metosin/users/123"}
|
; :path "/metosin/users/123"}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -69,7 +69,7 @@ A Match:
|
||||||
; :parameters {:path {:company java.lang.String,
|
; :parameters {:path {:company java.lang.String,
|
||||||
; :user-id Int}}},
|
; :user-id Int}}},
|
||||||
; :result nil,
|
; :result nil,
|
||||||
; :params {:company "metosin", :user-id "123"},
|
; :path-params {:company "metosin", :user-id "123"},
|
||||||
; :path "/metosin/users/123"}
|
; :path "/metosin/users/123"}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -109,7 +109,7 @@ Routing again:
|
||||||
; :parameters {:path {:company java.lang.String,
|
; :parameters {:path {:company java.lang.String,
|
||||||
; :user-id Int}}},
|
; :user-id Int}}},
|
||||||
; :result {:path #object[reitit.coercion$request_coercer$]},
|
; :result {:path #object[reitit.coercion$request_coercer$]},
|
||||||
; :params {:company "metosin", :user-id "123"},
|
; :path-params {:company "metosin", :user-id "123"},
|
||||||
; :path "/metosin/users/123"}
|
; :path "/metosin/users/123"}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -165,7 +165,7 @@ Here's an full example for doing routing and coercion with Reitit and Schema:
|
||||||
; :parameters {:path {:company java.lang.String,
|
; :parameters {:path {:company java.lang.String,
|
||||||
; :user-id Int}}},
|
; :user-id Int}}},
|
||||||
; :result {:path #object[reitit.coercion$request_coercer$]},
|
; :result {:path #object[reitit.coercion$request_coercer$]},
|
||||||
; :params {:company "metosin", :user-id "123"},
|
; :path-params {:company "metosin", :user-id "123"},
|
||||||
; :parameters {:path {:company "metosin", :user-id 123}}
|
; :parameters {:path {:company "metosin", :user-id 123}}
|
||||||
; :path "/metosin/users/123"}
|
; :path "/metosin/users/123"}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ Successful coercion:
|
||||||
; :parameters {:path {:company string?,
|
; :parameters {:path {:company string?,
|
||||||
; :user-id int?}}},
|
; :user-id int?}}},
|
||||||
; :result {:path #object[reitit.coercion$request_coercer$]},
|
; :result {:path #object[reitit.coercion$request_coercer$]},
|
||||||
; :params {:company "metosin", :user-id "123"},
|
; :path-params {:company "metosin", :user-id "123"},
|
||||||
; :parameters {:path {:company "metosin", :user-id 123}}
|
; :parameters {:path {:company "metosin", :user-id 123}}
|
||||||
; :path "/metosin/users/123"}
|
; :path "/metosin/users/123"}
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ Successful coercion:
|
||||||
; :parameters {:path {:company java.lang.String,
|
; :parameters {:path {:company java.lang.String,
|
||||||
; :user-id Int}}},
|
; :user-id Int}}},
|
||||||
; :result {:path #object[reitit.coercion$request_coercer$]},
|
; :result {:path #object[reitit.coercion$request_coercer$]},
|
||||||
; :params {:company "metosin", :user-id "123"},
|
; :path-params {:company "metosin", :user-id "123"},
|
||||||
; :parameters {:path {:company "metosin", :user-id 123}}
|
; :parameters {:path {:company "metosin", :user-id 123}}
|
||||||
; :path "/metosin/users/123"}
|
; :path "/metosin/users/123"}
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -157,4 +157,4 @@
|
||||||
If coercion or parameters are not defined, return `nil`"
|
If coercion or parameters are not defined, return `nil`"
|
||||||
[match]
|
[match]
|
||||||
(if-let [result (:result match)]
|
(if-let [result (:result match)]
|
||||||
(coerce-request result {:path-params (:params match)})))
|
(coerce-request result {:path-params (:path-params match)})))
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@
|
||||||
(into [] (keep #(compile-route % opts) routes)))
|
(into [] (keep #(compile-route % opts) routes)))
|
||||||
|
|
||||||
(defn route-info [route]
|
(defn route-info [route]
|
||||||
(select-keys (impl/create route) [:path :parts :params :result :data]))
|
(select-keys (impl/create route) [:path :parts :path-params :result :data]))
|
||||||
|
|
||||||
(defprotocol Router
|
(defprotocol Router
|
||||||
(router-name [this])
|
(router-name [this])
|
||||||
|
|
@ -108,13 +108,13 @@
|
||||||
(options [this])
|
(options [this])
|
||||||
(route-names [this])
|
(route-names [this])
|
||||||
(match-by-path [this path])
|
(match-by-path [this path])
|
||||||
(match-by-name [this name] [this name params]))
|
(match-by-name [this name] [this name path-params]))
|
||||||
|
|
||||||
(defn router? [x]
|
(defn router? [x]
|
||||||
(satisfies? Router x))
|
(satisfies? Router x))
|
||||||
|
|
||||||
(defrecord Match [template data result params path])
|
(defrecord Match [template data result path-params path])
|
||||||
(defrecord PartialMatch [template data result params required])
|
(defrecord PartialMatch [template data result path-params required])
|
||||||
|
|
||||||
(defn partial-match? [x]
|
(defn partial-match? [x]
|
||||||
(instance? PartialMatch x))
|
(instance? PartialMatch x))
|
||||||
|
|
@ -122,12 +122,12 @@
|
||||||
(defn match-by-name!
|
(defn match-by-name!
|
||||||
([this name]
|
([this name]
|
||||||
(match-by-name! this name nil))
|
(match-by-name! this name nil))
|
||||||
([this name params]
|
([this name path-params]
|
||||||
(if-let [match (match-by-name this name params)]
|
(if-let [match (match-by-name this name path-params)]
|
||||||
(if-not (partial-match? match)
|
(if-not (partial-match? match)
|
||||||
match
|
match
|
||||||
(impl/throw-on-missing-path-params
|
(impl/throw-on-missing-path-params
|
||||||
(:template match) (:required match) params)))))
|
(:template match) (:required match) path-params)))))
|
||||||
|
|
||||||
(def default-router-options
|
(def default-router-options
|
||||||
{:lookup name-lookup
|
{:lookup name-lookup
|
||||||
|
|
@ -145,10 +145,10 @@
|
||||||
(let [names (find-names routes opts)
|
(let [names (find-names 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 [params] :as route} (impl/create [p data result])
|
(let [{:keys [path-params] :as route} (impl/create [p data result])
|
||||||
f #(if-let [path (impl/path-for route %)]
|
f #(if-let [path (impl/path-for route %)]
|
||||||
(->Match p data result % path)
|
(->Match p data result % path)
|
||||||
(->PartialMatch p data result % 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)
|
[[] {}] routes)
|
||||||
|
|
@ -166,16 +166,16 @@
|
||||||
names)
|
names)
|
||||||
(match-by-path [_ path]
|
(match-by-path [_ path]
|
||||||
(reduce
|
(reduce
|
||||||
(fn [acc ^Route route]
|
(fn [_ ^Route route]
|
||||||
(if-let [params ((:matcher route) path)]
|
(if-let [path-params ((:matcher route) path)]
|
||||||
(reduced (->Match (:path route) (:data route) (:result route) params path))))
|
(reduced (->Match (:path route) (:data route) (:result route) path-params path))))
|
||||||
nil pl))
|
nil pl))
|
||||||
(match-by-name [_ name]
|
(match-by-name [_ name]
|
||||||
(if-let [match (impl/fast-get lookup name)]
|
(if-let [match (impl/fast-get lookup name)]
|
||||||
(match nil)))
|
(match nil)))
|
||||||
(match-by-name [_ name params]
|
(match-by-name [_ name path-params]
|
||||||
(if-let [match (impl/fast-get lookup name)]
|
(if-let [match (impl/fast-get lookup name)]
|
||||||
(match params)))))))
|
(match path-params)))))))
|
||||||
|
|
||||||
(defn lookup-router
|
(defn lookup-router
|
||||||
"Creates a lookup-router from resolved routes and optional
|
"Creates a lookup-router from resolved routes and optional
|
||||||
|
|
@ -213,9 +213,9 @@
|
||||||
(match-by-name [_ name]
|
(match-by-name [_ name]
|
||||||
(if-let [match (impl/fast-get lookup name)]
|
(if-let [match (impl/fast-get lookup name)]
|
||||||
(match nil)))
|
(match nil)))
|
||||||
(match-by-name [_ name params]
|
(match-by-name [_ name path-params]
|
||||||
(if-let [match (impl/fast-get lookup name)]
|
(if-let [match (impl/fast-get lookup name)]
|
||||||
(match params)))))))
|
(match path-params)))))))
|
||||||
|
|
||||||
(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
|
||||||
|
|
@ -226,10 +226,10 @@
|
||||||
(let [names (find-names routes opts)
|
(let [names (find-names 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 [params] :as route} (impl/create [p data result])
|
(let [{:keys [path-params] :as route} (impl/create [p data result])
|
||||||
f #(if-let [path (impl/path-for route %)]
|
f #(if-let [path (impl/path-for route %)]
|
||||||
(->Match p data result % path)
|
(->Match p data result % path)
|
||||||
(->PartialMatch p data result % 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 {}] routes)
|
||||||
|
|
@ -248,14 +248,14 @@
|
||||||
(match-by-path [_ path]
|
(match-by-path [_ path]
|
||||||
(if-let [match (segment/lookup pl path)]
|
(if-let [match (segment/lookup pl path)]
|
||||||
(-> (:data match)
|
(-> (:data match)
|
||||||
(assoc :params (:params match))
|
(assoc :path-params (:path-params match))
|
||||||
(assoc :path path))))
|
(assoc :path path))))
|
||||||
(match-by-name [_ name]
|
(match-by-name [_ name]
|
||||||
(if-let [match (impl/fast-get lookup name)]
|
(if-let [match (impl/fast-get lookup name)]
|
||||||
(match nil)))
|
(match nil)))
|
||||||
(match-by-name [_ name params]
|
(match-by-name [_ name path-params]
|
||||||
(if-let [match (impl/fast-get lookup name)]
|
(if-let [match (impl/fast-get lookup name)]
|
||||||
(match params)))))))
|
(match path-params)))))))
|
||||||
|
|
||||||
(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
|
||||||
|
|
@ -288,9 +288,9 @@
|
||||||
(match-by-name [_ name]
|
(match-by-name [_ name]
|
||||||
(if (= n name)
|
(if (= n name)
|
||||||
match))
|
match))
|
||||||
(match-by-name [_ name params]
|
(match-by-name [_ name path-params]
|
||||||
(if (= n name)
|
(if (= n name)
|
||||||
(impl/fast-assoc match :params params)))))))
|
(impl/fast-assoc match :path-params path-params)))))))
|
||||||
|
|
||||||
(defn mixed-router
|
(defn mixed-router
|
||||||
"Creates two routers: [[lookup-router]] or [[single-static-path-router]] for
|
"Creates two routers: [[lookup-router]] or [[single-static-path-router]] for
|
||||||
|
|
@ -321,9 +321,9 @@
|
||||||
(match-by-name [_ name]
|
(match-by-name [_ name]
|
||||||
(or (match-by-name static-router name)
|
(or (match-by-name static-router name)
|
||||||
(match-by-name wildcard-router name)))
|
(match-by-name wildcard-router name)))
|
||||||
(match-by-name [_ name params]
|
(match-by-name [_ name path-params]
|
||||||
(or (match-by-name static-router name params)
|
(or (match-by-name static-router name path-params)
|
||||||
(match-by-name wildcard-router name params)))))))
|
(match-by-name wildcard-router name path-params)))))))
|
||||||
|
|
||||||
(defn router
|
(defn router
|
||||||
"Create a [[Router]] from raw route data and optionally an options map.
|
"Create a [[Router]] from raw route data and optionally an options map.
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@
|
||||||
;; Routing (c) Metosin
|
;; Routing (c) Metosin
|
||||||
;;
|
;;
|
||||||
|
|
||||||
(defrecord Route [path matcher parts params data result])
|
(defrecord Route [path matcher parts path-params data result])
|
||||||
|
|
||||||
(defn create [[path data result]]
|
(defn create [[path data result]]
|
||||||
(let [path #?(:clj (.intern ^String path) :cljs path)]
|
(let [path #?(:clj (.intern ^String path) :cljs path)]
|
||||||
|
|
@ -110,8 +110,7 @@
|
||||||
:data data})
|
:data data})
|
||||||
(dissoc $ :path-re :path-constraints)
|
(dissoc $ :path-re :path-constraints)
|
||||||
(update $ :path-params set)
|
(update $ :path-params set)
|
||||||
(set/rename-keys $ {:path-parts :parts
|
(set/rename-keys $ {:path-parts :parts})
|
||||||
:path-params :params})
|
|
||||||
(map->Route $))))
|
(map->Route $))))
|
||||||
|
|
||||||
(defn wild-route? [[path]]
|
(defn wild-route? [[path]]
|
||||||
|
|
@ -128,20 +127,20 @@
|
||||||
(not= s1 s2) false
|
(not= s1 s2) false
|
||||||
:else (recur ss1 ss2))))
|
:else (recur ss1 ss2))))
|
||||||
|
|
||||||
(defn path-for [^Route route params]
|
(defn path-for [^Route route path-params]
|
||||||
(if-let [required (:params route)]
|
(if-let [required (:path-params route)]
|
||||||
(if (every? #(contains? params %) required)
|
(if (every? #(contains? path-params %) required)
|
||||||
(str "/" (str/join \/ (map #(get (or params {}) % %) (:parts route)))))
|
(str "/" (str/join \/ (map #(get (or path-params {}) % %) (:parts route)))))
|
||||||
(:path route)))
|
(:path route)))
|
||||||
|
|
||||||
(defn throw-on-missing-path-params [template required params]
|
(defn throw-on-missing-path-params [template required path-params]
|
||||||
(when-not (every? #(contains? params %) required)
|
(when-not (every? #(contains? path-params %) required)
|
||||||
(let [defined (-> params keys set)
|
(let [defined (-> path-params keys set)
|
||||||
missing (clojure.set/difference required defined)]
|
missing (clojure.set/difference required defined)]
|
||||||
(throw
|
(throw
|
||||||
(ex-info
|
(ex-info
|
||||||
(str "missing path-params for route " template " -> " missing)
|
(str "missing path-params for route " template " -> " missing)
|
||||||
{:params params, :required required})))))
|
{:path-params path-params, :required required})))))
|
||||||
|
|
||||||
(defn fast-assoc
|
(defn fast-assoc
|
||||||
#?@(:clj [[^clojure.lang.Associative a k v] (.assoc a k v)]
|
#?@(:clj [[^clojure.lang.Associative a k v] (.assoc a k v)]
|
||||||
|
|
|
||||||
|
|
@ -3,23 +3,23 @@
|
||||||
(:require [reitit.impl :as impl]
|
(:require [reitit.impl :as impl]
|
||||||
[clojure.string :as str]))
|
[clojure.string :as str]))
|
||||||
|
|
||||||
(defrecord Match [data params])
|
(defrecord Match [data path-params])
|
||||||
|
|
||||||
(defprotocol Segment
|
(defprotocol Segment
|
||||||
(-insert [this ps data])
|
(-insert [this ps data])
|
||||||
(-lookup [this ps params]))
|
(-lookup [this ps path-params]))
|
||||||
|
|
||||||
(extend-protocol Segment
|
(extend-protocol Segment
|
||||||
nil
|
nil
|
||||||
(-insert [_ _ _])
|
(-insert [_ _ _])
|
||||||
(-lookup [_ _ _]))
|
(-lookup [_ _ _]))
|
||||||
|
|
||||||
(defn- -catch-all [children catch-all params p ps]
|
(defn- -catch-all [children catch-all path-params p ps]
|
||||||
(if catch-all
|
(if catch-all
|
||||||
(-lookup
|
(-lookup
|
||||||
(impl/fast-get children catch-all)
|
(impl/fast-get children catch-all)
|
||||||
nil
|
nil
|
||||||
(assoc params catch-all (str/join "/" (cons p ps))))))
|
(assoc path-params catch-all (str/join "/" (cons p ps))))))
|
||||||
|
|
||||||
(defn- segment
|
(defn- segment
|
||||||
([] (segment {} #{} nil nil))
|
([] (segment {} #{} nil nil))
|
||||||
|
|
@ -36,12 +36,12 @@
|
||||||
catch-all (or c catch-all)
|
catch-all (or c catch-all)
|
||||||
children (update children (or w c p) #(-insert (or % (segment)) ps d))]
|
children (update children (or w c p) #(-insert (or % (segment)) ps d))]
|
||||||
(segment children wilds catch-all match))))
|
(segment children wilds catch-all match))))
|
||||||
(-lookup [_ [p & ps] params]
|
(-lookup [_ [p & ps] path-params]
|
||||||
(if (nil? p)
|
(if (nil? p)
|
||||||
(if match (assoc match :params params))
|
(if match (assoc match :path-params path-params))
|
||||||
(or (-lookup (impl/fast-get children' p) ps params)
|
(or (-lookup (impl/fast-get children' p) ps path-params)
|
||||||
(some #(-lookup (impl/fast-get children' %) ps (assoc params % p)) wilds)
|
(some #(-lookup (impl/fast-get children' %) ps (assoc path-params % p)) wilds)
|
||||||
(-catch-all children' catch-all params p ps))))))))
|
(-catch-all children' catch-all path-params p ps))))))))
|
||||||
|
|
||||||
(defn insert [root path data]
|
(defn insert [root path data]
|
||||||
(-insert (or root (segment)) (impl/segments path) (map->Match {:data data})))
|
(-insert (or root (segment)) (impl/segments path) (map->Match {:data data})))
|
||||||
|
|
|
||||||
|
|
@ -62,12 +62,12 @@
|
||||||
([request]
|
([request]
|
||||||
(if-let [match (r/match-by-path router (:uri request))]
|
(if-let [match (r/match-by-path router (:uri request))]
|
||||||
(let [method (:request-method request :any)
|
(let [method (:request-method request :any)
|
||||||
params (:params match)
|
path-params (:path-params match)
|
||||||
result (:result match)
|
result (:result match)
|
||||||
handler (or (-> result method :handler)
|
handler (or (-> result method :handler)
|
||||||
(-> result :any (:handler default-handler)))
|
(-> result :any (:handler default-handler)))
|
||||||
request (cond-> (impl/fast-assoc request ::match match)
|
request (cond-> (impl/fast-assoc request ::match match)
|
||||||
(seq params) (impl/fast-assoc :path-params params))
|
(seq path-params) (impl/fast-assoc :path-params path-params))
|
||||||
response (handler request)]
|
response (handler request)]
|
||||||
(if (nil? response)
|
(if (nil? response)
|
||||||
(default-handler request)
|
(default-handler request)
|
||||||
|
|
@ -76,12 +76,12 @@
|
||||||
([request respond raise]
|
([request respond raise]
|
||||||
(if-let [match (r/match-by-path router (:uri request))]
|
(if-let [match (r/match-by-path router (:uri request))]
|
||||||
(let [method (:request-method request :any)
|
(let [method (:request-method request :any)
|
||||||
params (:params match)
|
path-params (:path-params match)
|
||||||
result (:result match)
|
result (:result match)
|
||||||
handler (or (-> result method :handler)
|
handler (or (-> result method :handler)
|
||||||
(-> result :any (:handler default-handler)))
|
(-> result :any (:handler default-handler)))
|
||||||
request (cond-> (impl/fast-assoc request ::match match)
|
request (cond-> (impl/fast-assoc request ::match match)
|
||||||
(seq params) (impl/fast-assoc :path-params params))]
|
(seq path-params) (impl/fast-assoc :path-params path-params))]
|
||||||
(handler request respond raise))
|
(handler request respond raise))
|
||||||
(default-handler request respond raise))))
|
(default-handler request respond raise))))
|
||||||
{::router router}))))
|
{::router router}))))
|
||||||
|
|
|
||||||
|
|
@ -21,13 +21,13 @@
|
||||||
{:template "/api/ipa/:size"
|
{:template "/api/ipa/:size"
|
||||||
:data {:name ::beer}
|
:data {:name ::beer}
|
||||||
:path "/api/ipa/large"
|
:path "/api/ipa/large"
|
||||||
:params {:size "large"}})
|
:path-params {:size "large"}})
|
||||||
(r/match-by-path router "/api/ipa/large")))
|
(r/match-by-path router "/api/ipa/large")))
|
||||||
(is (= (r/map->Match
|
(is (= (r/map->Match
|
||||||
{:template "/api/ipa/:size"
|
{:template "/api/ipa/:size"
|
||||||
:data {:name ::beer}
|
:data {:name ::beer}
|
||||||
:path "/api/ipa/large"
|
:path "/api/ipa/large"
|
||||||
:params {:size "large"}})
|
:path-params {:size "large"}})
|
||||||
(r/match-by-name router ::beer {:size "large"})))
|
(r/match-by-name router ::beer {:size "large"})))
|
||||||
(is (= nil (r/match-by-name router "ILLEGAL")))
|
(is (= nil (r/match-by-name router "ILLEGAL")))
|
||||||
(is (= [::beer] (r/route-names router)))
|
(is (= [::beer] (r/route-names router)))
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
{:template "/api/ipa/:size"
|
{:template "/api/ipa/:size"
|
||||||
:data {:name ::beer}
|
:data {:name ::beer}
|
||||||
:required #{:size}
|
:required #{:size}
|
||||||
:params nil})
|
:path-params nil})
|
||||||
(r/match-by-name router ::beer)))
|
(r/match-by-name router ::beer)))
|
||||||
(is (r/partial-match? (r/match-by-name router ::beer)))
|
(is (r/partial-match? (r/match-by-name router ::beer)))
|
||||||
(is (thrown-with-msg?
|
(is (thrown-with-msg?
|
||||||
|
|
@ -77,13 +77,13 @@
|
||||||
{:template "/api/ipa/large"
|
{:template "/api/ipa/large"
|
||||||
:data {:name ::beer}
|
:data {:name ::beer}
|
||||||
:path "/api/ipa/large"
|
:path "/api/ipa/large"
|
||||||
:params {}})
|
:path-params {}})
|
||||||
(r/match-by-path router "/api/ipa/large")))
|
(r/match-by-path router "/api/ipa/large")))
|
||||||
(is (= (r/map->Match
|
(is (= (r/map->Match
|
||||||
{:template "/api/ipa/large"
|
{:template "/api/ipa/large"
|
||||||
:data {:name ::beer}
|
:data {:name ::beer}
|
||||||
:path "/api/ipa/large"
|
:path "/api/ipa/large"
|
||||||
:params {:size "large"}})
|
:path-params {:size "large"}})
|
||||||
(r/match-by-name router ::beer {:size "large"})))
|
(r/match-by-name router ::beer {:size "large"})))
|
||||||
(is (= nil (r/match-by-name router "ILLEGAL")))
|
(is (= nil (r/match-by-name router "ILLEGAL")))
|
||||||
(is (= [::beer] (r/route-names router)))
|
(is (= [::beer] (r/route-names router)))
|
||||||
|
|
@ -181,7 +181,7 @@
|
||||||
{:template "/api/user/:id/:sub-id"
|
{:template "/api/user/:id/:sub-id"
|
||||||
:data {:mw [:api], :parameters {:id "String", :sub-id "String"}}
|
:data {:mw [:api], :parameters {:id "String", :sub-id "String"}}
|
||||||
:path "/api/user/1/2"
|
:path "/api/user/1/2"
|
||||||
:params {:id "1", :sub-id "2"}})
|
:path-params {:id "1", :sub-id "2"}})
|
||||||
(r/match-by-path router "/api/user/1/2"))))))
|
(r/match-by-path router "/api/user/1/2"))))))
|
||||||
|
|
||||||
(deftest conflicting-routes-test
|
(deftest conflicting-routes-test
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue