mirror of
https://github.com/metosin/reitit.git
synced 2026-01-24 15:19:01 +00:00
Use exception/fail! in all creation-time exceptions
... to be companioned with a slick error printer
This commit is contained in:
parent
ad92c437e6
commit
950fef88d2
9 changed files with 63 additions and 68 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
(ns reitit.core
|
(ns reitit.core
|
||||||
(:require [clojure.string :as str]
|
(:require [clojure.string :as str]
|
||||||
[reitit.impl :as impl]
|
[reitit.impl :as impl]
|
||||||
|
[reitit.exception :as exception]
|
||||||
[reitit.trie :as trie]))
|
[reitit.trie :as trie]))
|
||||||
|
|
||||||
;;
|
;;
|
||||||
|
|
@ -50,10 +51,7 @@
|
||||||
conflicts)))
|
conflicts)))
|
||||||
|
|
||||||
(defn throw-on-conflicts! [f conflicts]
|
(defn throw-on-conflicts! [f conflicts]
|
||||||
(throw
|
(exception/fail! (f conflicts) {:conflicts conflicts}))
|
||||||
(ex-info
|
|
||||||
(f conflicts)
|
|
||||||
{:conflicts conflicts})))
|
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;; Router
|
;; Router
|
||||||
|
|
@ -149,11 +147,10 @@
|
||||||
(lookup-router compiled-routes {}))
|
(lookup-router compiled-routes {}))
|
||||||
([compiled-routes opts]
|
([compiled-routes opts]
|
||||||
(when-let [wilds (seq (filter impl/wild-route? compiled-routes))]
|
(when-let [wilds (seq (filter impl/wild-route? compiled-routes))]
|
||||||
(throw
|
(exception/fail!
|
||||||
(ex-info
|
(str "can't create :lookup-router with wildcard routes: " wilds)
|
||||||
(str "can't create :lookup-router with wildcard routes: " wilds)
|
{:wilds wilds
|
||||||
{:wilds wilds
|
:routes compiled-routes}))
|
||||||
:routes compiled-routes})))
|
|
||||||
(let [names (impl/find-names compiled-routes opts)
|
(let [names (impl/find-names compiled-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]]
|
||||||
|
|
@ -239,10 +236,9 @@
|
||||||
(single-static-path-router compiled-routes {}))
|
(single-static-path-router compiled-routes {}))
|
||||||
([compiled-routes opts]
|
([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? compiled-routes))
|
||||||
(throw
|
(exception/fail!
|
||||||
(ex-info
|
(str ":single-static-path-router requires exactly 1 static route: " compiled-routes)
|
||||||
(str ":single-static-path-router requires exactly 1 static route: " compiled-routes)
|
{:routes compiled-routes}))
|
||||||
{:routes compiled-routes})))
|
|
||||||
(let [[n :as names] (impl/find-names compiled-routes opts)
|
(let [[n :as names] (impl/find-names compiled-routes opts)
|
||||||
[[p data result]] compiled-routes
|
[[p data result]] compiled-routes
|
||||||
p #?(:clj (.intern ^String p) :cljs p)
|
p #?(:clj (.intern ^String p) :cljs p)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
(ns reitit.dependency
|
(ns reitit.dependency
|
||||||
"Dependency resolution for middleware/interceptors.")
|
"Dependency resolution for middleware/interceptors."
|
||||||
|
(:require [reitit.exception :as exception]))
|
||||||
|
|
||||||
(defn- providers
|
(defn- providers
|
||||||
"Map from provision key to provider. `get-provides` should return the provision keys of a dependent."
|
"Map from provision key to provider. `get-provides` should return the provision keys of a dependent."
|
||||||
|
|
@ -8,8 +9,9 @@
|
||||||
(into acc
|
(into acc
|
||||||
(map (fn [provide]
|
(map (fn [provide]
|
||||||
(when (contains? acc provide)
|
(when (contains? acc provide)
|
||||||
(throw (ex-info (str "multiple providers for: " provide)
|
(exception/fail!
|
||||||
{::multiple-providers provide})))
|
(str "multiple providers for: " provide)
|
||||||
|
{::multiple-providers provide}))
|
||||||
[provide dependent]))
|
[provide dependent]))
|
||||||
(get-provides dependent)))
|
(get-provides dependent)))
|
||||||
{} nodes))
|
{} nodes))
|
||||||
|
|
@ -19,8 +21,9 @@
|
||||||
[providers k]
|
[providers k]
|
||||||
(if (contains? providers k)
|
(if (contains? providers k)
|
||||||
(get providers k)
|
(get providers k)
|
||||||
(throw (ex-info (str "provider missing for dependency: " k)
|
(exception/fail!
|
||||||
{::missing-provider k}))))
|
(str "provider missing for dependency: " k)
|
||||||
|
{::missing-provider k})))
|
||||||
|
|
||||||
(defn post-order
|
(defn post-order
|
||||||
"Put `nodes` in post-order. Can also be described as a reverse topological sort.
|
"Put `nodes` in post-order. Can also be described as a reverse topological sort.
|
||||||
|
|
@ -37,8 +40,7 @@
|
||||||
(assoc colors node :grey))]
|
(assoc colors node :grey))]
|
||||||
[(conj nodes* node)
|
[(conj nodes* node)
|
||||||
(assoc colors node :black)])
|
(assoc colors node :black)])
|
||||||
:grey (throw (ex-info "circular dependency"
|
:grey (exception/fail! "circular dependency" {:cycle (drop-while #(not= % node) (conj path node))})
|
||||||
{:cycle (drop-while #(not= % node) (conj path node))}))
|
|
||||||
:black [() colors]))
|
:black [() colors]))
|
||||||
|
|
||||||
(toposort-seq [nodes path colors]
|
(toposort-seq [nodes path colors]
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,6 @@
|
||||||
|
|
||||||
(defn fail!
|
(defn fail!
|
||||||
([message]
|
([message]
|
||||||
(throw (ex-info message {:type ::exeption})))
|
(throw (ex-info message {::type :exeption})))
|
||||||
([message data]
|
([message data]
|
||||||
(throw (ex-info message (assoc data :type ::exeption)))))
|
(throw (ex-info message (merge {::type ::exeption} data)))))
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@
|
||||||
(:require [clojure.string :as str]
|
(:require [clojure.string :as str]
|
||||||
[clojure.set :as set]
|
[clojure.set :as set]
|
||||||
[meta-merge.core :as mm]
|
[meta-merge.core :as mm]
|
||||||
[reitit.trie :as trie])
|
[reitit.trie :as trie]
|
||||||
|
[reitit.exception :as exception])
|
||||||
#?(:clj
|
#?(:clj
|
||||||
(:import (java.util.regex Pattern)
|
(:import (java.util.regex Pattern)
|
||||||
(java.util HashMap Map)
|
(java.util HashMap Map)
|
||||||
|
|
@ -126,10 +127,9 @@
|
||||||
(when-not (every? #(contains? path-params %) required)
|
(when-not (every? #(contains? path-params %) required)
|
||||||
(let [defined (-> path-params keys set)
|
(let [defined (-> path-params keys set)
|
||||||
missing (set/difference required defined)]
|
missing (set/difference required defined)]
|
||||||
(throw
|
(exception/fail!
|
||||||
(ex-info
|
(str "missing path-params for route " template " -> " missing)
|
||||||
(str "missing path-params for route " template " -> " missing)
|
{:path-params path-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)]
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
(:require [meta-merge.core :refer [meta-merge]]
|
(:require [meta-merge.core :refer [meta-merge]]
|
||||||
[clojure.pprint :as pprint]
|
[clojure.pprint :as pprint]
|
||||||
[reitit.core :as r]
|
[reitit.core :as r]
|
||||||
[reitit.impl :as impl]))
|
[reitit.impl :as impl]
|
||||||
|
[reitit.exception :as exception]))
|
||||||
|
|
||||||
(defprotocol IntoInterceptor
|
(defprotocol IntoInterceptor
|
||||||
(into-interceptor [this data opts]))
|
(into-interceptor [this data opts]))
|
||||||
|
|
@ -33,10 +34,9 @@
|
||||||
#?(:clj clojure.lang.Keyword
|
#?(:clj clojure.lang.Keyword
|
||||||
:cljs cljs.core.Keyword)
|
:cljs cljs.core.Keyword)
|
||||||
(into-interceptor [this data {:keys [::registry] :as opts}]
|
(into-interceptor [this data {:keys [::registry] :as opts}]
|
||||||
(if-let [interceptor (if registry (registry this))]
|
(or (if-let [interceptor (if registry (registry this))]
|
||||||
(into-interceptor interceptor data opts)
|
(into-interceptor interceptor data opts))
|
||||||
(throw
|
(exception/fail!
|
||||||
(ex-info
|
|
||||||
(str
|
(str
|
||||||
"Interceptor " this " not found in registry.\n\n"
|
"Interceptor " this " not found in registry.\n\n"
|
||||||
(if (seq registry)
|
(if (seq registry)
|
||||||
|
|
@ -46,16 +46,15 @@
|
||||||
(pprint/print-table [:id :description] (for [[k v] registry] {:id k :description v}))))
|
(pprint/print-table [:id :description] (for [[k v] registry] {:id k :description v}))))
|
||||||
"see [reitit.interceptor/router] on how to add interceptor to the registry.\n") "\n")
|
"see [reitit.interceptor/router] on how to add interceptor to the registry.\n") "\n")
|
||||||
{:id this
|
{:id this
|
||||||
:registry registry}))))
|
:registry registry})))
|
||||||
|
|
||||||
#?(:clj clojure.lang.APersistentVector
|
#?(:clj clojure.lang.APersistentVector
|
||||||
:cljs cljs.core.PersistentVector)
|
:cljs cljs.core.PersistentVector)
|
||||||
(into-interceptor [[f & args :as form] data opts]
|
(into-interceptor [[f & args :as form] data opts]
|
||||||
(when (and (seq args) (not (fn? f)))
|
(when (and (seq args) (not (fn? f)))
|
||||||
(throw
|
(exception/fail!
|
||||||
(ex-info
|
(str "Invalid Interceptor form: " form "")
|
||||||
(str "Invalid Interceptor form: " form "")
|
{:form form}))
|
||||||
{:form form})))
|
|
||||||
(into-interceptor (apply f args) data opts))
|
(into-interceptor (apply f args) data opts))
|
||||||
|
|
||||||
#?(:clj clojure.lang.Fn
|
#?(:clj clojure.lang.Fn
|
||||||
|
|
@ -85,10 +84,9 @@
|
||||||
(let [compiled (::compiled opts 0)
|
(let [compiled (::compiled opts 0)
|
||||||
opts (assoc opts ::compiled (inc ^long compiled))]
|
opts (assoc opts ::compiled (inc ^long compiled))]
|
||||||
(when (>= ^long compiled ^long *max-compile-depth*)
|
(when (>= ^long compiled ^long *max-compile-depth*)
|
||||||
(throw
|
(exception/fail!
|
||||||
(ex-info
|
(str "Too deep Interceptor compilation - " compiled)
|
||||||
(str "Too deep Interceptor compilation - " compiled)
|
{:this this, :data data, :opts opts}))
|
||||||
{:this this, :data data, :opts opts})))
|
|
||||||
(if-let [interceptor (into-interceptor (compile data opts) data opts)]
|
(if-let [interceptor (into-interceptor (compile data opts) data opts)]
|
||||||
(map->Interceptor
|
(map->Interceptor
|
||||||
(merge
|
(merge
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
(:require [meta-merge.core :refer [meta-merge]]
|
(:require [meta-merge.core :refer [meta-merge]]
|
||||||
[clojure.pprint :as pprint]
|
[clojure.pprint :as pprint]
|
||||||
[reitit.core :as r]
|
[reitit.core :as r]
|
||||||
[reitit.impl :as impl]))
|
[reitit.impl :as impl]
|
||||||
|
[reitit.exception :as exception]))
|
||||||
|
|
||||||
(defprotocol IntoMiddleware
|
(defprotocol IntoMiddleware
|
||||||
(into-middleware [this data opts]))
|
(into-middleware [this data opts]))
|
||||||
|
|
@ -17,10 +18,9 @@
|
||||||
#?(:clj clojure.lang.Keyword
|
#?(:clj clojure.lang.Keyword
|
||||||
:cljs cljs.core.Keyword)
|
:cljs cljs.core.Keyword)
|
||||||
(into-middleware [this data {:keys [::registry] :as opts}]
|
(into-middleware [this data {:keys [::registry] :as opts}]
|
||||||
(if-let [middleware (if registry (registry this))]
|
(or (if-let [middleware (if registry (registry this))]
|
||||||
(into-middleware middleware data opts)
|
(into-middleware middleware data opts))
|
||||||
(throw
|
(exception/fail!
|
||||||
(ex-info
|
|
||||||
(str
|
(str
|
||||||
"Middleware " this " not found in registry.\n\n"
|
"Middleware " this " not found in registry.\n\n"
|
||||||
(if (seq registry)
|
(if (seq registry)
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
(pprint/print-table [:id :description] (for [[k v] registry] {:id k :description v}))))
|
(pprint/print-table [:id :description] (for [[k v] registry] {:id k :description v}))))
|
||||||
"see [reitit.middleware/router] on how to add middleware to the registry.\n") "\n")
|
"see [reitit.middleware/router] on how to add middleware to the registry.\n") "\n")
|
||||||
{:id this
|
{:id this
|
||||||
:registry registry}))))
|
:registry registry})))
|
||||||
|
|
||||||
#?(:clj clojure.lang.APersistentVector
|
#?(:clj clojure.lang.APersistentVector
|
||||||
:cljs cljs.core.PersistentVector)
|
:cljs cljs.core.PersistentVector)
|
||||||
|
|
@ -61,10 +61,9 @@
|
||||||
(let [compiled (::compiled opts 0)
|
(let [compiled (::compiled opts 0)
|
||||||
opts (assoc opts ::compiled (inc ^long compiled))]
|
opts (assoc opts ::compiled (inc ^long compiled))]
|
||||||
(when (>= ^long compiled ^long *max-compile-depth*)
|
(when (>= ^long compiled ^long *max-compile-depth*)
|
||||||
(throw
|
(exception/fail!
|
||||||
(ex-info
|
(str "Too deep Middleware compilation - " compiled)
|
||||||
(str "Too deep Middleware compilation - " compiled)
|
{:this this, :data data, :opts opts}))
|
||||||
{:this this, :data data, :opts opts})))
|
|
||||||
(if-let [middeware (into-middleware (compile data opts) data opts)]
|
(if-let [middeware (into-middleware (compile data opts) data opts)]
|
||||||
(map->Middleware
|
(map->Middleware
|
||||||
(merge
|
(merge
|
||||||
|
|
@ -76,11 +75,11 @@
|
||||||
|
|
||||||
(defn- ensure-handler! [path data scope]
|
(defn- ensure-handler! [path data scope]
|
||||||
(when-not (:handler data)
|
(when-not (:handler data)
|
||||||
(throw (ex-info
|
(exception/fail!
|
||||||
(str "path \"" path "\" doesn't have a :handler defined"
|
(str "path \"" path "\" doesn't have a :handler defined"
|
||||||
(if scope (str " for " scope)))
|
(if scope (str " for " scope)))
|
||||||
(merge {:path path, :data data}
|
(merge {:path path, :data data}
|
||||||
(if scope {:scope scope}))))))
|
(if scope {:scope scope})))))
|
||||||
|
|
||||||
(defn- expand-and-transform
|
(defn- expand-and-transform
|
||||||
[middleware data {:keys [::transform] :or {transform identity} :as opts}]
|
[middleware data {:keys [::transform] :or {transform identity} :as opts}]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
(ns reitit.spec
|
(ns reitit.spec
|
||||||
(:require [clojure.spec.alpha :as s]
|
(:require [clojure.spec.alpha :as s]
|
||||||
[clojure.spec.gen.alpha :as gen]
|
[clojure.spec.gen.alpha :as gen]
|
||||||
[reitit.core :as reitit]))
|
[reitit.core :as reitit]
|
||||||
|
[reitit.exception :as exception]))
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;; routes
|
;; routes
|
||||||
|
|
@ -119,10 +120,9 @@
|
||||||
problems)))
|
problems)))
|
||||||
|
|
||||||
(defn throw-on-problems! [problems explain]
|
(defn throw-on-problems! [problems explain]
|
||||||
(throw
|
(exception/fail!
|
||||||
(ex-info
|
(problems-str problems explain)
|
||||||
(problems-str problems explain)
|
{:problems problems}))
|
||||||
{:problems problems})))
|
|
||||||
|
|
||||||
(defn validate-route-data [routes spec]
|
(defn validate-route-data [routes spec]
|
||||||
(->> (for [[p d _] routes]
|
(->> (for [[p d _] routes]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
(ns reitit.ring.spec
|
(ns reitit.ring.spec
|
||||||
(:require [clojure.spec.alpha :as s]
|
(:require [clojure.spec.alpha :as s]
|
||||||
[reitit.middleware :as middleware]
|
[reitit.middleware :as middleware]
|
||||||
[reitit.spec :as rs]))
|
[reitit.spec :as rs]
|
||||||
|
[reitit.exception :as exception]))
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;; Specs
|
;; Specs
|
||||||
|
|
@ -19,11 +20,10 @@
|
||||||
|
|
||||||
(defn merge-specs [specs]
|
(defn merge-specs [specs]
|
||||||
(when-let [non-specs (seq (remove #(or (s/spec? %) (s/get-spec %)) specs))]
|
(when-let [non-specs (seq (remove #(or (s/spec? %) (s/get-spec %)) specs))]
|
||||||
(throw
|
(exception/fail!
|
||||||
(ex-info
|
(str "Not all specs satisfy the Spec protocol: " non-specs)
|
||||||
(str "Not all specs satisfy the Spec protocol: " non-specs)
|
{:specs specs
|
||||||
{:specs specs
|
:non-specs non-specs}))
|
||||||
:non-specs non-specs})))
|
|
||||||
(s/merge-spec-impl (vec specs) (vec specs) nil))
|
(s/merge-spec-impl (vec specs) (vec specs) nil))
|
||||||
|
|
||||||
(defn validate-route-data [routes key spec]
|
(defn validate-route-data [routes key spec]
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@
|
||||||
(throw
|
(throw
|
||||||
(ex-info
|
(ex-info
|
||||||
(str "Can't produce Spec apidocs for " spesification)
|
(str "Can't produce Spec apidocs for " spesification)
|
||||||
{:type spesification, :coercion :spec}))))
|
{:spesification spesification, :coercion :spec}))))
|
||||||
(-compile-model [_ model name]
|
(-compile-model [_ model name]
|
||||||
(into-spec model name))
|
(into-spec model name))
|
||||||
(-open-model [_ spec] spec)
|
(-open-model [_ spec] spec)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue