quarantine-router

This commit is contained in:
Tommi Reiman 2018-12-22 10:37:18 +02:00
parent c39122250f
commit 48961c9ed4
4 changed files with 60 additions and 3 deletions

View file

@ -4,6 +4,18 @@
* `segment-router` doesn't accept empty segments as path-parameters, fixes [#181](https://github.com/metosin/reitit/issues/181).
* path-params are decoded correctly with `r/match-by-name`, fixes [#192](https://github.com/metosin/reitit/issues/192).
* new `:quarantine-router`, which is uses by default if there are any path conflicts: uses internally `:mixed-router` for non-conflicting routes and `:linear-router` for conflicting routes.
```clj
(-> [["/joulu/kinkku"] ;; linear router
["/joulu/:torttu"] ;; linear router
["/tonttu/:id"] ;; segment-router
["/manna/puuro"] ;; lookup-router
["/sinappi/silli"]] ;; lookup-router
(r/router {:conflicts nil})
(r/router-name))
; => :quarantine-router
```
* updated deps:

View file

@ -9,6 +9,7 @@ Reitit ships with several different implementations for the `Router` protocol, o
| `:lookup-router` | Fast router, uses hash-lookup to resolve the route. Valid if no paths have path or catch-all parameters and there are no [Route conflicts](../basics/route_conflicts.md).
| `:single-static-path-router` | Super fast router: string-matches a route. Valid only if there is one static route.
| `:mixed-router` | Contains two routers: `:segment-router` for wildcard routes and a `:lookup-router` or `:single-static-path-router` for static routes. Valid only if there are no [Route conflicts](../basics/route_conflicts.md).
| `:quarantine-router` | Contains two routers: `:mixed-router` for non-conflicting routes and a `:linear-router` for conflicting routes.
The router name can be asked from the router:

View file

@ -77,6 +77,12 @@
(seq)
(into {})))
(defn conflicting-paths [conflicts]
(->> (for [[p pc] conflicts]
(conj (map first pc) (first p)))
(apply concat)
(set)))
(defn path-conflicts-str [conflicts]
(apply str "Router contains conflicting route paths:\n\n"
(mapv
@ -373,6 +379,42 @@
(or (match-by-name static-router name path-params)
(match-by-name wildcard-router name path-params)))))))
(defn quarantine-router
"Creates two routers: [[mixed-router]] for non-conflicting routes
and [[linear-router]] for conflicting routes. Takes resolved routes
and optional expanded options. See [[router]] for options."
([compiled-routes]
(quarantine-router compiled-routes {}))
([compiled-routes opts]
(let [conflicting-paths (-> compiled-routes path-conflicting-routes conflicting-paths)
conflicting? #(contains? conflicting-paths (first %))
{conflicting true, non-conflicting false} (group-by conflicting? compiled-routes)
linear-router (linear-router conflicting opts)
mixed-router (mixed-router non-conflicting opts)
names (find-names compiled-routes opts)
routes (uncompile-routes compiled-routes)]
^{:type ::router}
(reify Router
(router-name [_]
:quarantine-router)
(routes [_]
routes)
(compiled-routes [_]
compiled-routes)
(options [_]
opts)
(route-names [_]
names)
(match-by-path [_ path]
(or (match-by-path mixed-router path)
(match-by-path linear-router path)))
(match-by-name [_ name]
(or (match-by-name mixed-router name)
(match-by-name linear-router name)))
(match-by-name [_ name path-params]
(or (match-by-name mixed-router name path-params)
(match-by-name linear-router name path-params)))))))
(defn router
"Create a [[Router]] from raw route data and optionally an options map.
Selects implementation based on route details. The following options
@ -403,7 +445,7 @@
router (cond
router router
(and (= 1 (count compiled-routes)) (not wilds?)) single-static-path-router
path-conflicting linear-router
path-conflicting quarantine-router
(not wilds?) lookup-router
all-wilds? segment-router
:else mixed-router)]

View file

@ -98,7 +98,8 @@
r/linear-router :linear-router
r/segment-router :segment-router
r/mixed-router :mixed-router))
r/mixed-router :mixed-router
r/quarantine-router :quarantine-router))
(testing "routers handling static paths"
(are [r name]
@ -134,7 +135,8 @@
r/single-static-path-router :single-static-path-router
r/linear-router :linear-router
r/segment-router :segment-router
r/mixed-router :mixed-router))
r/mixed-router :mixed-router
r/quarantine-router :quarantine-router))
(testing "nil routes are stripped"
(is (= [] (r/routes (r/router nil))))