mirror of
https://github.com/metosin/reitit.git
synced 2025-12-16 16:01:11 +00:00
Better handling of nil in routing
This commit is contained in:
parent
56203ba11d
commit
7a544cd52d
5 changed files with 43 additions and 28 deletions
11
CHANGELOG.md
11
CHANGELOG.md
|
|
@ -2,14 +2,17 @@
|
|||
|
||||
### `reitit-core`
|
||||
|
||||
* Better handling of `nil` routes - they filtered away from route syntax before routes are expanded:
|
||||
* Better handling of `nil` in route syntax:
|
||||
* explicit `nil` after path string is always handled as `nil` route
|
||||
* `nil` as path string causes the whole route to be `nil`
|
||||
* `nil` as child route is stripped away
|
||||
|
||||
```clj
|
||||
(testing "nil routes are allowed ans stripped"
|
||||
(testing "nil routes are stripped"
|
||||
(is (= [] (r/routes (r/router nil))))
|
||||
(is (= [] (r/routes (r/router [nil ["/ping"]]))))
|
||||
(is (= [] (r/routes (r/router [nil [nil] [[nil nil nil]]]))))
|
||||
(is (= [["/ping" {} nil]] (r/routes (r/router [nil [nil] ["/ping"]]))))
|
||||
(is (= [["/ping" {} nil]] (r/routes (r/router [[[nil [nil] ["/ping"]]]])))))
|
||||
(is (= [] (r/routes (r/router ["/ping" [nil "/pong"]])))))
|
||||
```
|
||||
|
||||
### `reitit-schema`
|
||||
|
|
|
|||
|
|
@ -37,17 +37,16 @@
|
|||
[(walk-many [p m r]
|
||||
(reduce #(into %1 (walk-one p m %2)) [] r))
|
||||
(walk-one [pacc macc routes]
|
||||
(if-let [routes (seq (keep identity routes))]
|
||||
(if (vector? (first routes))
|
||||
(walk-many pacc macc routes)
|
||||
(if (vector? (first routes))
|
||||
(walk-many pacc macc routes)
|
||||
(if (string? (first routes))
|
||||
(let [[path & [maybe-arg :as args]] routes
|
||||
[data childs] (if (vector? maybe-arg)
|
||||
[data childs] (if (or (vector? maybe-arg) (nil? maybe-arg))
|
||||
[{} args]
|
||||
[maybe-arg (rest args)])
|
||||
macc (into macc (expand data opts))]
|
||||
(if (seq childs)
|
||||
(walk-many (str pacc path) macc childs)
|
||||
[[(str pacc path) macc]])))))]
|
||||
macc (into macc (expand data opts))
|
||||
child-routes (walk-many (str pacc path) macc (keep identity childs))]
|
||||
(if (seq childs) (seq child-routes) [[(str pacc path) macc]])))))]
|
||||
(walk-one path (mapv identity data) raw-routes)))
|
||||
|
||||
(defn map-data [f routes]
|
||||
|
|
|
|||
|
|
@ -9,18 +9,19 @@
|
|||
|
||||
(s/def ::path (s/with-gen string? #(gen/fmap (fn [s] (str "/" s)) (s/gen string?))))
|
||||
|
||||
(s/def ::arg (s/and any? (complement vector?)))
|
||||
(s/def ::arg (s/and some? (complement vector?)))
|
||||
(s/def ::data (s/map-of keyword? any?))
|
||||
(s/def ::result any?)
|
||||
|
||||
(s/def ::raw-route
|
||||
(s/cat :path ::path
|
||||
:arg (s/? ::arg)
|
||||
:childs (s/* (s/and (s/nilable ::raw-route)))))
|
||||
(s/nilable
|
||||
(s/cat :path ::path
|
||||
:arg (s/? ::arg)
|
||||
:childs (s/* (s/and (s/nilable ::raw-routes))))))
|
||||
|
||||
(s/def ::raw-routes
|
||||
(s/or :route ::raw-route
|
||||
:routes (s/coll-of ::raw-route :into [])))
|
||||
:routes (s/coll-of ::raw-routes :into [])))
|
||||
|
||||
(s/def ::route
|
||||
(s/cat :path ::path
|
||||
|
|
|
|||
|
|
@ -108,11 +108,11 @@
|
|||
r/segment-router :segment-router
|
||||
r/mixed-router :mixed-router))
|
||||
|
||||
(testing "nil routes are allowed ans stripped"
|
||||
(testing "nil routes are stripped"
|
||||
(is (= [] (r/routes (r/router nil))))
|
||||
(is (= [] (r/routes (r/router [nil ["/ping"]]))))
|
||||
(is (= [] (r/routes (r/router [nil [nil] [[nil nil nil]]]))))
|
||||
(is (= [["/ping" {} nil]] (r/routes (r/router [nil [nil] ["/ping"]]))))
|
||||
(is (= [["/ping" {} nil]] (r/routes (r/router [[[nil [nil] ["/ping"]]]])))))
|
||||
(is (= [] (r/routes (r/router ["/ping" [nil "/pong"]])))))
|
||||
|
||||
(testing "route coercion & compilation"
|
||||
|
||||
|
|
@ -246,3 +246,9 @@
|
|||
[["/a"] ["/a"]]))))
|
||||
(testing "can be configured to ignore"
|
||||
(is (not (nil? (r/router [["/a"] ["/a"]] {:conflicts (constantly nil)})))))))
|
||||
|
||||
(testing "nil routes are stripped"
|
||||
(is (= [] (r/routes (r/router nil))))
|
||||
(is (= [] (r/routes (r/router [nil ["/ping"]]))))
|
||||
(is (= [] (r/routes (r/router [nil [nil] [[nil nil nil]]]))))
|
||||
(is (= [] (r/routes (r/router ["/ping" [nil "/pong"]])))))
|
||||
|
|
|
|||
|
|
@ -1,14 +1,20 @@
|
|||
(ns reitit.spec-test
|
||||
(:require [clojure.test :refer [deftest testing is are]]
|
||||
(:require [clojure.test :refer [deftest testing is are use-fixtures]]
|
||||
[#?(:clj clojure.spec.test.alpha :cljs cljs.spec.test.alpha) :as stest]
|
||||
[clojure.spec.alpha :as s]
|
||||
[reitit.core :as r]
|
||||
[reitit.spec :as rs]
|
||||
[expound.alpha :as e])
|
||||
[reitit.spec :as rs])
|
||||
#?(:clj
|
||||
(:import (clojure.lang ExceptionInfo))))
|
||||
|
||||
(stest/instrument)
|
||||
(defn instrument-all [f]
|
||||
(try
|
||||
(stest/instrument)
|
||||
(f)
|
||||
(finally
|
||||
(stest/unstrument))))
|
||||
|
||||
(use-fixtures :each instrument-all)
|
||||
|
||||
(deftest router-spec-test
|
||||
|
||||
|
|
@ -40,9 +46,9 @@
|
|||
;; path
|
||||
[:invalid {}]
|
||||
|
||||
;; vector data
|
||||
["/api" []
|
||||
["/ipa"]])))
|
||||
;; nested path
|
||||
["/api"
|
||||
[:ipa]])))
|
||||
|
||||
(testing "routes conform to spec (can't spec protocol functions)"
|
||||
(is (s/valid? ::rs/routes (r/routes (r/router ["/ping"])))))
|
||||
|
|
@ -60,7 +66,7 @@
|
|||
{:conflicts (fn [_])}
|
||||
{:router r/linear-router})
|
||||
|
||||
(are [opts]
|
||||
#_(are [opts]
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Call to #'reitit.core/router did not conform to spec"
|
||||
|
|
|
|||
Loading…
Reference in a new issue