mirror of
https://github.com/metosin/reitit.git
synced 2025-12-17 16:31:11 +00:00
commit
0bcfda755f
10 changed files with 196 additions and 89 deletions
18
CHANGELOG.md
18
CHANGELOG.md
|
|
@ -21,6 +21,24 @@ We use [Break Versioning][breakver]. The version numbers follow a `<major>.<mino
|
|||
[metosin/jsonista "0.2.3"] is available but we use "0.2.2"
|
||||
```
|
||||
|
||||
### `reitit-core`
|
||||
|
||||
* Add support for explixit selection of router path-parameter `:syntax`, fixes [#276](https://github.com/metosin/reitit/issues/276)
|
||||
|
||||
```clj
|
||||
(require '[reitit.core :as r])
|
||||
|
||||
(-> (r/router
|
||||
["http://localhost:8080/api/user/{id}" ::user-by-id]
|
||||
{:syntax :bracket})
|
||||
(r/match-by-path "http://localhost:8080/api/user/123"))
|
||||
;#Match{:template "http://localhost:8080/api/user/{id}",
|
||||
; :data {:name :user/user-by-id},
|
||||
; :result nil,
|
||||
; :path-params {:id "123"},
|
||||
; :path "http://localhost:8080/api/user/123"}
|
||||
```
|
||||
|
||||
## 0.3.7 (2019-05-25)
|
||||
|
||||
### `reitit-pedestal`
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@
|
|||
|
||||
Routers can be configured via options. The following options are available for the `reitit.core/router`:
|
||||
|
||||
| key | description |
|
||||
|--------------|-------------|
|
||||
| key | description
|
||||
|--------------|-------------
|
||||
| `:path` | Base-path for routes
|
||||
| `:routes` | Initial resolved routes (default `[]`)
|
||||
| `:data` | Initial route data (default `{}`)
|
||||
| `:spec` | clojure.spec definition for a route data, see `reitit.spec` on how to use this
|
||||
| `:syntax` | Path-parameter syntax as keyword or set of keywords (default #{:bracket :colon})
|
||||
| `:expand` | Function of `arg opts => data` to expand route arg to route data (default `reitit.core/expand`)
|
||||
| `:coerce` | Function of `route opts => route` to coerce resolved route, can throw or return `nil`
|
||||
| `:compile` | Function of `route opts => result` to compile a route handler
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ Routes are defined as vectors of String path and optional (non-sequential) route
|
|||
|
||||
Routes can be wrapped in vectors and lists and `nil` routes are ignored.
|
||||
|
||||
Paths can have path-parameters (`:id`) or catch-all-parameters (`*path`). Since version `0.3.0`, parameters can also be wrapped in brackets, enabling use of qualified keywords `{user/id}`, `{*user/path}`. The non-bracket syntax might be deprecated later.
|
||||
Paths can have path-parameters (`:id`) or catch-all-parameters (`*path`). Parameters can also be wrapped in brackets, enabling use of qualified keywords `{user/id}`, `{*user/path}`. By default, both syntaxes are supported, see [configuring routers](../advanced/configuring_routers.md) on how to change this.
|
||||
|
||||
### Examples
|
||||
|
||||
|
|
@ -129,3 +129,23 @@ Routes are just data, so it's easy to create them programmatically:
|
|||
; ["/add-user" {:post {:interceptors [add-user]}}]
|
||||
; ["/add-order" {:post {:interceptors [add-order]}}])]
|
||||
```
|
||||
|
||||
### Explicit path-parameter syntax
|
||||
|
||||
Router options `:syntax` allows the path-parameter syntax to be explicitely defined. It takes a keyword or set of keywords as a value. Valid values are `:colon` and `:bracket`. Default value is `#{:colon :bracket}`.
|
||||
|
||||
Supporting only `:bracket` syntax:
|
||||
|
||||
```clj
|
||||
(require '[reitit.core :as r])
|
||||
|
||||
(-> (r/router
|
||||
["http://localhost:8080/api/user/{id}" ::user-by-id]
|
||||
{:syntax :bracket})
|
||||
(r/match-by-path "http://localhost:8080/api/user/123"))
|
||||
;#Match{:template "http://localhost:8080/api/user/{id}",
|
||||
; :data {:name :user/user-by-id},
|
||||
; :result nil,
|
||||
; :path-params {:id "123"},
|
||||
; :path "http://localhost:8080/api/user/123"}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@
|
|||
names (impl/find-names compiled-routes opts)
|
||||
[pl nl] (reduce
|
||||
(fn [[pl nl] [p {:keys [name] :as data} result]]
|
||||
(let [{:keys [path-params] :as route} (impl/parse p)
|
||||
(let [{:keys [path-params] :as route} (impl/parse p opts)
|
||||
f #(if-let [path (impl/path-for route %)]
|
||||
(->Match p data result (impl/url-decode-coll %) path)
|
||||
(->PartialMatch p data result (impl/url-decode-coll %) path-params))]
|
||||
|
|
@ -131,7 +131,7 @@
|
|||
([compiled-routes]
|
||||
(lookup-router compiled-routes {}))
|
||||
([compiled-routes opts]
|
||||
(when-let [wilds (seq (filter impl/wild-route? compiled-routes))]
|
||||
(when-let [wilds (seq (filter (impl/->wild-route? opts) compiled-routes))]
|
||||
(exception/fail!
|
||||
(str "can't create :lookup-router with wildcard routes: " wilds)
|
||||
{:wilds wilds
|
||||
|
|
@ -184,7 +184,7 @@
|
|||
names (impl/find-names compiled-routes opts)
|
||||
[pl nl] (reduce
|
||||
(fn [[pl nl] [p {:keys [name] :as data} result]]
|
||||
(let [{:keys [path-params] :as route} (impl/parse p)
|
||||
(let [{:keys [path-params] :as route} (impl/parse p opts)
|
||||
f #(if-let [path (impl/path-for route %)]
|
||||
(->Match p data result (impl/url-decode-coll %) path)
|
||||
(->PartialMatch p data result (impl/url-decode-coll %) path-params))]
|
||||
|
|
@ -227,7 +227,7 @@
|
|||
([compiled-routes]
|
||||
(single-static-path-router compiled-routes {}))
|
||||
([compiled-routes opts]
|
||||
(when (or (not= (count compiled-routes) 1) (some impl/wild-route? compiled-routes))
|
||||
(when (or (not= (count compiled-routes) 1) (some (impl/->wild-route? opts) compiled-routes))
|
||||
(exception/fail!
|
||||
(str ":single-static-path-router requires exactly 1 static route: " compiled-routes)
|
||||
{:routes compiled-routes}))
|
||||
|
|
@ -266,7 +266,7 @@
|
|||
([compiled-routes]
|
||||
(mixed-router compiled-routes {}))
|
||||
([compiled-routes opts]
|
||||
(let [{wild true, lookup false} (group-by impl/wild-route? compiled-routes)
|
||||
(let [{wild true, lookup false} (group-by (impl/->wild-route? opts) compiled-routes)
|
||||
->static-router (if (= 1 (count lookup)) single-static-path-router lookup-router)
|
||||
wildcard-router (trie-router wild opts)
|
||||
static-router (->static-router lookup opts)
|
||||
|
|
@ -301,7 +301,7 @@
|
|||
([compiled-routes]
|
||||
(quarantine-router compiled-routes {}))
|
||||
([compiled-routes opts]
|
||||
(let [conflicting-paths (-> compiled-routes impl/path-conflicting-routes impl/conflicting-paths)
|
||||
(let [conflicting-paths (-> compiled-routes (impl/path-conflicting-routes opts) impl/conflicting-paths)
|
||||
conflicting? #(contains? conflicting-paths (first %))
|
||||
{conflicting true, non-conflicting false} (group-by conflicting? compiled-routes)
|
||||
linear-router (linear-router conflicting opts)
|
||||
|
|
@ -347,12 +347,13 @@
|
|||
Selects implementation based on route details. The following options
|
||||
are available:
|
||||
|
||||
| key | description |
|
||||
| -------------|-------------|
|
||||
| key | description
|
||||
| -------------|-------------
|
||||
| `:path` | Base-path for routes
|
||||
| `:routes` | Initial resolved routes (default `[]`)
|
||||
| `:data` | Initial route data (default `{}`)
|
||||
| `:spec` | clojure.spec definition for a route data, see `reitit.spec` on how to use this
|
||||
| `:syntax` | Path-parameter syntax as keyword or set of keywords (default #{:bracket :colon})
|
||||
| `:expand` | Function of `arg opts => data` to expand route arg to route data (default `reitit.core/expand`)
|
||||
| `:coerce` | Function of `route opts => route` to coerce resolved route, can throw or return `nil`
|
||||
| `:compile` | Function of `route opts => result` to compile a route handler
|
||||
|
|
@ -366,11 +367,11 @@
|
|||
(let [{:keys [router] :as opts} (merge (default-router-options) opts)]
|
||||
(try
|
||||
(let [routes (impl/resolve-routes raw-routes opts)
|
||||
path-conflicting (impl/path-conflicting-routes routes)
|
||||
path-conflicting (impl/path-conflicting-routes routes opts)
|
||||
name-conflicting (impl/name-conflicting-routes routes)
|
||||
compiled-routes (impl/compile-routes routes opts)
|
||||
wilds? (boolean (some impl/wild-route? compiled-routes))
|
||||
all-wilds? (every? impl/wild-route? compiled-routes)
|
||||
wilds? (boolean (some (impl/->wild-route? opts) compiled-routes))
|
||||
all-wilds? (every? (impl/->wild-route? opts) compiled-routes)
|
||||
router (cond
|
||||
router router
|
||||
(and (= 1 (count compiled-routes)) (not wilds?)) single-static-path-router
|
||||
|
|
|
|||
|
|
@ -11,18 +11,19 @@
|
|||
(java.util HashMap Map)
|
||||
(java.net URLEncoder URLDecoder))))
|
||||
|
||||
(defrecord Route [path path-parts path-params])
|
||||
|
||||
(defn parse [path]
|
||||
(let [path #?(:clj (.intern ^String (trie/normalize path)) :cljs (trie/normalize path))
|
||||
path-parts (trie/split-path path)
|
||||
(defn parse [path opts]
|
||||
(let [path #?(:clj (.intern ^String (trie/normalize path opts)) :cljs (trie/normalize path opts))
|
||||
path-parts (trie/split-path path opts)
|
||||
path-params (->> path-parts (remove string?) (map :value) set)]
|
||||
(map->Route {:path-params path-params
|
||||
:path-parts path-parts
|
||||
:path path})))
|
||||
{:path-params path-params
|
||||
:path-parts path-parts
|
||||
:path path}))
|
||||
|
||||
(defn wild-route? [[path]]
|
||||
(-> path parse :path-params seq boolean))
|
||||
(defn wild-path? [path opts]
|
||||
(-> path (parse opts) :path-params seq boolean))
|
||||
|
||||
(defn ->wild-route? [opts]
|
||||
(fn [[path]] (-> path (parse opts) :path-params seq boolean)))
|
||||
|
||||
(defn maybe-map-values
|
||||
"Applies a function to every value of a map, updates the value if not nil.
|
||||
|
|
@ -74,14 +75,11 @@
|
|||
(cond->> (->> (walk raw-routes opts) (map-data merge-data))
|
||||
coerce (into [] (keep #(coerce % opts)))))
|
||||
|
||||
(defn conflicting-routes? [route1 route2]
|
||||
(trie/conflicting-paths? (first route1) (first route2)))
|
||||
|
||||
(defn path-conflicting-routes [routes]
|
||||
(defn path-conflicting-routes [routes opts]
|
||||
(-> (into {}
|
||||
(comp (map-indexed (fn [index route]
|
||||
[route (into #{}
|
||||
(filter (partial conflicting-routes? route))
|
||||
(filter #(trie/conflicting-paths? (first route) (first %) opts))
|
||||
(subvec routes (inc index)))]))
|
||||
(filter (comp seq second)))
|
||||
routes)
|
||||
|
|
@ -114,7 +112,7 @@
|
|||
(defn uncompile-routes [routes]
|
||||
(mapv (comp vec (partial take 2)) routes))
|
||||
|
||||
(defn path-for [^Route route path-params]
|
||||
(defn path-for [route path-params]
|
||||
(if (:path-params route)
|
||||
(if-let [parts (reduce
|
||||
(fn [acc part]
|
||||
|
|
|
|||
|
|
@ -5,6 +5,12 @@
|
|||
#?(:clj (:import [reitit Trie Trie$Match Trie$Matcher]
|
||||
(java.net URLDecoder))))
|
||||
|
||||
(defn ^:no-doc into-set [x]
|
||||
(cond
|
||||
(or (set? x) (sequential? x)) (set x)
|
||||
(nil? x) #{}
|
||||
:else (conj #{} x)))
|
||||
|
||||
(defrecord Wild [value])
|
||||
(defrecord CatchAll [value])
|
||||
(defrecord Match [params data])
|
||||
|
|
@ -51,25 +57,36 @@
|
|||
(keyword (subs s 0 i) (subs s (inc i)))
|
||||
(keyword s)))
|
||||
|
||||
(defn split-path [s]
|
||||
(let [-static (fn [from to] (if-not (= from to) [(subs s from to)]))
|
||||
(defn split-path [s {:keys [syntax] :or {syntax #{:bracket :colon}}}]
|
||||
(let [bracket? (-> syntax (into-set) :bracket)
|
||||
colon? (-> syntax (into-set) :colon)
|
||||
-static (fn [from to] (if-not (= from to) [(subs s from to)]))
|
||||
-wild (fn [from to] [(->Wild (-keyword (subs s (inc from) to)))])
|
||||
-catch-all (fn [from to] [(->CatchAll (keyword (subs s (inc from) to)))])]
|
||||
(loop [ss nil, from 0, to 0]
|
||||
(if (= to (count s))
|
||||
(concat ss (-static from to))
|
||||
(case (get s to)
|
||||
\{ (let [to' (or (str/index-of s "}" to) (ex/fail! ::unclosed-brackets {:path s}))]
|
||||
(if (= \* (get s (inc to)))
|
||||
(recur (concat ss (-static from to) (-catch-all (inc to) to')) (long (inc to')) (long (inc to')))
|
||||
(recur (concat ss (-static from to) (-wild to to')) (long (inc to')) (long (inc to')))))
|
||||
\: (let [to' (or (str/index-of s "/" to) (count s))]
|
||||
(if (= 1 (- to' to))
|
||||
(recur ss from (inc to))
|
||||
(recur (concat ss (-static from to) (-wild to to')) (long to') (long to'))))
|
||||
\* (let [to' (count s)]
|
||||
(recur (concat ss (-static from to) (-catch-all to to')) (long to') (long to')))
|
||||
(recur ss from (inc to)))))))
|
||||
(let [c (get s to)]
|
||||
(cond
|
||||
|
||||
(and bracket? (= \{ c))
|
||||
(let [to' (or (str/index-of s "}" to) (ex/fail! ::unclosed-brackets {:path s}))]
|
||||
(if (= \* (get s (inc to)))
|
||||
(recur (concat ss (-static from to) (-catch-all (inc to) to')) (long (inc to')) (long (inc to')))
|
||||
(recur (concat ss (-static from to) (-wild to to')) (long (inc to')) (long (inc to')))))
|
||||
|
||||
(and colon? (= \: c))
|
||||
(let [to' (or (str/index-of s "/" to) (count s))]
|
||||
(if (= 1 (- to' to))
|
||||
(recur ss from (inc to))
|
||||
(recur (concat ss (-static from to) (-wild to to')) (long to') (long to'))))
|
||||
|
||||
(and colon? (= \* c))
|
||||
(let [to' (count s)]
|
||||
(recur (concat ss (-static from to) (-catch-all to to')) (long to') (long to')))
|
||||
|
||||
:else
|
||||
(recur ss from (inc to))))))))
|
||||
|
||||
(defn join-path [xs]
|
||||
(reduce
|
||||
|
|
@ -80,8 +97,8 @@
|
|||
(instance? CatchAll x) (str "{*" (-> x :value str (subs 1)) "}"))))
|
||||
"" xs))
|
||||
|
||||
(defn normalize [s]
|
||||
(-> s (split-path) (join-path)))
|
||||
(defn normalize [s opts]
|
||||
(-> s (split-path opts) (join-path)))
|
||||
|
||||
;;
|
||||
;; Conflict Resolution
|
||||
|
|
@ -115,9 +132,9 @@
|
|||
(concat [(subs x i)] xs)
|
||||
xs)))
|
||||
|
||||
(defn conflicting-paths? [path1 path2]
|
||||
(loop [parts1 (split-path path1)
|
||||
parts2 (split-path path2)]
|
||||
(defn conflicting-paths? [path1 path2 opts]
|
||||
(loop [parts1 (split-path path1 opts)
|
||||
parts2 (split-path path2 opts)]
|
||||
(let [[[s1 & ss1] [s2 & ss2]] (-slice-start parts1 parts2)]
|
||||
(cond
|
||||
(= s1 s2 nil) true
|
||||
|
|
@ -314,10 +331,10 @@
|
|||
node routes))
|
||||
([node path data]
|
||||
(insert node path data nil))
|
||||
([node path data {::keys [parameters] :or {parameters map-parameters}}]
|
||||
(let [parts (split-path path)
|
||||
([node path data {::keys [parameters] :or {parameters map-parameters} :as opts}]
|
||||
(let [parts (split-path path opts)
|
||||
params (parameters (->> parts (remove string?) (map :value)))]
|
||||
(-insert (or node (-node {})) (split-path path) path params data))))
|
||||
(-insert (or node (-node {})) (split-path path opts) path params data))))
|
||||
|
||||
(defn compiler
|
||||
"Returns a default [[TrieCompiler]]."
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
(ns reitit.swagger
|
||||
(:require [reitit.core :as r]
|
||||
[reitit.impl :as impl]
|
||||
[meta-merge.core :refer [meta-merge]]
|
||||
[clojure.spec.alpha :as s]
|
||||
[clojure.set :as set]
|
||||
|
|
@ -65,8 +64,8 @@
|
|||
{:name ::swagger
|
||||
:spec ::spec})
|
||||
|
||||
(defn- swagger-path [path]
|
||||
(-> path trie/normalize (str/replace #"\{\*" "{")))
|
||||
(defn- swagger-path [path opts]
|
||||
(-> path (trie/normalize opts) (str/replace #"\{\*" "{")))
|
||||
|
||||
(defn create-swagger-handler []
|
||||
"Create a ring handler to emit swagger spec. Collects all routes from router which have
|
||||
|
|
@ -74,15 +73,14 @@
|
|||
(fn create-swagger
|
||||
([{:keys [::r/router ::r/match :request-method]}]
|
||||
(let [{:keys [id] :or {id ::default} :as swagger} (-> match :result request-method :data :swagger)
|
||||
->set (fn [x] (if (or (set? x) (sequential? x)) (set x) (conj #{} x)))
|
||||
ids (->set id)
|
||||
ids (trie/into-set id)
|
||||
strip-top-level-keys #(dissoc % :id :info :host :basePath :definitions :securityDefinitions)
|
||||
strip-endpoint-keys #(dissoc % :id :parameters :responses :summary :description)
|
||||
swagger (->> (strip-endpoint-keys swagger)
|
||||
(merge {:swagger "2.0"
|
||||
:x-id ids}))
|
||||
accept-route (fn [route]
|
||||
(-> route second :swagger :id (or ::default) ->set (set/intersection ids) seq))
|
||||
(-> route second :swagger :id (or ::default) (trie/into-set) (set/intersection ids) seq))
|
||||
transform-endpoint (fn [[method {{:keys [coercion no-doc swagger] :as data} :data
|
||||
middleware :middleware
|
||||
interceptors :interceptors}]]
|
||||
|
|
@ -97,7 +95,7 @@
|
|||
(strip-top-level-keys swagger))]))
|
||||
transform-path (fn [[p _ c]]
|
||||
(if-let [endpoint (some->> c (keep transform-endpoint) (seq) (into {}))]
|
||||
[(swagger-path p) endpoint]))]
|
||||
[(swagger-path p (r/options router)) endpoint]))]
|
||||
(let [map-in-order #(->> % (apply concat) (apply array-map))
|
||||
paths (->> router (r/compiled-routes) (filter accept-route) (map transform-path) map-in-order)]
|
||||
{:status 200
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@
|
|||
(let [routes (impl/resolve-routes data (r/default-router-options))
|
||||
conflicts (-> routes
|
||||
(impl/resolve-routes (r/default-router-options))
|
||||
(impl/path-conflicting-routes))]
|
||||
(impl/path-conflicting-routes nil))]
|
||||
(if conflicting? (seq conflicts) (nil? conflicts)))
|
||||
|
||||
true [["/a"]
|
||||
|
|
@ -328,7 +328,7 @@
|
|||
["/c" {}] #{["/*d" {}]}}
|
||||
(-> [["/a"] ["/:b"] ["/c"] ["/*d"]]
|
||||
(impl/resolve-routes (r/default-router-options))
|
||||
(impl/path-conflicting-routes)))))
|
||||
(impl/path-conflicting-routes nil)))))
|
||||
|
||||
(testing "router with conflicting routes"
|
||||
(testing "throws by default"
|
||||
|
|
|
|||
|
|
@ -2,27 +2,6 @@
|
|||
(:require [clojure.test :refer [deftest testing is are]]
|
||||
[reitit.impl :as impl]))
|
||||
|
||||
(deftest conflicting-route-test
|
||||
(are [c? p1 p2]
|
||||
(is (= c? (impl/conflicting-routes? [p1] [p2])))
|
||||
|
||||
true "/a" "/a"
|
||||
true "/a" "/:a"
|
||||
true "/a/:b" "/:a/b"
|
||||
true "/ab/:b" "/:a/ba"
|
||||
true "/*a" "/:a/ba/ca"
|
||||
|
||||
true "/a" "/{a}"
|
||||
true "/a/{b}" "/{a}/b"
|
||||
true "/ab/{b}" "/{a}/ba"
|
||||
true "/{*a}" "/{a}/ba/ca"
|
||||
|
||||
false "/a" "/:a/b"
|
||||
false "/a" "/:a/b"
|
||||
|
||||
false "/a" "/{a}/b"
|
||||
false "/a" "/{a}/b"))
|
||||
|
||||
(deftest strip-nils-test
|
||||
(is (= {:a 1, :c false} (impl/strip-nils {:a 1, :b nil, :c false}))))
|
||||
|
||||
|
|
@ -188,8 +167,7 @@
|
|||
"%2B632+905+123+4567" "+632 905 123 4567"))
|
||||
|
||||
(deftest parse-test
|
||||
(is (= (impl/map->Route
|
||||
{:path "https://google.com"
|
||||
:path-parts ["https://google.com"]
|
||||
:path-params #{}})
|
||||
(impl/parse "https://google.com"))))
|
||||
(is (= {:path "https://google.com"
|
||||
:path-parts ["https://google.com"]
|
||||
:path-params #{}}
|
||||
(impl/parse "https://google.com" nil))))
|
||||
|
|
|
|||
|
|
@ -2,16 +2,92 @@
|
|||
(:require [clojure.test :refer [deftest testing is are]]
|
||||
[reitit.trie :as trie]))
|
||||
|
||||
(deftest into-set-test
|
||||
(is (= #{} (trie/into-set nil)))
|
||||
(is (= #{} (trie/into-set [])))
|
||||
(is (= #{1} (trie/into-set 1)))
|
||||
(is (= #{1 2} (trie/into-set [1 2 1]))))
|
||||
|
||||
(deftest conflicting-paths?-test
|
||||
(are [c? p1 p2]
|
||||
(is (= c? (trie/conflicting-paths? p1 p2 nil)))
|
||||
|
||||
true "/a" "/a"
|
||||
true "/a" "/:a"
|
||||
true "/a/:b" "/:a/b"
|
||||
true "/ab/:b" "/:a/ba"
|
||||
true "/*a" "/:a/ba/ca"
|
||||
|
||||
true "/a" "/{a}"
|
||||
true "/a/{b}" "/{a}/b"
|
||||
true "/ab/{b}" "/{a}/ba"
|
||||
true "/{*a}" "/{a}/ba/ca"
|
||||
|
||||
false "/a" "/:a/b"
|
||||
false "/a" "/:a/b"
|
||||
|
||||
false "/a" "/{a}/b"
|
||||
false "/a" "/{a}/b"))
|
||||
|
||||
(deftest split-path-test
|
||||
(testing "colon"
|
||||
(doseq [syntax [:colon #{:colon}]]
|
||||
(are [path expected]
|
||||
(is (= expected (trie/split-path path {:syntax syntax})))
|
||||
|
||||
"/olipa/:kerran/avaruus", ["/olipa/" (trie/->Wild :kerran) "/avaruus"]
|
||||
"/olipa/{kerran}/avaruus", ["/olipa/{kerran}/avaruus"]
|
||||
"/olipa/{a.b/c}/avaruus", ["/olipa/{a.b/c}/avaruus"]
|
||||
"/olipa/kerran/*avaruus", ["/olipa/kerran/" (trie/->CatchAll :avaruus)]
|
||||
"/olipa/kerran/{*avaruus}", ["/olipa/kerran/{" (trie/->CatchAll (keyword "avaruus}"))]
|
||||
"/olipa/kerran/{*valtavan.suuri/avaruus}", ["/olipa/kerran/{" (trie/->CatchAll (keyword "valtavan.suuri/avaruus}"))])))
|
||||
|
||||
(testing "bracket"
|
||||
(doseq [syntax [:bracket #{:bracket}]]
|
||||
(are [path expected]
|
||||
(is (= expected (trie/split-path path {:syntax syntax})))
|
||||
|
||||
"/olipa/:kerran/avaruus", ["/olipa/:kerran/avaruus"]
|
||||
"/olipa/{kerran}/avaruus", ["/olipa/" (trie/->Wild :kerran) "/avaruus"]
|
||||
"/olipa/{a.b/c}/avaruus", ["/olipa/" (trie/->Wild :a.b/c) "/avaruus"]
|
||||
"/olipa/kerran/*avaruus", ["/olipa/kerran/*avaruus"]
|
||||
"/olipa/kerran/{*avaruus}", ["/olipa/kerran/" (trie/->CatchAll :avaruus)]
|
||||
"/olipa/kerran/{*valtavan.suuri/avaruus}", ["/olipa/kerran/" (trie/->CatchAll :valtavan.suuri/avaruus)])))
|
||||
|
||||
(testing "both"
|
||||
(doseq [syntax [#{:bracket :colon}]]
|
||||
(are [path expected]
|
||||
(is (= expected (trie/split-path path {:syntax syntax})))
|
||||
|
||||
"/olipa/:kerran/avaruus", ["/olipa/" (trie/->Wild :kerran) "/avaruus"]
|
||||
"/olipa/{kerran}/avaruus", ["/olipa/" (trie/->Wild :kerran) "/avaruus"]
|
||||
"/olipa/{a.b/c}/avaruus", ["/olipa/" (trie/->Wild :a.b/c) "/avaruus"]
|
||||
"/olipa/kerran/*avaruus", ["/olipa/kerran/" (trie/->CatchAll :avaruus)]
|
||||
"/olipa/kerran/{*avaruus}", ["/olipa/kerran/" (trie/->CatchAll :avaruus)]
|
||||
"/olipa/kerran/{*valtavan.suuri/avaruus}", ["/olipa/kerran/" (trie/->CatchAll :valtavan.suuri/avaruus)])))
|
||||
|
||||
(testing "nil"
|
||||
(doseq [syntax [nil]]
|
||||
(are [path expected]
|
||||
(is (= expected (trie/split-path path {:syntax syntax})))
|
||||
|
||||
"/olipa/:kerran/avaruus", ["/olipa/:kerran/avaruus"]
|
||||
"/olipa/{kerran}/avaruus", ["/olipa/{kerran}/avaruus"]
|
||||
"/olipa/{a.b/c}/avaruus", ["/olipa/{a.b/c}/avaruus"]
|
||||
"/olipa/kerran/*avaruus", ["/olipa/kerran/*avaruus"]
|
||||
"/olipa/kerran/{*avaruus}", ["/olipa/kerran/{*avaruus}"]
|
||||
"/olipa/kerran/{*valtavan.suuri/avaruus}", ["/olipa/kerran/{*valtavan.suuri/avaruus}"]))))
|
||||
|
||||
(deftest normalize-test
|
||||
(are [path expected]
|
||||
(is (= expected (trie/normalize path)))
|
||||
(is (= expected (trie/normalize path nil)))
|
||||
|
||||
"/olipa/:kerran/avaruus", "/olipa/{kerran}/avaruus"
|
||||
"/olipa/{kerran}/avaruus", "/olipa/{kerran}/avaruus"
|
||||
"/olipa/{a.b/c}/avaruus", "/olipa/{a.b/c}/avaruus"
|
||||
"/olipa/kerran/*avaruus", "/olipa/kerran/{*avaruus}"
|
||||
"/olipa/kerran/{*avaruus}", "/olipa/kerran/{*avaruus}"
|
||||
"/olipa/kerran/{*valvavan.suuri/avaruus}", "/olipa/kerran/{*valvavan.suuri/avaruus}"))
|
||||
"/olipa/kerran/{*valtavan.suuri/avaruus}", "/olipa/kerran/{*valtavan.suuri/avaruus}"))
|
||||
|
||||
(deftest tests
|
||||
(is (= (trie/->Match {} {:a 1})
|
||||
|
|
|
|||
Loading…
Reference in a new issue