mirror of
https://github.com/metosin/reitit.git
synced 2025-12-18 00:41:12 +00:00
format
This commit is contained in:
parent
b7cc420fde
commit
5d4c886d35
52 changed files with 1686 additions and 1690 deletions
|
|
@ -43,28 +43,28 @@
|
|||
|
||||
(defn ^:no-doc request-coercion-failed! [result coercion value in request]
|
||||
(throw
|
||||
(ex-info
|
||||
(str "Request coercion failed: " (pr-str result))
|
||||
(merge
|
||||
(into {} result)
|
||||
{:type ::request-coercion
|
||||
:coercion coercion
|
||||
:value value
|
||||
:in [:request in]
|
||||
:request request}))))
|
||||
(ex-info
|
||||
(str "Request coercion failed: " (pr-str result))
|
||||
(merge
|
||||
(into {} result)
|
||||
{:type ::request-coercion
|
||||
:coercion coercion
|
||||
:value value
|
||||
:in [:request in]
|
||||
:request request}))))
|
||||
|
||||
(defn ^:no-doc response-coercion-failed! [result coercion value request response]
|
||||
(throw
|
||||
(ex-info
|
||||
(str "Response coercion failed: " (pr-str result))
|
||||
(merge
|
||||
(into {} result)
|
||||
{:type ::response-coercion
|
||||
:coercion coercion
|
||||
:value value
|
||||
:in [:response :body]
|
||||
:request request
|
||||
:response response}))))
|
||||
(ex-info
|
||||
(str "Response coercion failed: " (pr-str result))
|
||||
(merge
|
||||
(into {} result)
|
||||
{:type ::response-coercion
|
||||
:coercion coercion
|
||||
:value value
|
||||
:in [:response :body]
|
||||
:request request
|
||||
:response response}))))
|
||||
|
||||
(defn extract-request-format-default [request]
|
||||
(-> request :muuntaja/request :format))
|
||||
|
|
@ -109,9 +109,9 @@
|
|||
|
||||
(defn coerce-request [coercers request]
|
||||
(reduce-kv
|
||||
(fn [acc k coercer]
|
||||
(impl/fast-assoc acc k (coercer request)))
|
||||
{} coercers))
|
||||
(fn [acc k coercer]
|
||||
(impl/fast-assoc acc k (coercer request)))
|
||||
{} coercers))
|
||||
|
||||
(defn coerce-response [coercers request response]
|
||||
(if response
|
||||
|
|
@ -147,13 +147,13 @@
|
|||
:multipart :formData}]
|
||||
(case specification
|
||||
:swagger (->> (update
|
||||
data
|
||||
:parameters
|
||||
(fn [parameters]
|
||||
(->> parameters
|
||||
(map (fn [[k v]] [(swagger-parameter k) v]))
|
||||
(filter first)
|
||||
(into {}))))
|
||||
data
|
||||
:parameters
|
||||
(fn [parameters]
|
||||
(->> parameters
|
||||
(map (fn [[k v]] [(swagger-parameter k) v]))
|
||||
(filter first)
|
||||
(into {}))))
|
||||
(-get-apidocs coercion specification)))))
|
||||
|
||||
;;
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
(if-not (partial-match? match)
|
||||
match
|
||||
(impl/throw-on-missing-path-params
|
||||
(:template match) (:required match) path-params)))))
|
||||
(:template match) (:required match) path-params)))))
|
||||
|
||||
(defn match->path
|
||||
([match]
|
||||
|
|
@ -87,15 +87,15 @@
|
|||
(let [compiler (::trie/trie-compiler opts (trie/compiler))
|
||||
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 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))]
|
||||
[(conj pl (-> (trie/insert nil p (->Match p data result nil nil) opts) (trie/compile)))
|
||||
(if name (assoc nl name f) nl)]))
|
||||
[[] {}]
|
||||
compiled-routes)
|
||||
(fn [[pl nl] [p {:keys [name] :as data} result]]
|
||||
(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))]
|
||||
[(conj pl (-> (trie/insert nil p (->Match p data result nil nil) opts) (trie/compile)))
|
||||
(if name (assoc nl name f) nl)]))
|
||||
[[] {}]
|
||||
compiled-routes)
|
||||
lookup (impl/fast-map nl)
|
||||
matcher (trie/linear-matcher compiler pl true)
|
||||
match-by-path (trie/path-matcher matcher compiler)
|
||||
|
|
@ -133,18 +133,18 @@
|
|||
([compiled-routes opts]
|
||||
(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
|
||||
:routes compiled-routes}))
|
||||
(str "can't create :lookup-router with wildcard routes: " wilds)
|
||||
{:wilds wilds
|
||||
:routes compiled-routes}))
|
||||
(let [names (impl/find-names compiled-routes opts)
|
||||
[pl nl] (reduce
|
||||
(fn [[pl nl] [p {:keys [name] :as data} result]]
|
||||
[(assoc pl p (->Match p data result {} p))
|
||||
(if name
|
||||
(assoc nl name #(->Match p data result % p))
|
||||
nl)])
|
||||
[{} {}]
|
||||
compiled-routes)
|
||||
(fn [[pl nl] [p {:keys [name] :as data} result]]
|
||||
[(assoc pl p (->Match p data result {} p))
|
||||
(if name
|
||||
(assoc nl name #(->Match p data result % p))
|
||||
nl)])
|
||||
[{} {}]
|
||||
compiled-routes)
|
||||
data (impl/fast-map pl)
|
||||
lookup (impl/fast-map nl)
|
||||
routes (impl/uncompile-routes compiled-routes)]
|
||||
|
|
@ -183,15 +183,15 @@
|
|||
(let [compiler (::trie/trie-compiler opts (trie/compiler))
|
||||
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 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))]
|
||||
[(trie/insert pl p (->Match p data result nil nil) opts)
|
||||
(if name (assoc nl name f) nl)]))
|
||||
[nil {}]
|
||||
compiled-routes)
|
||||
(fn [[pl nl] [p {:keys [name] :as data} result]]
|
||||
(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))]
|
||||
[(trie/insert pl p (->Match p data result nil nil) opts)
|
||||
(if name (assoc nl name f) nl)]))
|
||||
[nil {}]
|
||||
compiled-routes)
|
||||
matcher (trie/compile pl compiler)
|
||||
match-by-path (trie/path-matcher matcher compiler)
|
||||
lookup (impl/fast-map nl)
|
||||
|
|
@ -229,8 +229,8 @@
|
|||
([compiled-routes opts]
|
||||
(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}))
|
||||
(str ":single-static-path-router requires exactly 1 static route: " compiled-routes)
|
||||
{:routes compiled-routes}))
|
||||
(let [[n :as names] (impl/find-names compiled-routes opts)
|
||||
[[p data result]] compiled-routes
|
||||
p #?(:clj (.intern ^String p) :cljs p)
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
(map (fn [provide]
|
||||
(when (contains? acc provide)
|
||||
(exception/fail!
|
||||
(str "multiple providers for: " provide)
|
||||
{::multiple-providers provide}))
|
||||
(str "multiple providers for: " provide)
|
||||
{::multiple-providers provide}))
|
||||
[provide dependent]))
|
||||
(get-provides dependent)))
|
||||
{} nodes))
|
||||
|
|
@ -22,8 +22,8 @@
|
|||
(if (contains? providers k)
|
||||
(get providers k)
|
||||
(exception/fail!
|
||||
(str "provider missing for dependency: " k)
|
||||
{::missing-provider k})))
|
||||
(str "provider missing for dependency: " k)
|
||||
{::missing-provider k})))
|
||||
|
||||
(defn post-order
|
||||
"Put `nodes` in post-order. Can also be described as a reverse topological sort.
|
||||
|
|
|
|||
|
|
@ -31,20 +31,20 @@
|
|||
path " " (not-empty (select-keys route-data [:conflicting]))))]
|
||||
(apply str "Router contains conflicting route paths:\n\n"
|
||||
(mapv
|
||||
(fn [[[path route-data] vals]]
|
||||
(str (resolve-str path route-data)
|
||||
"\n"
|
||||
(str/join "\n" (mapv (fn [[path route-data]]
|
||||
(resolve-str path route-data)) vals))
|
||||
"\n\n"))
|
||||
conflicts))))
|
||||
(fn [[[path route-data] vals]]
|
||||
(str (resolve-str path route-data)
|
||||
"\n"
|
||||
(str/join "\n" (mapv (fn [[path route-data]]
|
||||
(resolve-str path route-data)) vals))
|
||||
"\n\n"))
|
||||
conflicts))))
|
||||
|
||||
(defmethod format-exception :name-conflicts [_ _ conflicts]
|
||||
(apply str "Router contains conflicting route names:\n\n"
|
||||
(mapv
|
||||
(fn [[name vals]]
|
||||
(str name "\n-> " (str/join "\n-> " (mapv first vals)) "\n"))
|
||||
conflicts)))
|
||||
(fn [[name vals]]
|
||||
(str name "\n-> " (str/join "\n-> " (mapv first vals)) "\n"))
|
||||
conflicts)))
|
||||
|
||||
(defmethod format-exception :reitit.impl/merge-data [_ _ data]
|
||||
(str "Error merging route-data\n\n" (pr-str data)))
|
||||
|
|
|
|||
|
|
@ -28,33 +28,33 @@
|
|||
Also works on vectors. Maintains key for maps, order for vectors."
|
||||
[f coll]
|
||||
(reduce-kv
|
||||
(fn [coll k v]
|
||||
(if-some [v' (f v)]
|
||||
(assoc coll k v')
|
||||
coll))
|
||||
coll
|
||||
coll))
|
||||
(fn [coll k v]
|
||||
(if-some [v' (f v)]
|
||||
(assoc coll k v')
|
||||
coll))
|
||||
coll
|
||||
coll))
|
||||
|
||||
(defn walk [raw-routes {:keys [path data routes expand]
|
||||
:or {data [], routes []}
|
||||
:as opts}]
|
||||
(letfn
|
||||
[(walk-many [p m r]
|
||||
(reduce #(into %1 (walk-one p m %2)) [] r))
|
||||
(walk-one [pacc macc routes]
|
||||
(if (vector? (first routes))
|
||||
(walk-many pacc macc routes)
|
||||
(when (string? (first routes))
|
||||
(let [[path & [maybe-arg :as args]] routes
|
||||
[data childs] (if (or (vector? maybe-arg)
|
||||
(and (sequential? maybe-arg)
|
||||
(sequential? (first maybe-arg)))
|
||||
(nil? maybe-arg))
|
||||
[{} args]
|
||||
[maybe-arg (rest args)])
|
||||
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-many [p m r]
|
||||
(reduce #(into %1 (walk-one p m %2)) [] r))
|
||||
(walk-one [pacc macc routes]
|
||||
(if (vector? (first routes))
|
||||
(walk-many pacc macc routes)
|
||||
(when (string? (first routes))
|
||||
(let [[path & [maybe-arg :as args]] routes
|
||||
[data childs] (if (or (vector? maybe-arg)
|
||||
(and (sequential? maybe-arg)
|
||||
(sequential? (first maybe-arg)))
|
||||
(nil? maybe-arg))
|
||||
[{} args]
|
||||
[maybe-arg (rest args)])
|
||||
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]
|
||||
|
|
@ -62,25 +62,25 @@
|
|||
|
||||
(defn merge-data [p x]
|
||||
(reduce
|
||||
(fn [acc [k v]]
|
||||
(try
|
||||
(mm/meta-merge acc {k v})
|
||||
(catch #?(:clj Exception, :cljs js/Error) e
|
||||
(ex/fail! ::merge-data {:path p, :left acc, :right {k v}, :exception e}))))
|
||||
{} x))
|
||||
(fn [acc [k v]]
|
||||
(try
|
||||
(mm/meta-merge acc {k v})
|
||||
(catch #?(:clj Exception, :cljs js/Error) e
|
||||
(ex/fail! ::merge-data {:path p, :left acc, :right {k v}, :exception e}))))
|
||||
{} x))
|
||||
|
||||
(defn resolve-routes [raw-routes {:keys [coerce] :as opts}]
|
||||
(cond->> (->> (walk raw-routes opts) (map-data merge-data))
|
||||
coerce (into [] (keep #(coerce % opts)))))
|
||||
coerce (into [] (keep #(coerce % opts)))))
|
||||
|
||||
(defn path-conflicting-routes [routes opts]
|
||||
(let [parts-and-routes (mapv (fn [[s :as r]] [(trie/split-path s opts) r]) routes)]
|
||||
(-> (into {} (comp (map-indexed (fn [index [p r]]
|
||||
[r (reduce
|
||||
(fn [acc [p' r']]
|
||||
(if (trie/conflicting-parts? p p')
|
||||
(conj acc r') acc))
|
||||
#{} (subvec parts-and-routes (inc index)))]))
|
||||
(fn [acc [p' r']]
|
||||
(if (trie/conflicting-parts? p p')
|
||||
(conj acc r') acc))
|
||||
#{} (subvec parts-and-routes (inc index)))]))
|
||||
(filter (comp seq second))) parts-and-routes)
|
||||
(not-empty))))
|
||||
|
||||
|
|
@ -123,13 +123,13 @@
|
|||
(defn path-for [route path-params]
|
||||
(if (:path-params route)
|
||||
(if-let [parts (reduce
|
||||
(fn [acc part]
|
||||
(if (string? part)
|
||||
(conj acc part)
|
||||
(if-let [p (get path-params (:value part))]
|
||||
(conj acc p)
|
||||
(reduced nil))))
|
||||
[] (:path-parts route))]
|
||||
(fn [acc part]
|
||||
(if (string? part)
|
||||
(conj acc part)
|
||||
(if-let [p (get path-params (:value part))]
|
||||
(conj acc p)
|
||||
(reduced nil))))
|
||||
[] (:path-parts route))]
|
||||
(apply str parts))
|
||||
(:path route)))
|
||||
|
||||
|
|
@ -138,8 +138,8 @@
|
|||
(let [defined (-> path-params keys set)
|
||||
missing (set/difference required defined)]
|
||||
(ex/fail!
|
||||
(str "missing path-params for route " template " -> " missing)
|
||||
{:path-params path-params, :required required}))))
|
||||
(str "missing path-params for route " template " -> " missing)
|
||||
{:path-params path-params, :required required}))))
|
||||
|
||||
(defn fast-assoc
|
||||
#?@(:clj [[^clojure.lang.Associative a k v] (.assoc a k v)]
|
||||
|
|
@ -178,10 +178,10 @@
|
|||
(if s
|
||||
#?(:clj (if (.contains ^String s "%")
|
||||
(URLDecoder/decode
|
||||
(if (.contains ^String s "+")
|
||||
(.replace ^String s "+" "%2B")
|
||||
^String s)
|
||||
"UTF-8"))
|
||||
(if (.contains ^String s "+")
|
||||
(.replace ^String s "+" "%2B")
|
||||
^String s)
|
||||
"UTF-8"))
|
||||
:cljs (js/decodeURIComponent s))))
|
||||
|
||||
(defn url-decode [s]
|
||||
|
|
|
|||
|
|
@ -37,36 +37,36 @@
|
|||
(if-let [interceptor (if registry (registry this))]
|
||||
(into-interceptor interceptor data opts)
|
||||
(throw
|
||||
(ex-info
|
||||
(str
|
||||
"Interceptor " this " not found in registry.\n\n"
|
||||
(if (seq registry)
|
||||
(str
|
||||
"Available interceptors in registry:\n"
|
||||
(with-out-str
|
||||
(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")
|
||||
{:id this
|
||||
:registry registry}))))
|
||||
(ex-info
|
||||
(str
|
||||
"Interceptor " this " not found in registry.\n\n"
|
||||
(if (seq registry)
|
||||
(str
|
||||
"Available interceptors in registry:\n"
|
||||
(with-out-str
|
||||
(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")
|
||||
{:id this
|
||||
:registry registry}))))
|
||||
|
||||
#?(:clj clojure.lang.APersistentVector
|
||||
:cljs cljs.core.PersistentVector)
|
||||
(into-interceptor [[f & args :as form] data opts]
|
||||
(when (and (seq args) (not (fn? f)))
|
||||
(exception/fail!
|
||||
(str "Invalid Interceptor form: " form "")
|
||||
{:form form}))
|
||||
(str "Invalid Interceptor form: " form "")
|
||||
{:form form}))
|
||||
(into-interceptor (apply f args) data opts))
|
||||
|
||||
#?(:clj clojure.lang.Fn
|
||||
:cljs function)
|
||||
(into-interceptor [this data opts]
|
||||
(into-interceptor
|
||||
{:name ::handler
|
||||
::handler this
|
||||
:enter (fn [ctx]
|
||||
(assoc ctx :response (this (:request ctx))))}
|
||||
data opts))
|
||||
{:name ::handler
|
||||
::handler this
|
||||
:enter (fn [ctx]
|
||||
(assoc ctx :response (this (:request ctx))))}
|
||||
data opts))
|
||||
|
||||
#?(:clj clojure.lang.PersistentArrayMap
|
||||
:cljs cljs.core.PersistentArrayMap)
|
||||
|
|
@ -86,13 +86,13 @@
|
|||
opts (assoc opts ::compiled (inc ^long compiled))]
|
||||
(when (>= ^long compiled ^long *max-compile-depth*)
|
||||
(exception/fail!
|
||||
(str "Too deep Interceptor compilation - " compiled)
|
||||
{:this this, :data data, :opts opts}))
|
||||
(str "Too deep Interceptor compilation - " compiled)
|
||||
{:this this, :data data, :opts opts}))
|
||||
(if-let [interceptor (into-interceptor (compile data opts) data opts)]
|
||||
(map->Interceptor
|
||||
(merge
|
||||
(dissoc this :compile)
|
||||
(impl/strip-nils interceptor)))))))
|
||||
(merge
|
||||
(dissoc this :compile)
|
||||
(impl/strip-nils interceptor)))))))
|
||||
|
||||
nil
|
||||
(into-interceptor [_ _ _]))
|
||||
|
|
@ -122,9 +122,9 @@
|
|||
([[_ {:keys [interceptors handler] :as data}] {::keys [queue] :as opts} _]
|
||||
(let [chain (chain (into (vec interceptors) [handler]) data opts)]
|
||||
(map->Endpoint
|
||||
{:interceptors chain
|
||||
:queue ((or queue identity) chain)
|
||||
:data data}))))
|
||||
{:interceptors chain
|
||||
:queue ((or queue identity) chain)
|
||||
:data data}))))
|
||||
|
||||
(defn transform-butlast
|
||||
"Returns a function to that takes a interceptor transformation function and
|
||||
|
|
@ -132,8 +132,8 @@
|
|||
[f]
|
||||
(fn [interceptors]
|
||||
(concat
|
||||
(f (butlast interceptors))
|
||||
[(last interceptors)])))
|
||||
(f (butlast interceptors))
|
||||
[(last interceptors)])))
|
||||
|
||||
(defn router
|
||||
"Creates a [[reitit.core/Router]] from raw route data and optionally an options map with
|
||||
|
|
|
|||
|
|
@ -21,17 +21,17 @@
|
|||
(if-let [middleware (if registry (registry this))]
|
||||
(into-middleware middleware data opts)
|
||||
(throw
|
||||
(ex-info
|
||||
(str
|
||||
"Middleware " this " not found in registry.\n\n"
|
||||
(if (seq registry)
|
||||
(str
|
||||
"Available middleware in registry:\n"
|
||||
(with-out-str
|
||||
(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")
|
||||
{:id this
|
||||
:registry registry}))))
|
||||
(ex-info
|
||||
(str
|
||||
"Middleware " this " not found in registry.\n\n"
|
||||
(if (seq registry)
|
||||
(str
|
||||
"Available middleware in registry:\n"
|
||||
(with-out-str
|
||||
(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")
|
||||
{:id this
|
||||
:registry registry}))))
|
||||
|
||||
#?(:clj clojure.lang.APersistentVector
|
||||
:cljs cljs.core.PersistentVector)
|
||||
|
|
@ -43,7 +43,7 @@
|
|||
:cljs function)
|
||||
(into-middleware [this _ _]
|
||||
(map->Middleware
|
||||
{:wrap this}))
|
||||
{:wrap this}))
|
||||
|
||||
#?(:clj clojure.lang.PersistentArrayMap
|
||||
:cljs cljs.core.PersistentArrayMap)
|
||||
|
|
@ -63,13 +63,13 @@
|
|||
opts (assoc opts ::compiled (inc ^long compiled))]
|
||||
(when (>= ^long compiled ^long *max-compile-depth*)
|
||||
(exception/fail!
|
||||
(str "Too deep Middleware compilation - " compiled)
|
||||
{:this this, :data data, :opts opts}))
|
||||
(str "Too deep Middleware compilation - " compiled)
|
||||
{:this this, :data data, :opts opts}))
|
||||
(if-let [middeware (into-middleware (compile data opts) data opts)]
|
||||
(map->Middleware
|
||||
(merge
|
||||
(dissoc this :compile)
|
||||
(impl/strip-nils middeware)))))))
|
||||
(merge
|
||||
(dissoc this :compile)
|
||||
(impl/strip-nils middeware)))))))
|
||||
|
||||
nil
|
||||
(into-middleware [_ _ _]))
|
||||
|
|
@ -77,10 +77,10 @@
|
|||
(defn- ensure-handler! [path data scope]
|
||||
(when-not (:handler data)
|
||||
(exception/fail!
|
||||
(str "path \"" path "\" doesn't have a :handler defined"
|
||||
(if scope (str " for " scope)))
|
||||
(merge {:path path, :data data}
|
||||
(if scope {:scope scope})))))
|
||||
(str "path \"" path "\" doesn't have a :handler defined"
|
||||
(if scope (str " for " scope)))
|
||||
(merge {:path path, :data data}
|
||||
(if scope {:scope scope})))))
|
||||
|
||||
(defn- expand-and-transform
|
||||
[middleware data {::keys [transform] :or {transform identity} :as opts}]
|
||||
|
|
@ -116,9 +116,9 @@
|
|||
(ensure-handler! path data scope)
|
||||
(let [middleware (expand-and-transform middleware data opts)]
|
||||
(map->Endpoint
|
||||
{:handler (compile-handler middleware handler)
|
||||
:middleware middleware
|
||||
:data data}))))
|
||||
{:handler (compile-handler middleware handler)
|
||||
:middleware middleware
|
||||
:data data}))))
|
||||
|
||||
(defn router
|
||||
"Creates a [[reitit.core/Router]] from raw route data and optionally an options map with
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@
|
|||
|
||||
(s/def ::raw-route
|
||||
(s/nilable
|
||||
(s/cat :path ::path
|
||||
:arg (s/? ::arg)
|
||||
:childs (s/* (s/and (s/nilable ::raw-routes))))))
|
||||
(s/cat :path ::path
|
||||
:arg (s/? ::arg)
|
||||
:childs (s/* (s/and (s/nilable ::raw-routes))))))
|
||||
|
||||
(s/def ::raw-routes
|
||||
(s/or :route ::raw-route
|
||||
|
|
@ -60,19 +60,19 @@
|
|||
|
||||
(s/def ::opts
|
||||
(s/nilable
|
||||
(s/keys :opt-un [:reitit.router/path
|
||||
:reitit.router/routes
|
||||
:reitit.router/data
|
||||
:reitit.router/expand
|
||||
:reitit.router/coerce
|
||||
:reitit.router/compile
|
||||
:reitit.router/conflicts
|
||||
:reitit.router/router])))
|
||||
(s/keys :opt-un [:reitit.router/path
|
||||
:reitit.router/routes
|
||||
:reitit.router/data
|
||||
:reitit.router/expand
|
||||
:reitit.router/coerce
|
||||
:reitit.router/compile
|
||||
:reitit.router/conflicts
|
||||
:reitit.router/router])))
|
||||
|
||||
(s/fdef r/router
|
||||
:args (s/or :1arity (s/cat :data (s/spec ::raw-routes))
|
||||
:2arity (s/cat :data (s/spec ::raw-routes), :opts ::opts))
|
||||
:ret ::router)
|
||||
:args (s/or :1arity (s/cat :data (s/spec ::raw-routes))
|
||||
:2arity (s/cat :data (s/spec ::raw-routes), :opts ::opts))
|
||||
:ret ::router)
|
||||
|
||||
;;
|
||||
;; coercion
|
||||
|
|
@ -128,15 +128,15 @@
|
|||
(defn validate [routes {:keys [spec] ::keys [wrap] :or {spec ::default-data, wrap identity}}]
|
||||
(when-let [problems (validate-route-data routes wrap spec)]
|
||||
(exception/fail!
|
||||
::invalid-route-data
|
||||
{:problems problems})))
|
||||
::invalid-route-data
|
||||
{:problems problems})))
|
||||
|
||||
(defmethod exception/format-exception :reitit.spec/invalid-route-data [_ _ {:keys [problems]}]
|
||||
(apply str "Invalid route data:\n\n"
|
||||
(mapv
|
||||
(fn [{:keys [path scope data spec]}]
|
||||
(str "-- On route -----------------------\n\n"
|
||||
(pr-str path) (if scope (str " " (pr-str scope))) "\n\n"
|
||||
(pr-str data) "\n\n"
|
||||
(s/explain-str spec data) "\n"))
|
||||
problems)))
|
||||
(fn [{:keys [path scope data spec]}]
|
||||
(str "-- On route -----------------------\n\n"
|
||||
(pr-str path) (if scope (str " " (pr-str scope))) "\n\n"
|
||||
(pr-str data) "\n\n"
|
||||
(s/explain-str spec data) "\n"))
|
||||
problems)))
|
||||
|
|
|
|||
|
|
@ -90,12 +90,12 @@
|
|||
|
||||
(defn join-path [xs]
|
||||
(reduce
|
||||
(fn [s x]
|
||||
(str s (cond
|
||||
(string? x) x
|
||||
(instance? Wild x) (str "{" (-> x :value str (subs 1)) "}")
|
||||
(instance? CatchAll x) (str "{*" (-> x :value str (subs 1)) "}"))))
|
||||
"" xs))
|
||||
(fn [s x]
|
||||
(str s (cond
|
||||
(string? x) x
|
||||
(instance? Wild x) (str "{" (-> x :value str (subs 1)) "}")
|
||||
(instance? CatchAll x) (str "{*" (-> x :value str (subs 1)) "}"))))
|
||||
"" xs))
|
||||
|
||||
(defn normalize [s opts]
|
||||
(-> s (split-path opts) (join-path)))
|
||||
|
|
@ -172,25 +172,25 @@
|
|||
|
||||
:else
|
||||
(or
|
||||
(reduce
|
||||
(fn [_ [p n]]
|
||||
(if-let [cp (common-prefix p path)]
|
||||
(if (= cp p)
|
||||
(reduce
|
||||
(fn [_ [p n]]
|
||||
(if-let [cp (common-prefix p path)]
|
||||
(if (= cp p)
|
||||
;; insert into child node
|
||||
(let [n' (-insert n (conj ps (subs path (count p))) fp params data)]
|
||||
(reduced (assoc-in node [:children p] n')))
|
||||
(let [n' (-insert n (conj ps (subs path (count p))) fp params data)]
|
||||
(reduced (assoc-in node [:children p] n')))
|
||||
;; split child node
|
||||
(let [rp (subs p (count cp))
|
||||
rp' (subs path (count cp))
|
||||
n' (-insert (-node {}) ps fp params data)
|
||||
n'' (-insert (-node {:children {rp n, rp' n'}}) nil nil nil nil)]
|
||||
(reduced (update node :children (fn [children]
|
||||
(-> children
|
||||
(dissoc p)
|
||||
(assoc cp n'')))))))))
|
||||
nil (:children node))
|
||||
(let [rp (subs p (count cp))
|
||||
rp' (subs path (count cp))
|
||||
n' (-insert (-node {}) ps fp params data)
|
||||
n'' (-insert (-node {:children {rp n, rp' n'}}) nil nil nil nil)]
|
||||
(reduced (update node :children (fn [children]
|
||||
(-> children
|
||||
(dissoc p)
|
||||
(assoc cp n'')))))))))
|
||||
nil (:children node))
|
||||
;; new child node
|
||||
(assoc-in node [:children path] (-insert (-node {}) ps fp params data))))]
|
||||
(assoc-in node [:children path] (-insert (-node {}) ps fp params data))))]
|
||||
(if-let [child (get-in node' [:children ""])]
|
||||
;; optimize by removing empty paths
|
||||
(-> (merge-with merge (dissoc node' :data) child)
|
||||
|
|
@ -202,10 +202,10 @@
|
|||
(if percent?
|
||||
#?(:cljs (js/decodeURIComponent param)
|
||||
:clj (URLDecoder/decode
|
||||
(if (.contains ^String param "+")
|
||||
(.replace ^String param "+" "%2B")
|
||||
param)
|
||||
"UTF-8"))
|
||||
(if (.contains ^String param "+")
|
||||
(.replace ^String param "+" "%2B")
|
||||
param)
|
||||
"UTF-8"))
|
||||
param)))
|
||||
|
||||
;;
|
||||
|
|
@ -313,13 +313,13 @@
|
|||
(def record-parameters
|
||||
"Memoized function to transform parameters into runtime generated Record."
|
||||
(memoize
|
||||
(fn [keys]
|
||||
(if (some qualified-keyword? keys)
|
||||
(map-parameters keys)
|
||||
(let [sym (gensym "PathParams")
|
||||
ctor (symbol (str "map->" sym))]
|
||||
(binding [*ns* (find-ns 'user)]
|
||||
(eval `(do (defrecord ~sym ~(mapv (comp symbol name) keys)) (~ctor {}))))))))))
|
||||
(fn [keys]
|
||||
(if (some qualified-keyword? keys)
|
||||
(map-parameters keys)
|
||||
(let [sym (gensym "PathParams")
|
||||
ctor (symbol (str "map->" sym))]
|
||||
(binding [*ns* (find-ns 'user)]
|
||||
(eval `(do (defrecord ~sym ~(mapv (comp symbol name) keys)) (~ctor {}))))))))))
|
||||
|
||||
(defn insert
|
||||
"Returns a trie with routes added to it."
|
||||
|
|
@ -327,9 +327,9 @@
|
|||
(insert nil routes))
|
||||
([node routes]
|
||||
(reduce
|
||||
(fn [acc [p d]]
|
||||
(insert acc p d))
|
||||
node routes))
|
||||
(fn [acc [p d]]
|
||||
(insert acc p d))
|
||||
node routes))
|
||||
([node path data]
|
||||
(insert node path data nil))
|
||||
([node path data {::keys [parameters] :or {parameters map-parameters} :as opts}]
|
||||
|
|
@ -355,12 +355,12 @@
|
|||
(cond-> data (conj (data-matcher compiler params data)))
|
||||
(into (for [[p c] children] (static-matcher compiler p (compile c compiler (conj cp p)))))
|
||||
(into
|
||||
(for [[p c] wilds]
|
||||
(let [pv (:value p)
|
||||
ends (ends c)]
|
||||
(if (next ends)
|
||||
(ex/fail! ::multiple-terminators {:terminators ends, :path (join-path (conj cp p))})
|
||||
(wild-matcher compiler pv (ffirst ends) (compile c compiler (conj cp pv)))))))
|
||||
(for [[p c] wilds]
|
||||
(let [pv (:value p)
|
||||
ends (ends c)]
|
||||
(if (next ends)
|
||||
(ex/fail! ::multiple-terminators {:terminators ends, :path (join-path (conj cp p))})
|
||||
(wild-matcher compiler pv (ffirst ends) (compile c compiler (conj cp pv)))))))
|
||||
(into (for [[p c] catch-all] (catch-all-matcher compiler (:value p) params (:data c)))))]
|
||||
(cond
|
||||
(> (count matchers) 1) (linear-matcher compiler matchers false)
|
||||
|
|
@ -387,61 +387,61 @@
|
|||
|
||||
(comment
|
||||
(->
|
||||
[["/v2/whoami" 1]
|
||||
["/v2/users/:user-id/datasets" 2]
|
||||
["/v2/public/projects/:project-id/datasets" 3]
|
||||
["/v1/public/topics/:topic" 4]
|
||||
["/v1/users/:user-id/orgs/:org-id" 5]
|
||||
["/v1/search/topics/:term" 6]
|
||||
["/v1/users/:user-id/invitations" 7]
|
||||
["/v1/users/:user-id/topics" 9]
|
||||
["/v1/users/:user-id/bookmarks/followers" 10]
|
||||
["/v2/datasets/:dataset-id" 11]
|
||||
["/v1/orgs/:org-id/usage-stats" 12]
|
||||
["/v1/orgs/:org-id/devices/:client-id" 13]
|
||||
["/v1/messages/user/:user-id" 14]
|
||||
["/v1/users/:user-id/devices" 15]
|
||||
["/v1/public/users/:user-id" 16]
|
||||
["/v1/orgs/:org-id/errors" 17]
|
||||
["/v1/public/orgs/:org-id" 18]
|
||||
["/v1/orgs/:org-id/invitations" 19]
|
||||
["/v1/users/:user-id/device-errors" 22]
|
||||
["/v2/login" 23]
|
||||
["/v1/users/:user-id/usage-stats" 24]
|
||||
["/v2/users/:user-id/devices" 25]
|
||||
["/v1/users/:user-id/claim-device/:client-id" 26]
|
||||
["/v2/public/projects/:project-id" 27]
|
||||
["/v2/public/datasets/:dataset-id" 28]
|
||||
["/v2/users/:user-id/topics/bulk" 29]
|
||||
["/v1/messages/device/:client-id" 30]
|
||||
["/v1/users/:user-id/owned-orgs" 31]
|
||||
["/v1/topics/:topic" 32]
|
||||
["/v1/users/:user-id/bookmark/:topic" 33]
|
||||
["/v1/orgs/:org-id/members/:user-id" 34]
|
||||
["/v1/users/:user-id/devices/:client-id" 35]
|
||||
["/v1/users/:user-id" 36]
|
||||
["/v1/orgs/:org-id/devices" 37]
|
||||
["/v1/orgs/:org-id/members" 38]
|
||||
["/v2/orgs/:org-id/topics" 40]
|
||||
["/v1/whoami" 41]
|
||||
["/v1/orgs/:org-id" 42]
|
||||
["/v1/users/:user-id/api-key" 43]
|
||||
["/v2/schemas" 44]
|
||||
["/v2/users/:user-id/topics" 45]
|
||||
["/v1/orgs/:org-id/confirm-membership/:token" 46]
|
||||
["/v2/topics/:topic" 47]
|
||||
["/v1/messages/topic/:topic" 48]
|
||||
["/v1/users/:user-id/devices/:client-id/reset-password" 49]
|
||||
["/v2/topics" 50]
|
||||
["/v1/login" 51]
|
||||
["/v1/users/:user-id/orgs" 52]
|
||||
["/v2/public/messages/dataset/:dataset-id" 53]
|
||||
["/v1/topics" 54]
|
||||
["/v1/orgs" 55]
|
||||
["/v1/users/:user-id/bookmarks" 56]
|
||||
["/v1/orgs/:org-id/topics" 57]
|
||||
["/command1 {arg1} {arg2}" ::cmd1]
|
||||
["/command2 {arg1} {arg2} {arg3}" ::cmd2]]
|
||||
(insert)
|
||||
(compile)
|
||||
(pretty)))
|
||||
[["/v2/whoami" 1]
|
||||
["/v2/users/:user-id/datasets" 2]
|
||||
["/v2/public/projects/:project-id/datasets" 3]
|
||||
["/v1/public/topics/:topic" 4]
|
||||
["/v1/users/:user-id/orgs/:org-id" 5]
|
||||
["/v1/search/topics/:term" 6]
|
||||
["/v1/users/:user-id/invitations" 7]
|
||||
["/v1/users/:user-id/topics" 9]
|
||||
["/v1/users/:user-id/bookmarks/followers" 10]
|
||||
["/v2/datasets/:dataset-id" 11]
|
||||
["/v1/orgs/:org-id/usage-stats" 12]
|
||||
["/v1/orgs/:org-id/devices/:client-id" 13]
|
||||
["/v1/messages/user/:user-id" 14]
|
||||
["/v1/users/:user-id/devices" 15]
|
||||
["/v1/public/users/:user-id" 16]
|
||||
["/v1/orgs/:org-id/errors" 17]
|
||||
["/v1/public/orgs/:org-id" 18]
|
||||
["/v1/orgs/:org-id/invitations" 19]
|
||||
["/v1/users/:user-id/device-errors" 22]
|
||||
["/v2/login" 23]
|
||||
["/v1/users/:user-id/usage-stats" 24]
|
||||
["/v2/users/:user-id/devices" 25]
|
||||
["/v1/users/:user-id/claim-device/:client-id" 26]
|
||||
["/v2/public/projects/:project-id" 27]
|
||||
["/v2/public/datasets/:dataset-id" 28]
|
||||
["/v2/users/:user-id/topics/bulk" 29]
|
||||
["/v1/messages/device/:client-id" 30]
|
||||
["/v1/users/:user-id/owned-orgs" 31]
|
||||
["/v1/topics/:topic" 32]
|
||||
["/v1/users/:user-id/bookmark/:topic" 33]
|
||||
["/v1/orgs/:org-id/members/:user-id" 34]
|
||||
["/v1/users/:user-id/devices/:client-id" 35]
|
||||
["/v1/users/:user-id" 36]
|
||||
["/v1/orgs/:org-id/devices" 37]
|
||||
["/v1/orgs/:org-id/members" 38]
|
||||
["/v2/orgs/:org-id/topics" 40]
|
||||
["/v1/whoami" 41]
|
||||
["/v1/orgs/:org-id" 42]
|
||||
["/v1/users/:user-id/api-key" 43]
|
||||
["/v2/schemas" 44]
|
||||
["/v2/users/:user-id/topics" 45]
|
||||
["/v1/orgs/:org-id/confirm-membership/:token" 46]
|
||||
["/v2/topics/:topic" 47]
|
||||
["/v1/messages/topic/:topic" 48]
|
||||
["/v1/users/:user-id/devices/:client-id/reset-password" 49]
|
||||
["/v2/topics" 50]
|
||||
["/v1/login" 51]
|
||||
["/v1/users/:user-id/orgs" 52]
|
||||
["/v2/public/messages/dataset/:dataset-id" 53]
|
||||
["/v1/topics" 54]
|
||||
["/v1/orgs" 55]
|
||||
["/v1/users/:user-id/bookmarks" 56]
|
||||
["/v1/orgs/:org-id/topics" 57]
|
||||
["/command1 {arg1} {arg2}" ::cmd1]
|
||||
["/command2 {arg1} {arg2} {arg3}" ::cmd2]]
|
||||
(insert)
|
||||
(compile)
|
||||
(pretty)))
|
||||
|
|
|
|||
|
|
@ -152,13 +152,13 @@
|
|||
(printer nil))
|
||||
([options]
|
||||
(map->EdnPrinter
|
||||
(merge
|
||||
{:width 80
|
||||
:symbols {}
|
||||
:print-length *print-length*
|
||||
:print-level *print-level*
|
||||
:print-meta *print-meta*}
|
||||
options))))
|
||||
(merge
|
||||
{:width 80
|
||||
:symbols {}
|
||||
:print-length *print-length*
|
||||
:print-level *print-level*
|
||||
:print-meta *print-meta*}
|
||||
options))))
|
||||
|
||||
(defn pprint
|
||||
([x] (pprint x {}))
|
||||
|
|
@ -209,13 +209,13 @@
|
|||
(defn exception-str [message source printer]
|
||||
(with-out-str
|
||||
(print-doc
|
||||
[:group
|
||||
(title "Router creation failed" source printer)
|
||||
[:break] [:break]
|
||||
message
|
||||
[:break]
|
||||
(footer printer)]
|
||||
printer)))
|
||||
[:group
|
||||
(title "Router creation failed" source printer)
|
||||
[:break] [:break]
|
||||
message
|
||||
[:break]
|
||||
(footer printer)]
|
||||
printer)))
|
||||
|
||||
(defmulti format-exception (fn [type _ _] type))
|
||||
|
||||
|
|
@ -231,11 +231,11 @@
|
|||
|
||||
(defn de-expound-colors [^String s mappings]
|
||||
(let [s' (reduce
|
||||
(fn [s [from to]]
|
||||
(.replace ^String s
|
||||
^String (expound.ansi/esc [from])
|
||||
^String (-start (colors to))))
|
||||
s mappings)]
|
||||
(fn [s [from to]]
|
||||
(.replace ^String s
|
||||
^String (expound.ansi/esc [from])
|
||||
^String (-start (colors to))))
|
||||
s mappings)]
|
||||
(.replace ^String s'
|
||||
^String (expound.ansi/esc [:none])
|
||||
(str (expound.ansi/esc [:none]) (-start (colors :text))))))
|
||||
|
|
@ -254,9 +254,9 @@
|
|||
|
||||
(def expound-printer
|
||||
(expound.alpha/custom-printer
|
||||
{:theme :figwheel-theme
|
||||
:show-valid-values? false
|
||||
:print-specs? false}))
|
||||
{:theme :figwheel-theme
|
||||
:show-valid-values? false
|
||||
:print-specs? false}))
|
||||
|
||||
;;
|
||||
;; Formatters
|
||||
|
|
@ -276,18 +276,18 @@
|
|||
" ")
|
||||
(edn (not-empty (select-keys route-data [:conflicting])))])]
|
||||
(into
|
||||
[:group]
|
||||
(mapv
|
||||
(fn [[[path route-data] vals]]
|
||||
[:group
|
||||
(path-report path route-data)
|
||||
(into
|
||||
[:group]
|
||||
(map
|
||||
(fn [[path route-data]] (path-report path route-data))
|
||||
vals))
|
||||
[:break]])
|
||||
conflicts)))
|
||||
[:group]
|
||||
(mapv
|
||||
(fn [[[path route-data] vals]]
|
||||
[:group
|
||||
(path-report path route-data)
|
||||
(into
|
||||
[:group]
|
||||
(map
|
||||
(fn [[path route-data]] (path-report path route-data))
|
||||
vals))
|
||||
[:break]])
|
||||
conflicts)))
|
||||
[:span (text "Either fix the conflicting paths or disable the conflict resolution")
|
||||
[:break] (text "by setting route data for conflicting route: ") [:break] [:break]
|
||||
(edn {:conflicting true} {:margin 3})
|
||||
|
|
@ -302,19 +302,19 @@
|
|||
(text "Router contains conflicting route names:")
|
||||
[:break] [:break]
|
||||
(into
|
||||
[:group]
|
||||
(mapv
|
||||
(fn [[name vals]]
|
||||
[:group
|
||||
[:span (text name)]
|
||||
[:break]
|
||||
(into
|
||||
[:group]
|
||||
(map
|
||||
(fn [p] [:span (color :grey "-> " p) [:break]])
|
||||
(mapv first vals)))
|
||||
[:break]])
|
||||
conflicts))
|
||||
[:group]
|
||||
(mapv
|
||||
(fn [[name vals]]
|
||||
[:group
|
||||
[:span (text name)]
|
||||
[:break]
|
||||
(into
|
||||
[:group]
|
||||
(map
|
||||
(fn [p] [:span (color :grey "-> " p) [:break]])
|
||||
(mapv first vals)))
|
||||
[:break]])
|
||||
conflicts))
|
||||
(color :white "https://cljdoc.org/d/metosin/reitit/CURRENT/doc/basics/route-conflicts")
|
||||
[:break]])
|
||||
|
||||
|
|
@ -323,22 +323,22 @@
|
|||
(text "Invalid route data:")
|
||||
[:break] [:break]
|
||||
(into
|
||||
[:group]
|
||||
(map
|
||||
(fn [{:keys [data path spec scope]}]
|
||||
[:group
|
||||
[:span (color :grey "-- On route -----------------------")]
|
||||
[:break]
|
||||
[:break]
|
||||
(text path) (if scope [:span " " (text scope)])
|
||||
[:break]
|
||||
[:break]
|
||||
(-> (s/explain-data spec data)
|
||||
(expound-printer)
|
||||
(with-out-str)
|
||||
(fippify))
|
||||
[:break]])
|
||||
problems))
|
||||
[:group]
|
||||
(map
|
||||
(fn [{:keys [data path spec scope]}]
|
||||
[:group
|
||||
[:span (color :grey "-- On route -----------------------")]
|
||||
[:break]
|
||||
[:break]
|
||||
(text path) (if scope [:span " " (text scope)])
|
||||
[:break]
|
||||
[:break]
|
||||
(-> (s/explain-data spec data)
|
||||
(expound-printer)
|
||||
(with-out-str)
|
||||
(fippify))
|
||||
[:break]])
|
||||
problems))
|
||||
(color :white "https://cljdoc.org/d/metosin/reitit/CURRENT/doc/basics/route-data-validation")
|
||||
[:break]])
|
||||
|
||||
|
|
|
|||
|
|
@ -64,11 +64,11 @@
|
|||
(let [defined (-> path-params keys set)
|
||||
missing (set/difference (:required match) defined)]
|
||||
(js/console.warn
|
||||
"missing path-params for route" name
|
||||
{:template (:template match)
|
||||
:missing missing
|
||||
:path-params path-params
|
||||
:required (:required match)})
|
||||
"missing path-params for route" name
|
||||
{:template (:template match)
|
||||
:missing missing
|
||||
:path-params path-params
|
||||
:required (:required match)})
|
||||
nil))
|
||||
match)
|
||||
(do (js/console.warn "missing route" name)
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
(when (nil? @history)
|
||||
(reset! history this))
|
||||
(on-navigate m this))
|
||||
opts))
|
||||
opts))
|
||||
|
||||
(defn
|
||||
^{:see-also ["reitit.frontend.history/href"]}
|
||||
|
|
|
|||
|
|
@ -9,16 +9,16 @@
|
|||
|
||||
(defn coerce-handler [[path data] {:keys [expand] :as opts}]
|
||||
[path (reduce
|
||||
(fn [acc method]
|
||||
(if (contains? acc method)
|
||||
(update acc method expand opts)
|
||||
acc)) data ring/http-methods)])
|
||||
(fn [acc method]
|
||||
(if (contains? acc method)
|
||||
(update acc method expand opts)
|
||||
acc)) data ring/http-methods)])
|
||||
|
||||
(defn compile-result [[path data] {:keys [::default-options-endpoint expand] :as opts}]
|
||||
(let [[top childs] (ring/group-keys data)
|
||||
childs (cond-> childs
|
||||
(and (not (:options childs)) (not (:handler top)) default-options-endpoint)
|
||||
(assoc :options (expand default-options-endpoint opts)))
|
||||
(and (not (:options childs)) (not (:handler top)) default-options-endpoint)
|
||||
(assoc :options (expand default-options-endpoint opts)))
|
||||
compile (fn [[path data] opts scope]
|
||||
(interceptor/compile-result [path data] opts scope))
|
||||
->endpoint (fn [p d m s]
|
||||
|
|
@ -29,19 +29,19 @@
|
|||
(assoc :method m))))
|
||||
->methods (fn [any? data]
|
||||
(reduce
|
||||
(fn [acc method]
|
||||
(cond-> acc
|
||||
any? (assoc method (->endpoint path data method nil))))
|
||||
(ring/map->Methods {})
|
||||
ring/http-methods))]
|
||||
(fn [acc method]
|
||||
(cond-> acc
|
||||
any? (assoc method (->endpoint path data method nil))))
|
||||
(ring/map->Methods {})
|
||||
ring/http-methods))]
|
||||
(if-not (seq childs)
|
||||
(->methods true top)
|
||||
(reduce-kv
|
||||
(fn [acc method data]
|
||||
(let [data (meta-merge top data)]
|
||||
(assoc acc method (->endpoint path data method method))))
|
||||
(->methods (:handler top) data)
|
||||
childs))))
|
||||
(fn [acc method data]
|
||||
(let [data (meta-merge top data)]
|
||||
(assoc acc method (->endpoint path data method method))))
|
||||
(->methods (:handler top) data)
|
||||
childs))))
|
||||
|
||||
(defn router
|
||||
"Creates a [[reitit.core/Router]] from raw route data and optionally an options map with
|
||||
|
|
@ -133,7 +133,7 @@
|
|||
(assoc ::interceptor/queue (partial interceptor/queue executor))
|
||||
(dissoc :data) ; data is already merged into routes
|
||||
(cond-> (seq interceptors)
|
||||
(update-in [:data :interceptors] (partial into (vec interceptors)))))
|
||||
(update-in [:data :interceptors] (partial into (vec interceptors)))))
|
||||
router (reitit.http/router (r/routes router) router-opts) ;; will re-compile the interceptors
|
||||
enrich-request (ring/create-enrich-request inject-match? inject-router?)
|
||||
enrich-default-request (ring/create-enrich-default-request inject-router?)]
|
||||
|
|
|
|||
|
|
@ -22,5 +22,5 @@
|
|||
[routes {:keys [spec ::rs/wrap] :or {spec ::data, wrap identity}}]
|
||||
(when-let [problems (rrs/validate-route-data routes :interceptors wrap spec)]
|
||||
(exception/fail!
|
||||
::rs/invalid-route-data
|
||||
{:problems problems})))
|
||||
::rs/invalid-route-data
|
||||
{:problems problems})))
|
||||
|
|
|
|||
|
|
@ -36,16 +36,16 @@
|
|||
[stages {:keys [enter leave error name] :as interceptor}]
|
||||
(if (->> (select-keys interceptor stages) (vals) (keep identity) (seq))
|
||||
(cond-> {:name ::diff}
|
||||
(and enter (stages :enter)) (assoc :enter (handle name :enter))
|
||||
(and leave (stages :leave)) (assoc :leave (handle name :leave))
|
||||
(and error (stages :error)) (assoc :error (handle name :error)))))
|
||||
(and enter (stages :enter)) (assoc :enter (handle name :enter))
|
||||
(and leave (stages :leave)) (assoc :leave (handle name :leave))
|
||||
(and error (stages :error)) (assoc :error (handle name :error)))))
|
||||
|
||||
(defn print-context-diffs
|
||||
"A interceptor chain transformer that adds a context diff printer between all interceptors"
|
||||
[interceptors]
|
||||
(reduce
|
||||
(fn [chain interceptor]
|
||||
(into chain (keep identity [(diff-interceptor #{:leave :error} interceptor)
|
||||
interceptor
|
||||
(diff-interceptor #{:enter} interceptor)])))
|
||||
[(diff-interceptor #{:enter :leave :error} {:enter identity})] interceptors))
|
||||
(fn [chain interceptor]
|
||||
(into chain (keep identity [(diff-interceptor #{:leave :error} interceptor)
|
||||
interceptor
|
||||
(diff-interceptor #{:enter} interceptor)])))
|
||||
[(diff-interceptor #{:enter :leave :error} {:enter identity})] interceptors))
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
error-handler (or (get handlers type)
|
||||
(get handlers ex-class)
|
||||
(some
|
||||
(partial get handlers)
|
||||
(descendants type))
|
||||
(partial get handlers)
|
||||
(descendants type))
|
||||
(some
|
||||
(partial get handlers)
|
||||
(super-classes ex-class))
|
||||
(partial get handlers)
|
||||
(super-classes ex-class))
|
||||
(get handlers ::default))]
|
||||
(if-let [wrap (get handlers ::wrap)]
|
||||
(wrap error-handler error request)
|
||||
|
|
|
|||
|
|
@ -18,14 +18,14 @@
|
|||
(def temp-file-part
|
||||
"Spec for file param created by ring.middleware.multipart-params.temp-file store."
|
||||
(st/spec
|
||||
{:spec (s/keys :req-un [::filename ::content-type ::tempfile ::size])
|
||||
:swagger/type "file"}))
|
||||
{:spec (s/keys :req-un [::filename ::content-type ::tempfile ::size])
|
||||
:swagger/type "file"}))
|
||||
|
||||
(def bytes-part
|
||||
"Spec for file param created by ring.middleware.multipart-params.byte-array store."
|
||||
(st/spec
|
||||
{:spec (s/keys :req-un [::filename ::content-type ::bytes])
|
||||
:swagger/type "file"}))
|
||||
{:spec (s/keys :req-un [::filename ::content-type ::bytes])
|
||||
:swagger/type "file"}))
|
||||
|
||||
(defn- coerced-request [request coercers]
|
||||
(if-let [coerced (if coercers (coercion/coerce-request coercers request))]
|
||||
|
|
@ -49,7 +49,7 @@
|
|||
:compile (fn [{:keys [parameters coercion]} opts]
|
||||
(if-let [multipart (:multipart parameters)]
|
||||
(let [parameter-coercion {:multipart (coercion/->ParameterCoercion
|
||||
:multipart-params :string true true)}
|
||||
:multipart-params :string true true)}
|
||||
opts (assoc opts ::coercion/parameter-coercion parameter-coercion)
|
||||
coercers (if multipart (coercion/request-coercers coercion parameters opts))]
|
||||
{:data {:swagger {:consumes ^:replace #{"multipart/form-data"}}}
|
||||
|
|
|
|||
|
|
@ -40,10 +40,10 @@
|
|||
:compile (fn [{:keys [muuntaja parameters]} _]
|
||||
(if-let [muuntaja (or muuntaja default-muuntaja)]
|
||||
(merge
|
||||
(stripped (muuntaja.interceptor/format-interceptor muuntaja))
|
||||
(if (publish-swagger-data? parameters)
|
||||
{:data {:swagger {:produces (displace (m/encodes muuntaja))
|
||||
:consumes (displace (m/decodes muuntaja))}}}))))}))
|
||||
(stripped (muuntaja.interceptor/format-interceptor muuntaja))
|
||||
(if (publish-swagger-data? parameters)
|
||||
{:data {:swagger {:produces (displace (m/encodes muuntaja))
|
||||
:consumes (displace (m/decodes muuntaja))}}}))))}))
|
||||
|
||||
(defn format-negotiate-interceptor
|
||||
"Interceptor for content-negotiation.
|
||||
|
|
@ -87,9 +87,9 @@
|
|||
:compile (fn [{:keys [muuntaja parameters]} _]
|
||||
(if-let [muuntaja (or muuntaja default-muuntaja)]
|
||||
(merge
|
||||
(stripped (muuntaja.interceptor/format-request-interceptor muuntaja))
|
||||
(when (publish-swagger-data? parameters)
|
||||
{:data {:swagger {:consumes (displace (m/decodes muuntaja))}}}))))}))
|
||||
(stripped (muuntaja.interceptor/format-request-interceptor muuntaja))
|
||||
(when (publish-swagger-data? parameters)
|
||||
{:data {:swagger {:consumes (displace (m/decodes muuntaja))}}}))))}))
|
||||
|
||||
(defn format-response-interceptor
|
||||
"Interceptor for response formatting.
|
||||
|
|
@ -112,6 +112,6 @@
|
|||
:compile (fn [{:keys [muuntaja parameters]} _]
|
||||
(if-let [muuntaja (or muuntaja default-muuntaja)]
|
||||
(merge
|
||||
(stripped (muuntaja.interceptor/format-response-interceptor muuntaja))
|
||||
(when (publish-swagger-data? parameters)
|
||||
{:data {:swagger {:produces (displace (m/encodes muuntaja))}}}))))}))
|
||||
(stripped (muuntaja.interceptor/format-response-interceptor muuntaja))
|
||||
(when (publish-swagger-data? parameters)
|
||||
{:data {:swagger {:produces (displace (m/encodes muuntaja))}}}))))}))
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@
|
|||
(reify TransformationProvider
|
||||
(-transformer [_ {:keys [strip-extra-keys default-values]}]
|
||||
(mt/transformer
|
||||
(if strip-extra-keys (mt/strip-extra-keys-transformer))
|
||||
transformer
|
||||
(if default-values (mt/default-value-transformer))))))
|
||||
(if strip-extra-keys (mt/strip-extra-keys-transformer))
|
||||
transformer
|
||||
(if default-values (mt/default-value-transformer))))))
|
||||
|
||||
(def string-transformer-provider (-provider (mt/string-transformer)))
|
||||
(def json-transformer-provider (-provider (mt/json-transformer)))
|
||||
|
|
@ -61,7 +61,7 @@
|
|||
transformed
|
||||
(let [error (-explain coercer transformed)]
|
||||
(coercion/map->CoercionError
|
||||
(assoc error :transformed transformed)))))
|
||||
(assoc error :transformed transformed)))))
|
||||
value))
|
||||
;; encode: decode -> validate -> encode
|
||||
(fn [value format]
|
||||
|
|
@ -71,7 +71,7 @@
|
|||
(-encode coercer transformed)
|
||||
(let [error (-explain coercer transformed)]
|
||||
(coercion/map->CoercionError
|
||||
(assoc error :transformed transformed))))
|
||||
(assoc error :transformed transformed))))
|
||||
value))))))))
|
||||
|
||||
;;
|
||||
|
|
@ -91,15 +91,15 @@
|
|||
(defmethod extract-parameter :default [in schema options]
|
||||
(let [{:keys [properties required]} (swagger/transform schema (merge options {:in in, :type :parameter}))]
|
||||
(mapv
|
||||
(fn [[k {:keys [type] :as schema}]]
|
||||
(merge
|
||||
{:in (name in)
|
||||
:name k
|
||||
:description (:description schema "")
|
||||
:type type
|
||||
:required (contains? (set required) k)}
|
||||
schema))
|
||||
properties)))
|
||||
(fn [[k {:keys [type] :as schema}]]
|
||||
(merge
|
||||
{:in (name in)
|
||||
:name k
|
||||
:description (:description schema "")
|
||||
:type type
|
||||
:required (contains? (set required) k)}
|
||||
schema))
|
||||
properties)))
|
||||
|
||||
;;
|
||||
;; public api
|
||||
|
|
@ -143,39 +143,39 @@
|
|||
(-get-apidocs [_ specification {:keys [parameters responses]}]
|
||||
(case specification
|
||||
:swagger (merge
|
||||
(if parameters
|
||||
{:parameters
|
||||
(->> (for [[in schema] parameters
|
||||
parameter (extract-parameter in (compile schema options) options)]
|
||||
parameter)
|
||||
(into []))})
|
||||
(if responses
|
||||
{:responses
|
||||
(into
|
||||
(empty responses)
|
||||
(for [[status response] responses]
|
||||
[status (as-> response $
|
||||
(set/rename-keys $ {:body :schema})
|
||||
(update $ :description (fnil identity ""))
|
||||
(if (:schema $)
|
||||
(-> $
|
||||
(update :schema compile options)
|
||||
(update :schema swagger/transform {:type :schema}))
|
||||
$))]))}))
|
||||
(if parameters
|
||||
{:parameters
|
||||
(->> (for [[in schema] parameters
|
||||
parameter (extract-parameter in (compile schema options) options)]
|
||||
parameter)
|
||||
(into []))})
|
||||
(if responses
|
||||
{:responses
|
||||
(into
|
||||
(empty responses)
|
||||
(for [[status response] responses]
|
||||
[status (as-> response $
|
||||
(set/rename-keys $ {:body :schema})
|
||||
(update $ :description (fnil identity ""))
|
||||
(if (:schema $)
|
||||
(-> $
|
||||
(update :schema compile options)
|
||||
(update :schema swagger/transform {:type :schema}))
|
||||
$))]))}))
|
||||
(throw
|
||||
(ex-info
|
||||
(str "Can't produce Schema apidocs for " specification)
|
||||
{:type specification, :coercion :schema}))))
|
||||
(ex-info
|
||||
(str "Can't produce Schema apidocs for " specification)
|
||||
{:type specification, :coercion :schema}))))
|
||||
(-compile-model [_ model _] (compile model options))
|
||||
(-open-model [_ schema] schema)
|
||||
(-encode-error [_ error]
|
||||
(cond-> error
|
||||
(show? :humanized) (assoc :humanized (me/humanize error {:wrap :message}))
|
||||
(show? :schema) (update :schema edn/write-string opts)
|
||||
(show? :errors) (-> (me/with-error-messages opts)
|
||||
(update :errors (partial map #(update % :schema edn/write-string opts))))
|
||||
(seq error-keys) (select-keys error-keys)
|
||||
encode-error (encode-error)))
|
||||
(show? :humanized) (assoc :humanized (me/humanize error {:wrap :message}))
|
||||
(show? :schema) (update :schema edn/write-string opts)
|
||||
(show? :errors) (-> (me/with-error-messages opts)
|
||||
(update :errors (partial map #(update % :schema edn/write-string opts))))
|
||||
(seq error-keys) (select-keys error-keys)
|
||||
encode-error (encode-error)))
|
||||
(-request-coercer [_ type schema]
|
||||
(-coercer (compile schema options) type transformers :decode opts))
|
||||
(-response-coercer [_ schema]
|
||||
|
|
|
|||
|
|
@ -48,6 +48,6 @@
|
|||
printer between all middleware."
|
||||
[chain]
|
||||
(reduce
|
||||
(fn [chain mw]
|
||||
(into chain [mw (print-diff-middleware (select-keys mw [:name]))]))
|
||||
[(print-diff-middleware)] chain))
|
||||
(fn [chain mw]
|
||||
(into chain [mw (print-diff-middleware (select-keys mw [:name]))]))
|
||||
[(print-diff-middleware)] chain))
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
error-handler (or (get handlers type)
|
||||
(get handlers ex-class)
|
||||
(some
|
||||
(partial get handlers)
|
||||
(descendants type))
|
||||
(partial get handlers)
|
||||
(descendants type))
|
||||
(some
|
||||
(partial get handlers)
|
||||
(super-classes ex-class))
|
||||
(partial get handlers)
|
||||
(super-classes ex-class))
|
||||
(get handlers ::default))]
|
||||
(if-let [wrap (get handlers ::wrap)]
|
||||
(wrap error-handler error request)
|
||||
|
|
|
|||
|
|
@ -15,14 +15,14 @@
|
|||
(def temp-file-part
|
||||
"Spec for file param created by ring.middleware.multipart-params.temp-file store."
|
||||
(st/spec
|
||||
{:spec (s/keys :req-un [::filename ::content-type ::tempfile ::size])
|
||||
:swagger/type "file"}))
|
||||
{:spec (s/keys :req-un [::filename ::content-type ::tempfile ::size])
|
||||
:swagger/type "file"}))
|
||||
|
||||
(def bytes-part
|
||||
"Spec for file param created by ring.middleware.multipart-params.byte-array store."
|
||||
(st/spec
|
||||
{:spec (s/keys :req-un [::filename ::content-type ::bytes])
|
||||
:swagger/type "file"}))
|
||||
{:spec (s/keys :req-un [::filename ::content-type ::bytes])
|
||||
:swagger/type "file"}))
|
||||
|
||||
(defn- coerced-request [request coercers]
|
||||
(if-let [coerced (if coercers (coercion/coerce-request coercers request))]
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
(fn [{:keys [parameters coercion]} opts]
|
||||
(if-let [multipart (:multipart parameters)]
|
||||
(let [parameter-coercion {:multipart (coercion/->ParameterCoercion
|
||||
:multipart-params :string true true)}
|
||||
:multipart-params :string true true)}
|
||||
opts (assoc opts ::coercion/parameter-coercion parameter-coercion)
|
||||
coercers (if multipart (coercion/request-coercers coercion parameters opts))]
|
||||
{:data {:swagger {:consumes ^:replace #{"multipart/form-data"}}}
|
||||
|
|
|
|||
|
|
@ -34,10 +34,10 @@
|
|||
:compile (fn [{:keys [muuntaja parameters]} _]
|
||||
(if muuntaja
|
||||
(merge
|
||||
(if (publish-swagger-data? parameters)
|
||||
{:data {:swagger {:produces (displace (m/encodes muuntaja))
|
||||
:consumes (displace (m/decodes muuntaja))}}})
|
||||
{:wrap #(muuntaja.middleware/wrap-format % muuntaja)})))})
|
||||
(if (publish-swagger-data? parameters)
|
||||
{:data {:swagger {:produces (displace (m/encodes muuntaja))
|
||||
:consumes (displace (m/decodes muuntaja))}}})
|
||||
{:wrap #(muuntaja.middleware/wrap-format % muuntaja)})))})
|
||||
|
||||
(def format-negotiate-middleware
|
||||
"Middleware for content-negotiation.
|
||||
|
|
@ -71,9 +71,9 @@
|
|||
:compile (fn [{:keys [muuntaja parameters]} _]
|
||||
(if muuntaja
|
||||
(merge
|
||||
(when (publish-swagger-data? parameters)
|
||||
{:data {:swagger {:consumes (displace (m/decodes muuntaja))}}})
|
||||
{:wrap #(muuntaja.middleware/wrap-format-request % muuntaja)})))})
|
||||
(when (publish-swagger-data? parameters)
|
||||
{:data {:swagger {:consumes (displace (m/decodes muuntaja))}}})
|
||||
{:wrap #(muuntaja.middleware/wrap-format-request % muuntaja)})))})
|
||||
|
||||
(def format-response-middleware
|
||||
"Middleware for response formatting.
|
||||
|
|
@ -91,6 +91,6 @@
|
|||
:compile (fn [{:keys [muuntaja parameters]} _]
|
||||
(if muuntaja
|
||||
(merge
|
||||
(when (publish-swagger-data? parameters)
|
||||
{:data {:swagger {:produces (displace (m/encodes muuntaja))}}})
|
||||
{:wrap #(muuntaja.middleware/wrap-format-response % muuntaja)})))})
|
||||
(when (publish-swagger-data? parameters)
|
||||
{:data {:swagger {:produces (displace (m/encodes muuntaja))}}})
|
||||
{:wrap #(muuntaja.middleware/wrap-format-response % muuntaja)})))})
|
||||
|
|
|
|||
|
|
@ -36,9 +36,9 @@
|
|||
interceptor
|
||||
(->> (select-keys interceptor [:enter :leave :error]) (vals) (keep identity) (seq))
|
||||
(interceptor/interceptor
|
||||
(if (error-without-arity-2? interceptor)
|
||||
(wrap-error-arity-2->1 interceptor)
|
||||
interceptor))))
|
||||
(if (error-without-arity-2? interceptor)
|
||||
(wrap-error-arity-2->1 interceptor)
|
||||
interceptor))))
|
||||
|
||||
;;
|
||||
;; Public API
|
||||
|
|
@ -62,11 +62,11 @@
|
|||
(routing-interceptor router default-handler nil))
|
||||
([router default-handler {:keys [interceptors]}]
|
||||
(interceptor/interceptor
|
||||
(reitit.http/routing-interceptor
|
||||
router
|
||||
default-handler
|
||||
{:executor pedestal-executor
|
||||
:interceptors interceptors}))))
|
||||
(reitit.http/routing-interceptor
|
||||
router
|
||||
default-handler
|
||||
{:executor pedestal-executor
|
||||
:interceptors interceptors}))))
|
||||
|
||||
(defn replace-last-interceptor [service-map interceptor]
|
||||
(-> service-map
|
||||
|
|
|
|||
|
|
@ -17,23 +17,23 @@
|
|||
|
||||
(defn ^:no-wiki group-keys [data]
|
||||
(reduce-kv
|
||||
(fn [[top childs] k v]
|
||||
(if (http-methods k)
|
||||
[top (assoc childs k v)]
|
||||
[(assoc top k v) childs])) [{} {}] data))
|
||||
(fn [[top childs] k v]
|
||||
(if (http-methods k)
|
||||
[top (assoc childs k v)]
|
||||
[(assoc top k v) childs])) [{} {}] data))
|
||||
|
||||
(defn coerce-handler [[path data] {:keys [expand] :as opts}]
|
||||
[path (reduce
|
||||
(fn [acc method]
|
||||
(if (contains? acc method)
|
||||
(update acc method expand opts)
|
||||
acc)) data http-methods)])
|
||||
(fn [acc method]
|
||||
(if (contains? acc method)
|
||||
(update acc method expand opts)
|
||||
acc)) data http-methods)])
|
||||
|
||||
(defn compile-result [[path data] {:keys [::default-options-endpoint expand] :as opts}]
|
||||
(let [[top childs] (group-keys data)
|
||||
childs (cond-> childs
|
||||
(and (not (:options childs)) (not (:handler top)) default-options-endpoint)
|
||||
(assoc :options (expand default-options-endpoint opts)))
|
||||
(and (not (:options childs)) (not (:handler top)) default-options-endpoint)
|
||||
(assoc :options (expand default-options-endpoint opts)))
|
||||
->endpoint (fn [p d m s]
|
||||
(-> (middleware/compile-result [p d] opts s)
|
||||
(map->Endpoint)
|
||||
|
|
@ -41,19 +41,19 @@
|
|||
(assoc :method m)))
|
||||
->methods (fn [any? data]
|
||||
(reduce
|
||||
(fn [acc method]
|
||||
(cond-> acc
|
||||
any? (assoc method (->endpoint path data method nil))))
|
||||
(map->Methods {})
|
||||
http-methods))]
|
||||
(fn [acc method]
|
||||
(cond-> acc
|
||||
any? (assoc method (->endpoint path data method nil))))
|
||||
(map->Methods {})
|
||||
http-methods))]
|
||||
(if-not (seq childs)
|
||||
(->methods true top)
|
||||
(reduce-kv
|
||||
(fn [acc method data]
|
||||
(let [data (meta-merge top data)]
|
||||
(assoc acc method (->endpoint path data method method))))
|
||||
(->methods (:handler top) data)
|
||||
childs))))
|
||||
(fn [acc method data]
|
||||
(let [data (meta-merge top data)]
|
||||
(assoc acc method (->endpoint path data method method))))
|
||||
(->methods (:handler top) data)
|
||||
childs))))
|
||||
|
||||
(def default-options-handler
|
||||
(let [handle (fn [request]
|
||||
|
|
@ -318,26 +318,26 @@
|
|||
enrich-default-request (create-enrich-default-request inject-router?)]
|
||||
(with-meta
|
||||
(wrap
|
||||
(fn
|
||||
([request]
|
||||
(if-let [match (r/match-by-path router (:uri request))]
|
||||
(let [method (:request-method request)
|
||||
path-params (:path-params match)
|
||||
result (:result match)
|
||||
handler (-> result method :handler (or default-handler))
|
||||
request (enrich-request request path-params match router)]
|
||||
(or (handler request) (default-handler request)))
|
||||
(default-handler (enrich-default-request request router))))
|
||||
([request respond raise]
|
||||
(if-let [match (r/match-by-path router (:uri request))]
|
||||
(let [method (:request-method request)
|
||||
path-params (:path-params match)
|
||||
result (:result match)
|
||||
handler (-> result method :handler (or default-handler))
|
||||
request (enrich-request request path-params match router)]
|
||||
((routes handler default-handler) request respond raise))
|
||||
(default-handler (enrich-default-request request router) respond raise))
|
||||
nil)))
|
||||
(fn
|
||||
([request]
|
||||
(if-let [match (r/match-by-path router (:uri request))]
|
||||
(let [method (:request-method request)
|
||||
path-params (:path-params match)
|
||||
result (:result match)
|
||||
handler (-> result method :handler (or default-handler))
|
||||
request (enrich-request request path-params match router)]
|
||||
(or (handler request) (default-handler request)))
|
||||
(default-handler (enrich-default-request request router))))
|
||||
([request respond raise]
|
||||
(if-let [match (r/match-by-path router (:uri request))]
|
||||
(let [method (:request-method request)
|
||||
path-params (:path-params match)
|
||||
result (:result match)
|
||||
handler (-> result method :handler (or default-handler))
|
||||
request (enrich-request request path-params match router)]
|
||||
((routes handler default-handler) request respond raise))
|
||||
(default-handler (enrich-default-request request router) respond raise))
|
||||
nil)))
|
||||
{::r/router router}))))
|
||||
|
||||
(defn get-router [handler]
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
::coercion/response-coercion 500
|
||||
nil)]
|
||||
(respond
|
||||
{:status status
|
||||
:body (coercion/encode-error data)})
|
||||
{:status status
|
||||
:body (coercion/encode-error data)})
|
||||
(raise e))))
|
||||
|
||||
;;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
(s/def ::trace map?)
|
||||
(s/def ::patch map?)
|
||||
|
||||
|
||||
(s/def ::data
|
||||
(s/keys :opt-un [::rs/handler ::rs/name ::rs/no-doc ::middleware]))
|
||||
|
||||
|
|
@ -30,9 +29,9 @@
|
|||
(defn merge-specs [specs]
|
||||
(when-let [non-specs (seq (remove #(or (s/spec? %) (s/get-spec %)) specs))]
|
||||
(exception/fail!
|
||||
::invalid-specs
|
||||
{:specs specs
|
||||
:invalid non-specs}))
|
||||
::invalid-specs
|
||||
{:specs specs
|
||||
:invalid non-specs}))
|
||||
(s/merge-spec-impl (vec specs) (vec specs) nil))
|
||||
|
||||
(defn validate-route-data [routes key wrap spec]
|
||||
|
|
@ -51,5 +50,5 @@
|
|||
[routes {:keys [spec ::rs/wrap] :or {spec ::data, wrap identity}}]
|
||||
(when-let [problems (validate-route-data routes :middleware wrap spec)]
|
||||
(exception/fail!
|
||||
::rs/invalid-route-data
|
||||
{:problems problems})))
|
||||
::rs/invalid-route-data
|
||||
{:problems problems})))
|
||||
|
|
|
|||
|
|
@ -23,16 +23,16 @@
|
|||
|
||||
(defn stringify [schema]
|
||||
(walk/prewalk
|
||||
(fn [x]
|
||||
(cond
|
||||
#?@(:clj [(class? x) (.getName ^Class x)])
|
||||
(instance? schema.core.OptionalKey x) (pr-str (list 'opt (:k x)))
|
||||
(instance? schema.core.RequiredKey x) (pr-str (list 'req (:k x)))
|
||||
(and (satisfies? s/Schema x) (record? x)) (try (pr-str (s/explain x)) (catch #?(:clj Exception :cljs js/Error) _ x))
|
||||
(instance? schema.utils.ValidationError x) (str (su/validation-error-explain x))
|
||||
(instance? schema.utils.NamedError x) (str (su/named-error-explain x))
|
||||
:else x))
|
||||
schema))
|
||||
(fn [x]
|
||||
(cond
|
||||
#?@(:clj [(class? x) (.getName ^Class x)])
|
||||
(instance? schema.core.OptionalKey x) (pr-str (list 'opt (:k x)))
|
||||
(instance? schema.core.RequiredKey x) (pr-str (list 'req (:k x)))
|
||||
(and (satisfies? s/Schema x) (record? x)) (try (pr-str (s/explain x)) (catch #?(:clj Exception :cljs js/Error) _ x))
|
||||
(instance? schema.utils.ValidationError x) (str (su/validation-error-explain x))
|
||||
(instance? schema.utils.NamedError x) (str (su/named-error-explain x))
|
||||
:else x))
|
||||
schema))
|
||||
|
||||
(def default-options
|
||||
{:coerce-response? coerce-response?
|
||||
|
|
@ -50,27 +50,27 @@
|
|||
;; TODO: this looks identical to spec, refactor when schema is done.
|
||||
(case specification
|
||||
:swagger (swagger/swagger-spec
|
||||
(merge
|
||||
(if parameters
|
||||
{::swagger/parameters
|
||||
(into
|
||||
(empty parameters)
|
||||
(for [[k v] parameters]
|
||||
[k (coercion/-compile-model this v nil)]))})
|
||||
(if responses
|
||||
{::swagger/responses
|
||||
(into
|
||||
(empty responses)
|
||||
(for [[k response] responses]
|
||||
[k (as-> response $
|
||||
(set/rename-keys $ {:body :schema})
|
||||
(if (:schema $)
|
||||
(update $ :schema #(coercion/-compile-model this % nil))
|
||||
$))]))})))
|
||||
(merge
|
||||
(if parameters
|
||||
{::swagger/parameters
|
||||
(into
|
||||
(empty parameters)
|
||||
(for [[k v] parameters]
|
||||
[k (coercion/-compile-model this v nil)]))})
|
||||
(if responses
|
||||
{::swagger/responses
|
||||
(into
|
||||
(empty responses)
|
||||
(for [[k response] responses]
|
||||
[k (as-> response $
|
||||
(set/rename-keys $ {:body :schema})
|
||||
(if (:schema $)
|
||||
(update $ :schema #(coercion/-compile-model this % nil))
|
||||
$))]))})))
|
||||
(throw
|
||||
(ex-info
|
||||
(str "Can't produce Schema apidocs for " specification)
|
||||
{:type specification, :coercion :schema}))))
|
||||
(ex-info
|
||||
(str "Can't produce Schema apidocs for " specification)
|
||||
{:type specification, :coercion :schema}))))
|
||||
(-compile-model [_ model _] model)
|
||||
(-open-model [_ schema] (st/open-schema schema))
|
||||
(-encode-error [_ error]
|
||||
|
|
@ -88,8 +88,8 @@
|
|||
coerced (coercer value)]
|
||||
(if-let [error (su/error-val coerced)]
|
||||
(coercion/map->CoercionError
|
||||
{:schema schema
|
||||
:errors error})
|
||||
{:schema schema
|
||||
:errors error})
|
||||
coerced))
|
||||
value))))
|
||||
(-response-coercer [this schema]
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@
|
|||
interceptor/Executor
|
||||
(queue [_ interceptors]
|
||||
(queue/into-queue
|
||||
(map
|
||||
(fn [{::interceptor/keys [handler] :as interceptor}]
|
||||
(or handler interceptor))
|
||||
interceptors)))
|
||||
(map
|
||||
(fn [{::interceptor/keys [handler] :as interceptor}]
|
||||
(or handler interceptor))
|
||||
interceptors)))
|
||||
(execute [_ interceptors request]
|
||||
(sieppari/execute interceptors request))
|
||||
(execute [_ interceptors request respond raise]
|
||||
|
|
|
|||
|
|
@ -11,13 +11,13 @@
|
|||
|
||||
(def string-transformer
|
||||
(st/type-transformer
|
||||
st/strip-extra-keys-transformer
|
||||
st/string-transformer))
|
||||
st/strip-extra-keys-transformer
|
||||
st/string-transformer))
|
||||
|
||||
(def json-transformer
|
||||
(st/type-transformer
|
||||
st/strip-extra-keys-transformer
|
||||
st/json-transformer))
|
||||
st/strip-extra-keys-transformer
|
||||
st/json-transformer))
|
||||
|
||||
(def strip-extra-keys-transformer
|
||||
st/strip-extra-keys-transformer)
|
||||
|
|
@ -88,27 +88,27 @@
|
|||
(-get-apidocs [this specification {:keys [parameters responses]}]
|
||||
(case specification
|
||||
:swagger (swagger/swagger-spec
|
||||
(merge
|
||||
(if parameters
|
||||
{::swagger/parameters
|
||||
(into
|
||||
(empty parameters)
|
||||
(for [[k v] parameters]
|
||||
[k (coercion/-compile-model this v nil)]))})
|
||||
(if responses
|
||||
{::swagger/responses
|
||||
(into
|
||||
(empty responses)
|
||||
(for [[k response] responses]
|
||||
[k (as-> response $
|
||||
(set/rename-keys $ {:body :schema})
|
||||
(if (:schema $)
|
||||
(update $ :schema #(coercion/-compile-model this % nil))
|
||||
$))]))})))
|
||||
(merge
|
||||
(if parameters
|
||||
{::swagger/parameters
|
||||
(into
|
||||
(empty parameters)
|
||||
(for [[k v] parameters]
|
||||
[k (coercion/-compile-model this v nil)]))})
|
||||
(if responses
|
||||
{::swagger/responses
|
||||
(into
|
||||
(empty responses)
|
||||
(for [[k response] responses]
|
||||
[k (as-> response $
|
||||
(set/rename-keys $ {:body :schema})
|
||||
(if (:schema $)
|
||||
(update $ :schema #(coercion/-compile-model this % nil))
|
||||
$))]))})))
|
||||
(throw
|
||||
(ex-info
|
||||
(str "Can't produce Spec apidocs for " specification)
|
||||
{:specification specification, :coercion :spec}))))
|
||||
(ex-info
|
||||
(str "Can't produce Spec apidocs for " specification)
|
||||
{:specification specification, :coercion :spec}))))
|
||||
(-compile-model [_ model name]
|
||||
(into-spec model name))
|
||||
(-open-model [_ spec] spec)
|
||||
|
|
@ -129,8 +129,8 @@
|
|||
(if (s/invalid? transformed)
|
||||
(let [problems (st/explain-data spec coerced transformer)]
|
||||
(coercion/map->CoercionError
|
||||
{:spec spec
|
||||
:problems problems}))
|
||||
{:spec spec
|
||||
:problems problems}))
|
||||
(s/unform spec transformed)))))
|
||||
value))))
|
||||
(-response-coercer [this spec]
|
||||
|
|
|
|||
|
|
@ -31,10 +31,10 @@
|
|||
([options]
|
||||
(let [config-json (fn [{:keys [url config]}] (j/write-value-as-string (merge config {:url url})))
|
||||
options (as-> options $
|
||||
(update $ :root (fnil identity "swagger-ui"))
|
||||
(update $ :url (fnil identity "/swagger.json"))
|
||||
(assoc $ :paths {"/config.json" {:headers {"Content-Type" "application/json"}
|
||||
:status 200
|
||||
:body (config-json $)}}))]
|
||||
(update $ :root (fnil identity "swagger-ui"))
|
||||
(update $ :url (fnil identity "/swagger.json"))
|
||||
(assoc $ :paths {"/config.json" {:headers {"Content-Type" "application/json"}
|
||||
:status 200
|
||||
:body (config-json $)}}))]
|
||||
(ring/routes
|
||||
(ring/create-resource-handler options))))))
|
||||
(ring/create-resource-handler options))))))
|
||||
|
|
|
|||
|
|
@ -88,13 +88,13 @@
|
|||
(if (and data (not no-doc))
|
||||
[method
|
||||
(meta-merge
|
||||
base-swagger-spec
|
||||
(apply meta-merge (keep (comp :swagger :data) middleware))
|
||||
(apply meta-merge (keep (comp :swagger :data) interceptors))
|
||||
(if coercion
|
||||
(coercion/get-apidocs coercion :swagger data))
|
||||
(select-keys data [:tags :summary :description])
|
||||
(strip-top-level-keys swagger))]))
|
||||
base-swagger-spec
|
||||
(apply meta-merge (keep (comp :swagger :data) middleware))
|
||||
(apply meta-merge (keep (comp :swagger :data) interceptors))
|
||||
(if coercion
|
||||
(coercion/get-apidocs coercion :swagger data))
|
||||
(select-keys data [:tags :summary :description])
|
||||
(strip-top-level-keys swagger))]))
|
||||
transform-path (fn [[p _ c]]
|
||||
(if-let [endpoint (some->> c (keep transform-endpoint) (seq) (into {}))]
|
||||
[(swagger-path p (r/options router)) endpoint]))
|
||||
|
|
|
|||
|
|
@ -11,11 +11,10 @@
|
|||
wrap (if (pos? (count indent)) vector identity)]
|
||||
(wrap [name {:file (str "doc/" file)}])))
|
||||
(reduce
|
||||
(fn [acc data]
|
||||
(if (vector? (first data))
|
||||
(update-in acc [(dec (count acc)) 2] (fnil into []) data)
|
||||
(conj acc data))
|
||||
) [])
|
||||
(fn [acc data]
|
||||
(if (vector? (first data))
|
||||
(update-in acc [(dec (count acc)) 2] (fnil into []) data)
|
||||
(conj acc data))) [])
|
||||
;; third sweep to flatten chids...
|
||||
(mapv (fn [[n o c]] (if c (into [n o] c) [n o]))))
|
||||
data {:cljdoc/include-namespaces-from-dependencies ['metosin/reitit
|
||||
|
|
|
|||
|
|
@ -17,23 +17,23 @@
|
|||
(create f nil))
|
||||
([f wrap]
|
||||
(http/ring-handler
|
||||
(http/router
|
||||
[["/defaults"
|
||||
{:handler f}]
|
||||
["/coercion"
|
||||
{:interceptors [(reitit.http.coercion/coerce-request-interceptor)
|
||||
(reitit.http.coercion/coerce-response-interceptor)]
|
||||
:coercion reitit.coercion.spec/coercion
|
||||
:parameters {:query {:x int?, :y int?}}
|
||||
:responses {200 {:body {:total pos-int?}}}
|
||||
:handler f}]]
|
||||
{:data {:interceptors [(exception/exception-interceptor
|
||||
(merge
|
||||
exception/default-handlers
|
||||
{::kikka (constantly {:status 400, :body "kikka"})
|
||||
SQLException (constantly {:status 400, :body "sql"})
|
||||
::exception/wrap wrap}))]}})
|
||||
{:executor sieppari/executor})))]
|
||||
(http/router
|
||||
[["/defaults"
|
||||
{:handler f}]
|
||||
["/coercion"
|
||||
{:interceptors [(reitit.http.coercion/coerce-request-interceptor)
|
||||
(reitit.http.coercion/coerce-response-interceptor)]
|
||||
:coercion reitit.coercion.spec/coercion
|
||||
:parameters {:query {:x int?, :y int?}}
|
||||
:responses {200 {:body {:total pos-int?}}}
|
||||
:handler f}]]
|
||||
{:data {:interceptors [(exception/exception-interceptor
|
||||
(merge
|
||||
exception/default-handlers
|
||||
{::kikka (constantly {:status 400, :body "kikka"})
|
||||
SQLException (constantly {:status 400, :body "sql"})
|
||||
::exception/wrap wrap}))]}})
|
||||
{:executor sieppari/executor})))]
|
||||
|
||||
(testing "normal calls work ok"
|
||||
(let [response {:status 200, :body "ok"}
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@
|
|||
(deftest muuntaja-test
|
||||
(let [data {:kikka "kukka"}
|
||||
app (http/ring-handler
|
||||
(http/router
|
||||
["/ping" {:get (constantly {:status 200, :body data})}]
|
||||
{:data {:muuntaja m/instance
|
||||
:interceptors [(muuntaja/format-interceptor)]}})
|
||||
{:executor sieppari/executor})]
|
||||
(http/router
|
||||
["/ping" {:get (constantly {:status 200, :body data})}]
|
||||
{:data {:muuntaja m/instance
|
||||
:interceptors [(muuntaja/format-interceptor)]}})
|
||||
{:executor sieppari/executor})]
|
||||
(is (= data (->> {:request-method :get, :uri "/ping"}
|
||||
(app)
|
||||
:body
|
||||
|
|
@ -24,27 +24,27 @@
|
|||
no-edn-decode (m/create (-> m/default-options (update-in [:formats "application/edn"] dissoc :decoder)))
|
||||
just-edn (m/create (-> m/default-options (m/select-formats ["application/edn"])))
|
||||
app (http/ring-handler
|
||||
(http/router
|
||||
[["/defaults"
|
||||
{:get identity}]
|
||||
["/explicit-defaults"
|
||||
{:muuntaja with-defaults
|
||||
:get identity}]
|
||||
["/no-edn-decode"
|
||||
{:muuntaja no-edn-decode
|
||||
:get identity}]
|
||||
["/just-edn"
|
||||
{:muuntaja just-edn
|
||||
:get identity}]
|
||||
["/form-params"
|
||||
{:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]
|
||||
{:data {:muuntaja m/instance
|
||||
:interceptors [(muuntaja/format-interceptor)]}})
|
||||
{:executor sieppari/executor})
|
||||
(http/router
|
||||
[["/defaults"
|
||||
{:get identity}]
|
||||
["/explicit-defaults"
|
||||
{:muuntaja with-defaults
|
||||
:get identity}]
|
||||
["/no-edn-decode"
|
||||
{:muuntaja no-edn-decode
|
||||
:get identity}]
|
||||
["/just-edn"
|
||||
{:muuntaja just-edn
|
||||
:get identity}]
|
||||
["/form-params"
|
||||
{:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]
|
||||
{:data {:muuntaja m/instance
|
||||
:interceptors [(muuntaja/format-interceptor)]}})
|
||||
{:executor sieppari/executor})
|
||||
spec (fn [method path]
|
||||
(let [path (keyword path)]
|
||||
(-> {:request-method :get :uri "/swagger.json"}
|
||||
|
|
@ -99,42 +99,42 @@
|
|||
|
||||
(deftest muuntaja-swagger-parts-test
|
||||
(let [app (http/ring-handler
|
||||
(http/router
|
||||
[["/request"
|
||||
{:interceptors [(muuntaja/format-negotiate-interceptor)
|
||||
(muuntaja/format-request-interceptor)]
|
||||
:get identity}]
|
||||
["/response"
|
||||
{:interceptors [(muuntaja/format-negotiate-interceptor)
|
||||
(muuntaja/format-response-interceptor)]
|
||||
:get identity}]
|
||||
["/both"
|
||||
{:interceptors [(muuntaja/format-negotiate-interceptor)
|
||||
(muuntaja/format-response-interceptor)
|
||||
(muuntaja/format-request-interceptor)]
|
||||
:get identity}]
|
||||
["/form-request"
|
||||
{:interceptors [(muuntaja/format-negotiate-interceptor)
|
||||
(http/router
|
||||
[["/request"
|
||||
{:interceptors [(muuntaja/format-negotiate-interceptor)
|
||||
(muuntaja/format-request-interceptor)]
|
||||
:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
["/form-response"
|
||||
{:interceptors [(muuntaja/format-negotiate-interceptor)
|
||||
:get identity}]
|
||||
["/response"
|
||||
{:interceptors [(muuntaja/format-negotiate-interceptor)
|
||||
(muuntaja/format-response-interceptor)]
|
||||
:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
["/form-with-both"
|
||||
{:interceptors [(muuntaja/format-negotiate-interceptor)
|
||||
:get identity}]
|
||||
["/both"
|
||||
{:interceptors [(muuntaja/format-negotiate-interceptor)
|
||||
(muuntaja/format-response-interceptor)
|
||||
(muuntaja/format-request-interceptor)]
|
||||
:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
:get identity}]
|
||||
["/form-request"
|
||||
{:interceptors [(muuntaja/format-negotiate-interceptor)
|
||||
(muuntaja/format-request-interceptor)]
|
||||
:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
["/form-response"
|
||||
{:interceptors [(muuntaja/format-negotiate-interceptor)
|
||||
(muuntaja/format-response-interceptor)]
|
||||
:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
["/form-with-both"
|
||||
{:interceptors [(muuntaja/format-negotiate-interceptor)
|
||||
(muuntaja/format-response-interceptor)
|
||||
(muuntaja/format-request-interceptor)]
|
||||
:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]
|
||||
{:data {:muuntaja m/instance}})
|
||||
{:executor sieppari/executor})
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]
|
||||
{:data {:muuntaja m/instance}})
|
||||
{:executor sieppari/executor})
|
||||
spec (fn [method path]
|
||||
(-> {:request-method :get :uri "/swagger.json"}
|
||||
(app) :body :paths (get path) method))
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
|
||||
(deftest parameters-test
|
||||
(let [app (http/ring-handler
|
||||
(http/router
|
||||
["/ping" {:get #(select-keys % [:params :query-params])}]
|
||||
{:data {:interceptors [(parameters/parameters-interceptor)]}})
|
||||
{:executor sieppari/executor})]
|
||||
(http/router
|
||||
["/ping" {:get #(select-keys % [:params :query-params])}]
|
||||
{:data {:interceptors [(parameters/parameters-interceptor)]}})
|
||||
{:executor sieppari/executor})]
|
||||
(is (= {:query-params {"kikka" "kukka"}
|
||||
:params {"kikka" "kukka"}}
|
||||
(app {:request-method :get
|
||||
|
|
@ -19,15 +19,15 @@
|
|||
|
||||
(deftest parameters-swagger-test
|
||||
(let [app (http/ring-handler
|
||||
(http/router
|
||||
[["/form-params" {:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
["/body-params" {:post {:parameters {:body {:x string?}}
|
||||
:handler identity}}]
|
||||
["/swagger.json" {:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]
|
||||
{:data {:interceptors [(parameters/parameters-interceptor)]}})
|
||||
{:executor sieppari/executor})
|
||||
(http/router
|
||||
[["/form-params" {:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
["/body-params" {:post {:parameters {:body {:x string?}}
|
||||
:handler identity}}]
|
||||
["/swagger.json" {:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]
|
||||
{:data {:interceptors [(parameters/parameters-interceptor)]}})
|
||||
{:executor sieppari/executor})
|
||||
spec (fn [path]
|
||||
(-> {:request-method :get :uri "/swagger.json"}
|
||||
app
|
||||
|
|
|
|||
|
|
@ -74,20 +74,20 @@
|
|||
(deftest spec-coercion-test
|
||||
(let [create (fn [interceptors]
|
||||
(http/ring-handler
|
||||
(http/router
|
||||
["/api"
|
||||
["/plus/:e"
|
||||
{:get {:parameters {:query {:a int?}
|
||||
:body {:b int?}
|
||||
:form {:c int?}
|
||||
:header {:d int?}
|
||||
:path {:e int?}}
|
||||
:responses {200 {:body {:total pos-int?}}
|
||||
500 {:description "fail"}}
|
||||
:handler handler}}]]
|
||||
{:data {:interceptors interceptors
|
||||
:coercion spec/coercion}})
|
||||
{:executor sieppari/executor}))]
|
||||
(http/router
|
||||
["/api"
|
||||
["/plus/:e"
|
||||
{:get {:parameters {:query {:a int?}
|
||||
:body {:b int?}
|
||||
:form {:c int?}
|
||||
:header {:d int?}
|
||||
:path {:e int?}}
|
||||
:responses {200 {:body {:total pos-int?}}
|
||||
500 {:description "fail"}}
|
||||
:handler handler}}]]
|
||||
{:data {:interceptors interceptors
|
||||
:coercion spec/coercion}})
|
||||
{:executor sieppari/executor}))]
|
||||
|
||||
(testing "without exception handling"
|
||||
(let [app (create [(rrc/coerce-request-interceptor)
|
||||
|
|
@ -103,15 +103,15 @@
|
|||
|
||||
(testing "invalid request"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Request coercion failed"
|
||||
(app invalid-request1))))
|
||||
ExceptionInfo
|
||||
#"Request coercion failed"
|
||||
(app invalid-request1))))
|
||||
|
||||
(testing "invalid response"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Response coercion failed"
|
||||
(app invalid-request2))))))
|
||||
ExceptionInfo
|
||||
#"Response coercion failed"
|
||||
(app invalid-request2))))))
|
||||
|
||||
(testing "with exception handling"
|
||||
(let [app (create [(rrc/coerce-exceptions-interceptor)
|
||||
|
|
@ -134,20 +134,20 @@
|
|||
(deftest schema-coercion-test
|
||||
(let [create (fn [middleware]
|
||||
(http/ring-handler
|
||||
(http/router
|
||||
["/api"
|
||||
["/plus/:e"
|
||||
{:get {:parameters {:query {:a s/Int}
|
||||
:body {:b s/Int}
|
||||
:form {:c s/Int}
|
||||
:header {:d s/Int}
|
||||
:path {:e s/Int}}
|
||||
:responses {200 {:body {:total (s/constrained s/Int pos? 'positive)}}
|
||||
500 {:description "fail"}}
|
||||
:handler handler}}]]
|
||||
{:data {:interceptors middleware
|
||||
:coercion schema/coercion}})
|
||||
{:executor sieppari/executor}))]
|
||||
(http/router
|
||||
["/api"
|
||||
["/plus/:e"
|
||||
{:get {:parameters {:query {:a s/Int}
|
||||
:body {:b s/Int}
|
||||
:form {:c s/Int}
|
||||
:header {:d s/Int}
|
||||
:path {:e s/Int}}
|
||||
:responses {200 {:body {:total (s/constrained s/Int pos? 'positive)}}
|
||||
500 {:description "fail"}}
|
||||
:handler handler}}]]
|
||||
{:data {:interceptors middleware
|
||||
:coercion schema/coercion}})
|
||||
{:executor sieppari/executor}))]
|
||||
|
||||
(testing "without exception handling"
|
||||
(let [app (create [(rrc/coerce-request-interceptor)
|
||||
|
|
@ -163,15 +163,15 @@
|
|||
|
||||
(testing "invalid request"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Request coercion failed"
|
||||
(app invalid-request1))))
|
||||
ExceptionInfo
|
||||
#"Request coercion failed"
|
||||
(app invalid-request1))))
|
||||
|
||||
(testing "invalid response"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Response coercion failed"
|
||||
(app invalid-request2))))
|
||||
ExceptionInfo
|
||||
#"Response coercion failed"
|
||||
(app invalid-request2))))
|
||||
|
||||
(testing "with exception handling"
|
||||
(let [app (create [(rrc/coerce-exceptions-interceptor)
|
||||
|
|
@ -194,51 +194,51 @@
|
|||
(deftest malli-coercion-test
|
||||
(let [create (fn [interceptors]
|
||||
(http/ring-handler
|
||||
(http/router
|
||||
["/api"
|
||||
(http/router
|
||||
["/api"
|
||||
|
||||
["/validate" {:summary "just validation"
|
||||
:coercion (reitit.coercion.malli/create {:transformers {}})
|
||||
:post {:parameters {:body [:map [:x int?]]}
|
||||
:responses {200 {:body [:map [:x int?]]}}
|
||||
:handler (fn [req]
|
||||
{:status 200
|
||||
:body (-> req :parameters :body)})}}]
|
||||
["/validate" {:summary "just validation"
|
||||
:coercion (reitit.coercion.malli/create {:transformers {}})
|
||||
:post {:parameters {:body [:map [:x int?]]}
|
||||
:responses {200 {:body [:map [:x int?]]}}
|
||||
:handler (fn [req]
|
||||
{:status 200
|
||||
:body (-> req :parameters :body)})}}]
|
||||
|
||||
["/no-op" {:summary "no-operation"
|
||||
:coercion (reitit.coercion.malli/create {:transformers {}, :validate false})
|
||||
:post {:parameters {:body [:map [:x int?]]}
|
||||
:responses {200 {:body [:map [:x int?]]}}
|
||||
:handler (fn [req]
|
||||
{:status 200
|
||||
:body (-> req :parameters :body)})}}]
|
||||
["/no-op" {:summary "no-operation"
|
||||
:coercion (reitit.coercion.malli/create {:transformers {}, :validate false})
|
||||
:post {:parameters {:body [:map [:x int?]]}
|
||||
:responses {200 {:body [:map [:x int?]]}}
|
||||
:handler (fn [req]
|
||||
{:status 200
|
||||
:body (-> req :parameters :body)})}}]
|
||||
|
||||
["/skip" {:summary "skip"
|
||||
:coercion (reitit.coercion.malli/create {:enabled false})
|
||||
:post {:parameters {:body [:map [:x int?]]}
|
||||
:responses {200 {:body [:map [:x int?]]}}
|
||||
:handler (fn [req]
|
||||
{:status 200
|
||||
:body (-> req :parameters :body)})}}]
|
||||
|
||||
["/or" {:post {:summary "accepts either of two map schemas"
|
||||
:parameters {:body [:or [:map [:x int?]] [:map [:y int?]]]}
|
||||
:responses {200 {:body [:map [:msg string?]]}}
|
||||
:handler (fn [{{{:keys [x]} :body} :parameters}]
|
||||
["/skip" {:summary "skip"
|
||||
:coercion (reitit.coercion.malli/create {:enabled false})
|
||||
:post {:parameters {:body [:map [:x int?]]}
|
||||
:responses {200 {:body [:map [:x int?]]}}
|
||||
:handler (fn [req]
|
||||
{:status 200
|
||||
:body {:msg (if x "you sent x" "you sent y")}})}}]
|
||||
:body (-> req :parameters :body)})}}]
|
||||
|
||||
["/plus/:e" {:get {:parameters {:query [:map [:a {:optional true} int?]]
|
||||
:body [:map [:b int?]]
|
||||
:form [:map [:c [int? {:default 3}]]]
|
||||
:header [:map [:d int?]]
|
||||
:path [:map [:e int?]]}
|
||||
:responses {200 {:body [:map [:total pos-int?]]}
|
||||
500 {:description "fail"}}
|
||||
:handler handler}}]]
|
||||
{:data {:interceptors interceptors
|
||||
:coercion malli/coercion}})
|
||||
{:executor sieppari/executor}))]
|
||||
["/or" {:post {:summary "accepts either of two map schemas"
|
||||
:parameters {:body [:or [:map [:x int?]] [:map [:y int?]]]}
|
||||
:responses {200 {:body [:map [:msg string?]]}}
|
||||
:handler (fn [{{{:keys [x]} :body} :parameters}]
|
||||
{:status 200
|
||||
:body {:msg (if x "you sent x" "you sent y")}})}}]
|
||||
|
||||
["/plus/:e" {:get {:parameters {:query [:map [:a {:optional true} int?]]
|
||||
:body [:map [:b int?]]
|
||||
:form [:map [:c [int? {:default 3}]]]
|
||||
:header [:map [:d int?]]
|
||||
:path [:map [:e int?]]}
|
||||
:responses {200 {:body [:map [:total pos-int?]]}
|
||||
500 {:description "fail"}}
|
||||
:handler handler}}]]
|
||||
{:data {:interceptors interceptors
|
||||
:coercion malli/coercion}})
|
||||
{:executor sieppari/executor}))]
|
||||
|
||||
(testing "withut exception handling"
|
||||
(let [app (create [(rrc/coerce-request-interceptor)
|
||||
|
|
@ -249,8 +249,8 @@
|
|||
:body {:total 15}}
|
||||
(app valid-request1)))
|
||||
#_(is (= {:status 200
|
||||
:body {:total 115}}
|
||||
(app valid-request2)))
|
||||
:body {:total 115}}
|
||||
(app valid-request2)))
|
||||
(is (= {:status 200
|
||||
:body {:total 15}}
|
||||
(app valid-request3)))
|
||||
|
|
@ -264,15 +264,15 @@
|
|||
|
||||
(testing "invalid request"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Request coercion failed"
|
||||
(app invalid-request1))))
|
||||
ExceptionInfo
|
||||
#"Request coercion failed"
|
||||
(app invalid-request1))))
|
||||
|
||||
(testing "invalid response"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Response coercion failed"
|
||||
(app invalid-request2))))))
|
||||
ExceptionInfo
|
||||
#"Response coercion failed"
|
||||
(app invalid-request2))))))
|
||||
|
||||
(testing "with exception handling"
|
||||
(let [app (create [(rrc/coerce-exceptions-interceptor)
|
||||
|
|
@ -339,16 +339,16 @@
|
|||
{:status 200, :body (assoc body :response true)})}})
|
||||
->app (fn [options]
|
||||
(http/ring-handler
|
||||
(http/router
|
||||
["/api"
|
||||
["/default" (endpoint [:map [:x int?]])]
|
||||
["/closed" (endpoint [:map {:closed true} [:x int?]])]
|
||||
["/open" (endpoint [:map {:closed false} [:x int?]])]]
|
||||
{:data {:interceptors [(rrc/coerce-exceptions-interceptor)
|
||||
(rrc/coerce-request-interceptor)
|
||||
(rrc/coerce-response-interceptor)]
|
||||
:coercion (malli/create options)}})
|
||||
{:executor sieppari/executor}))
|
||||
(http/router
|
||||
["/api"
|
||||
["/default" (endpoint [:map [:x int?]])]
|
||||
["/closed" (endpoint [:map {:closed true} [:x int?]])]
|
||||
["/open" (endpoint [:map {:closed false} [:x int?]])]]
|
||||
{:data {:interceptors [(rrc/coerce-exceptions-interceptor)
|
||||
(rrc/coerce-request-interceptor)
|
||||
(rrc/coerce-response-interceptor)]
|
||||
:coercion (malli/create options)}})
|
||||
{:executor sieppari/executor}))
|
||||
->request (fn [uri] {:uri (str "/api/" uri)
|
||||
:request-method :get
|
||||
:muuntaja/request {:format "application/json"}
|
||||
|
|
@ -399,23 +399,23 @@
|
|||
|
||||
(testing "sequence schemas"
|
||||
(let [app (http/ring-handler
|
||||
(http/router
|
||||
["/ping" {:get {:parameters {:body [:vector [:map [:message string?]]]}
|
||||
:responses {200 {:body [:vector [:map [:pong string?]]]}
|
||||
501 {:body [:vector [:map [:error string?]]]}}
|
||||
:handler (fn [{{[{:keys [message]}] :body} :parameters :as req}]
|
||||
(condp = message
|
||||
"ping" {:status 200
|
||||
:body [{:pong message}]}
|
||||
"fail" {:status 501
|
||||
:body [{:error "fail"}]}
|
||||
{:status 200
|
||||
:body {:invalid "response"}}))}}]
|
||||
{:data {:interceptors [(rrc/coerce-exceptions-interceptor)
|
||||
(rrc/coerce-request-interceptor)
|
||||
(rrc/coerce-response-interceptor)]
|
||||
:coercion malli/coercion}})
|
||||
{:executor sieppari/executor})
|
||||
(http/router
|
||||
["/ping" {:get {:parameters {:body [:vector [:map [:message string?]]]}
|
||||
:responses {200 {:body [:vector [:map [:pong string?]]]}
|
||||
501 {:body [:vector [:map [:error string?]]]}}
|
||||
:handler (fn [{{[{:keys [message]}] :body} :parameters :as req}]
|
||||
(condp = message
|
||||
"ping" {:status 200
|
||||
:body [{:pong message}]}
|
||||
"fail" {:status 501
|
||||
:body [{:error "fail"}]}
|
||||
{:status 200
|
||||
:body {:invalid "response"}}))}}]
|
||||
{:data {:interceptors [(rrc/coerce-exceptions-interceptor)
|
||||
(rrc/coerce-request-interceptor)
|
||||
(rrc/coerce-response-interceptor)]
|
||||
:coercion malli/coercion}})
|
||||
{:executor sieppari/executor})
|
||||
->request (fn [body]
|
||||
{:uri "/ping"
|
||||
:request-method :get
|
||||
|
|
@ -439,19 +439,19 @@
|
|||
|
||||
(deftest muuntaja-test
|
||||
(let [app (http/ring-handler
|
||||
(http/router
|
||||
["/api"
|
||||
["/plus"
|
||||
{:post {:parameters {:body {:int int?, :keyword keyword?}}
|
||||
:responses {200 {:body {:int int?, :keyword keyword?}}}
|
||||
:handler (fn [{{:keys [body]} :parameters}]
|
||||
{:status 200
|
||||
:body body})}}]]
|
||||
{:data {:interceptors [(muuntaja.interceptor/format-interceptor)
|
||||
(rrc/coerce-response-interceptor)
|
||||
(rrc/coerce-request-interceptor)]
|
||||
:coercion spec/coercion}})
|
||||
{:executor sieppari/executor})
|
||||
(http/router
|
||||
["/api"
|
||||
["/plus"
|
||||
{:post {:parameters {:body {:int int?, :keyword keyword?}}
|
||||
:responses {200 {:body {:int int?, :keyword keyword?}}}
|
||||
:handler (fn [{{:keys [body]} :parameters}]
|
||||
{:status 200
|
||||
:body body})}}]]
|
||||
{:data {:interceptors [(muuntaja.interceptor/format-interceptor)
|
||||
(rrc/coerce-response-interceptor)
|
||||
(rrc/coerce-request-interceptor)]
|
||||
:coercion spec/coercion}})
|
||||
{:executor sieppari/executor})
|
||||
request (fn [content-type body]
|
||||
(-> {:request-method :post
|
||||
:headers {"content-type" content-type, "accept" content-type}
|
||||
|
|
|
|||
|
|
@ -21,14 +21,14 @@
|
|||
(testing "http-handler"
|
||||
(let [api-interceptor (interceptor :api)
|
||||
router (http/router
|
||||
["/api" {:interceptors [api-interceptor]}
|
||||
["/all" handler]
|
||||
["/get" {:get handler}]
|
||||
["/users" {:interceptors [[interceptor :users]]
|
||||
:get handler
|
||||
:post {:handler handler
|
||||
:interceptors [[interceptor :post]]}
|
||||
:handler handler}]])
|
||||
["/api" {:interceptors [api-interceptor]}
|
||||
["/all" handler]
|
||||
["/get" {:get handler}]
|
||||
["/users" {:interceptors [[interceptor :users]]
|
||||
:get handler
|
||||
:post {:handler handler
|
||||
:interceptors [[interceptor :post]]}
|
||||
:handler handler}]])
|
||||
app (http/ring-handler router nil {:executor sieppari/executor})]
|
||||
|
||||
(testing "router can be extracted"
|
||||
|
|
@ -68,14 +68,14 @@
|
|||
|
||||
(testing "named routes"
|
||||
(let [router (http/router
|
||||
[["/api"
|
||||
["/all" {:handler handler :name ::all}]
|
||||
["/get" {:get {:handler handler :name ::HIDDEN}
|
||||
:name ::get}]
|
||||
["/users" {:get handler
|
||||
:post handler
|
||||
:handler handler
|
||||
:name ::users}]]])
|
||||
[["/api"
|
||||
["/all" {:handler handler :name ::all}]
|
||||
["/get" {:get {:handler handler :name ::HIDDEN}
|
||||
:name ::get}]
|
||||
["/users" {:get handler
|
||||
:post handler
|
||||
:handler handler
|
||||
:name ::users}]]])
|
||||
app (http/ring-handler router nil {:executor sieppari/executor})]
|
||||
|
||||
(testing "router can be extracted"
|
||||
|
|
@ -102,13 +102,13 @@
|
|||
(deftest enforcing-data-rules-at-runtime-test
|
||||
(let [handler (constantly {:status 200, :body "ok"})
|
||||
app (http/ring-handler
|
||||
(http/router
|
||||
[["/api"
|
||||
["/ping" handler]
|
||||
["/admin" {::roles #{:admin}}
|
||||
["/ping" handler]]]]
|
||||
{:data {:interceptors [enforce-roles-interceptor]}})
|
||||
nil {:executor sieppari/executor})]
|
||||
(http/router
|
||||
[["/api"
|
||||
["/ping" handler]
|
||||
["/admin" {::roles #{:admin}}
|
||||
["/ping" handler]]]]
|
||||
{:data {:interceptors [enforce-roles-interceptor]}})
|
||||
nil {:executor sieppari/executor})]
|
||||
|
||||
(testing "public handler"
|
||||
(is (= {:status 200, :body "ok"}
|
||||
|
|
@ -128,8 +128,8 @@
|
|||
(deftest default-handler-test
|
||||
(let [response {:status 200, :body "ok"}
|
||||
router (http/router
|
||||
[["/ping" {:get (constantly response)}]
|
||||
["/pong" (constantly nil)]])
|
||||
[["/ping" {:get (constantly response)}]
|
||||
["/pong" (constantly nil)]])
|
||||
app (http/ring-handler router nil {:executor sieppari/executor})]
|
||||
|
||||
(testing "match"
|
||||
|
|
@ -146,9 +146,9 @@
|
|||
|
||||
(testing "with default http responses"
|
||||
(let [app (http/ring-handler
|
||||
router
|
||||
(ring/create-default-handler)
|
||||
{:executor sieppari/executor})]
|
||||
router
|
||||
(ring/create-default-handler)
|
||||
{:executor sieppari/executor})]
|
||||
(testing "route doesn't match yields 404"
|
||||
(is (= 404 (:status (app {:request-method :get, :uri "/"})))))
|
||||
(testing "method doesn't match yields 405"
|
||||
|
|
@ -158,12 +158,12 @@
|
|||
|
||||
(testing "with custom http responses"
|
||||
(let [app (http/ring-handler
|
||||
router
|
||||
(ring/create-default-handler
|
||||
{:not-found (constantly {:status -404})
|
||||
:method-not-allowed (constantly {:status -405})
|
||||
:not-acceptable (constantly {:status -406})})
|
||||
{:executor sieppari/executor})]
|
||||
router
|
||||
(ring/create-default-handler
|
||||
{:not-found (constantly {:status -404})
|
||||
:method-not-allowed (constantly {:status -405})
|
||||
:not-acceptable (constantly {:status -406})})
|
||||
{:executor sieppari/executor})]
|
||||
(testing "route doesn't match"
|
||||
(is (= -404 (:status (app {:request-method :get, :uri "/"})))))
|
||||
(testing "method doesn't match"
|
||||
|
|
@ -180,12 +180,12 @@
|
|||
|
||||
(testing "with defaults"
|
||||
(let [app (http/ring-handler
|
||||
(http/router
|
||||
[["/get" {:get (constantly response)
|
||||
:post (constantly response)}]
|
||||
["/options" {:options (constantly response)}]
|
||||
["/any" (constantly response)]])
|
||||
{:executor sieppari/executor})]
|
||||
(http/router
|
||||
[["/get" {:get (constantly response)
|
||||
:post (constantly response)}]
|
||||
["/options" {:options (constantly response)}]
|
||||
["/any" (constantly response)]])
|
||||
{:executor sieppari/executor})]
|
||||
|
||||
(testing "endpoint with a non-options handler"
|
||||
(is (= response (app {:request-method :get, :uri "/get"})))
|
||||
|
|
@ -201,12 +201,12 @@
|
|||
|
||||
(testing "disabled via options"
|
||||
(let [app (http/ring-handler
|
||||
(http/router
|
||||
[["/get" {:get (constantly response)}]
|
||||
["/options" {:options (constantly response)}]
|
||||
["/any" (constantly response)]]
|
||||
{::http/default-options-endpoint nil})
|
||||
{:executor sieppari/executor})]
|
||||
(http/router
|
||||
[["/get" {:get (constantly response)}]
|
||||
["/options" {:options (constantly response)}]
|
||||
["/any" (constantly response)]]
|
||||
{::http/default-options-endpoint nil})
|
||||
{:executor sieppari/executor})]
|
||||
|
||||
(testing "endpoint with a non-options handler"
|
||||
(is (= response (app {:request-method :get, :uri "/get"})))
|
||||
|
|
@ -227,8 +227,8 @@
|
|||
(reset! value x))))
|
||||
response {:status 200, :body "ok"}
|
||||
router (http/router
|
||||
[["/ping" {:get (fn [_] response)}]
|
||||
["/pong" (fn [_] nil)]])
|
||||
[["/ping" {:get (fn [_] response)}]
|
||||
["/pong" (fn [_] nil)]])
|
||||
app (http/ring-handler router nil {:executor sieppari/executor})]
|
||||
|
||||
(testing "match"
|
||||
|
|
@ -287,11 +287,11 @@
|
|||
(require '[sieppari.async.core-async])
|
||||
(let [response {:status 200, :body "ok"}
|
||||
app (http/ring-handler
|
||||
(http/router
|
||||
["/ping" {:get {:interceptors [{:enter #(a/go %)}]
|
||||
:handler (fn [_] (a/go response))}}])
|
||||
(ring/create-default-handler)
|
||||
{:executor sieppari/executor})]
|
||||
(http/router
|
||||
["/ping" {:get {:interceptors [{:enter #(a/go %)}]
|
||||
:handler (fn [_] (a/go response))}}])
|
||||
(ring/create-default-handler)
|
||||
{:executor sieppari/executor})]
|
||||
(let [respond (promise)]
|
||||
(app {:request-method :get, :uri "/ping"} respond ::irrelevant)
|
||||
(is (= response (deref respond 100 ::timeout)))))))
|
||||
|
|
@ -302,11 +302,11 @@
|
|||
(testing "works if registered"
|
||||
(let [response {:status 200, :body "ok"}
|
||||
app (http/ring-handler
|
||||
(http/router
|
||||
["/ping" {:get {:interceptors [{:enter map->MyAsyncContext}]
|
||||
:handler (fn [_] response)}}])
|
||||
(ring/create-default-handler)
|
||||
{:executor sieppari/executor})
|
||||
(http/router
|
||||
["/ping" {:get {:interceptors [{:enter map->MyAsyncContext}]
|
||||
:handler (fn [_] response)}}])
|
||||
(ring/create-default-handler)
|
||||
{:executor sieppari/executor})
|
||||
respond (promise)
|
||||
raise (promise)]
|
||||
(app {:request-method :get, :uri "/ping"} respond raise)
|
||||
|
|
@ -321,14 +321,14 @@
|
|||
request {:uri "/api/avaruus" :request-method :get}
|
||||
create (fn [options]
|
||||
(http/ring-handler
|
||||
(http/router
|
||||
["/api" {:interceptors [(interceptor :olipa)]}
|
||||
["/avaruus" {:interceptors [(interceptor :kerran)]
|
||||
:get {:handler handler
|
||||
:interceptors [(interceptor :avaruus)]}}]]
|
||||
options)
|
||||
nil
|
||||
{:executor sieppari/executor}))]
|
||||
(http/router
|
||||
["/api" {:interceptors [(interceptor :olipa)]}
|
||||
["/avaruus" {:interceptors [(interceptor :kerran)]
|
||||
:get {:handler handler
|
||||
:interceptors [(interceptor :avaruus)]}}]]
|
||||
options)
|
||||
nil
|
||||
{:executor sieppari/executor}))]
|
||||
|
||||
(testing "by default, all middleware are applied in order"
|
||||
(let [app (create nil)]
|
||||
|
|
@ -352,10 +352,10 @@
|
|||
|
||||
(testing "from root"
|
||||
(let [app (http/ring-handler
|
||||
(http/router
|
||||
["/*" (ring/create-resource-handler)])
|
||||
(ring/create-default-handler)
|
||||
{:executor sieppari/executor})]
|
||||
(http/router
|
||||
["/*" (ring/create-resource-handler)])
|
||||
(ring/create-default-handler)
|
||||
{:executor sieppari/executor})]
|
||||
(testing test
|
||||
(testing "different file-types"
|
||||
(let [response (app (request "/hello.json"))]
|
||||
|
|
@ -388,10 +388,10 @@
|
|||
|
||||
(testing "from path"
|
||||
(let [app (http/ring-handler
|
||||
(http/router
|
||||
["/files/*" (ring/create-resource-handler)])
|
||||
(ring/create-default-handler)
|
||||
{:executor sieppari/executor})
|
||||
(http/router
|
||||
["/files/*" (ring/create-resource-handler)])
|
||||
(ring/create-default-handler)
|
||||
{:executor sieppari/executor})
|
||||
request #(request (str "/files" %))
|
||||
redirect #(redirect (str "/files" %))]
|
||||
(testing test
|
||||
|
|
@ -428,11 +428,11 @@
|
|||
|
||||
(testing "from root"
|
||||
(let [app (http/ring-handler
|
||||
(http/router [])
|
||||
(ring/routes
|
||||
(ring/create-resource-handler {:path "/"})
|
||||
(ring/create-default-handler))
|
||||
{:executor sieppari/executor})]
|
||||
(http/router [])
|
||||
(ring/routes
|
||||
(ring/create-resource-handler {:path "/"})
|
||||
(ring/create-default-handler))
|
||||
{:executor sieppari/executor})]
|
||||
(testing test
|
||||
(testing "different file-types"
|
||||
(let [response (app (request "/hello.json"))]
|
||||
|
|
@ -465,11 +465,11 @@
|
|||
|
||||
(testing "from path"
|
||||
(let [app (http/ring-handler
|
||||
(http/router [])
|
||||
(ring/routes
|
||||
(ring/create-resource-handler {:path "/files"})
|
||||
(ring/create-default-handler))
|
||||
{:executor sieppari/executor})
|
||||
(http/router [])
|
||||
(ring/routes
|
||||
(ring/create-resource-handler {:path "/files"})
|
||||
(ring/create-default-handler))
|
||||
{:executor sieppari/executor})
|
||||
request #(request (str "/files" %))
|
||||
redirect #(redirect (str "/files" %))]
|
||||
(testing test
|
||||
|
|
@ -510,18 +510,18 @@
|
|||
interceptor (fn [x] {:enter (fn [ctx] (swap! times update-in [:enter x] (fnil inc 0)) ctx)
|
||||
:leave (fn [ctx] (swap! times update-in [:leave x] (fnil inc 0)) ctx)})
|
||||
app (http/ring-handler
|
||||
(http/router
|
||||
["/api"
|
||||
{:interceptors [(interceptor :api)]}
|
||||
["/ping"
|
||||
{:interceptors [(interceptor :ping)]
|
||||
:get {:interceptors [(interceptor :get)]
|
||||
:handler (fn [_] response)}}]])
|
||||
(ring/routes
|
||||
(ring/create-default-handler)
|
||||
{:data {:interceptors [(interceptor :router)]}})
|
||||
{:executor sieppari/executor
|
||||
:interceptors [(interceptor :top)]})]
|
||||
(http/router
|
||||
["/api"
|
||||
{:interceptors [(interceptor :api)]}
|
||||
["/ping"
|
||||
{:interceptors [(interceptor :ping)]
|
||||
:get {:interceptors [(interceptor :get)]
|
||||
:handler (fn [_] response)}}]])
|
||||
(ring/routes
|
||||
(ring/create-default-handler)
|
||||
{:data {:interceptors [(interceptor :router)]}})
|
||||
{:executor sieppari/executor
|
||||
:interceptors [(interceptor :top)]})]
|
||||
(is (= response (app {:request-method :get, :uri "/api/ping"})))
|
||||
(is (= {:enter {:top 1, :api 1, :ping 1, :get 1}
|
||||
:leave {:get 1, :ping 1, :api 1, :top 1}}
|
||||
|
|
@ -530,15 +530,15 @@
|
|||
(deftest router-available-in-default-branch
|
||||
(testing "1-arity"
|
||||
((http/ring-handler
|
||||
(http/router [])
|
||||
(fn [{::r/keys [router]}]
|
||||
(is router))
|
||||
{:executor sieppari/executor})
|
||||
(http/router [])
|
||||
(fn [{::r/keys [router]}]
|
||||
(is router))
|
||||
{:executor sieppari/executor})
|
||||
{}))
|
||||
(testing "3-arity"
|
||||
((http/ring-handler
|
||||
(http/router [])
|
||||
(fn [{::r/keys [router]}]
|
||||
(is router))
|
||||
{:executor sieppari/executor})
|
||||
(http/router [])
|
||||
(fn [{::r/keys [router]}]
|
||||
(is router))
|
||||
{:executor sieppari/executor})
|
||||
{} ::respond ::raise)))
|
||||
|
|
|
|||
|
|
@ -28,11 +28,11 @@
|
|||
|
||||
(deftest pedestal-e2e-test
|
||||
(let [router (pedestal/routing-interceptor
|
||||
(http/router
|
||||
[""
|
||||
{:interceptors [{:name :nop} (exception/exception-interceptor)]}
|
||||
["/ok" (fn [_] {:status 200, :body "ok"})]
|
||||
["/fail" (fn [_] (throw (ex-info "kosh" {})))]]))
|
||||
(http/router
|
||||
[""
|
||||
{:interceptors [{:name :nop} (exception/exception-interceptor)]}
|
||||
["/ok" (fn [_] {:status 200, :body "ok"})]
|
||||
["/fail" (fn [_] (throw (ex-info "kosh" {})))]]))
|
||||
service (-> {:io.pedestal.http/request-logger nil
|
||||
:io.pedestal.http/routes []}
|
||||
(io.pedestal.http/default-interceptors)
|
||||
|
|
|
|||
|
|
@ -18,25 +18,25 @@
|
|||
(create f nil))
|
||||
([f wrap]
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
[["/defaults"
|
||||
{:handler f}]
|
||||
["/http-response"
|
||||
{:handler (fn [req]
|
||||
(http-response/unauthorized! "Unauthorized"))}]
|
||||
["/coercion"
|
||||
{:middleware [reitit.ring.coercion/coerce-request-middleware
|
||||
reitit.ring.coercion/coerce-response-middleware]
|
||||
:coercion reitit.coercion.spec/coercion
|
||||
:parameters {:query {:x int?, :y int?}}
|
||||
:responses {200 {:body {:total pos-int?}}}
|
||||
:handler f}]]
|
||||
{:data {:middleware [(exception/create-exception-middleware
|
||||
(merge
|
||||
exception/default-handlers
|
||||
{::kikka (constantly {:status 400, :body "kikka"})
|
||||
SQLException (constantly {:status 400, :body "sql"})
|
||||
::exception/wrap wrap}))]}}))))]
|
||||
(ring/router
|
||||
[["/defaults"
|
||||
{:handler f}]
|
||||
["/http-response"
|
||||
{:handler (fn [req]
|
||||
(http-response/unauthorized! "Unauthorized"))}]
|
||||
["/coercion"
|
||||
{:middleware [reitit.ring.coercion/coerce-request-middleware
|
||||
reitit.ring.coercion/coerce-response-middleware]
|
||||
:coercion reitit.coercion.spec/coercion
|
||||
:parameters {:query {:x int?, :y int?}}
|
||||
:responses {200 {:body {:total pos-int?}}}
|
||||
:handler f}]]
|
||||
{:data {:middleware [(exception/create-exception-middleware
|
||||
(merge
|
||||
exception/default-handlers
|
||||
{::kikka (constantly {:status 400, :body "kikka"})
|
||||
SQLException (constantly {:status 400, :body "sql"})
|
||||
::exception/wrap wrap}))]}}))))]
|
||||
|
||||
(testing "normal calls work ok"
|
||||
(let [response {:status 200, :body "ok"}
|
||||
|
|
@ -66,7 +66,6 @@
|
|||
:response response}))))]
|
||||
(is (= response (app {:request-method :post, :uri "/http-response"})))))
|
||||
|
||||
|
||||
(testing ":muuntaja/decode"
|
||||
(let [app (create (fn [_] (m/decode m/instance "application/json" "{:so \"invalid\"}")))]
|
||||
(is (= {:body "Malformed \"application/json\" request."
|
||||
|
|
@ -130,21 +129,21 @@
|
|||
|
||||
(deftest spec-coercion-exception-test
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
["/plus"
|
||||
{:get
|
||||
{:parameters {:query {:x int?, :y int?}}
|
||||
:responses {200 {:body {:total pos-int?}}}
|
||||
:handler (fn [{{{:keys [x y]} :query} :parameters}]
|
||||
{:status 200, :body {:total (+ x y)}})}}]
|
||||
{:data {:coercion reitit.coercion.spec/coercion
|
||||
:middleware [(exception/create-exception-middleware
|
||||
(merge
|
||||
exception/default-handlers
|
||||
{::coercion/request-coercion (fn [e _] {:status 400, :body (ex-data e)})
|
||||
::coercion/response-coercion (fn [e _] {:status 500, :body (ex-data e)})}))
|
||||
reitit.ring.coercion/coerce-request-middleware
|
||||
reitit.ring.coercion/coerce-response-middleware]}}))]
|
||||
(ring/router
|
||||
["/plus"
|
||||
{:get
|
||||
{:parameters {:query {:x int?, :y int?}}
|
||||
:responses {200 {:body {:total pos-int?}}}
|
||||
:handler (fn [{{{:keys [x y]} :query} :parameters}]
|
||||
{:status 200, :body {:total (+ x y)}})}}]
|
||||
{:data {:coercion reitit.coercion.spec/coercion
|
||||
:middleware [(exception/create-exception-middleware
|
||||
(merge
|
||||
exception/default-handlers
|
||||
{::coercion/request-coercion (fn [e _] {:status 400, :body (ex-data e)})
|
||||
::coercion/response-coercion (fn [e _] {:status 500, :body (ex-data e)})}))
|
||||
reitit.ring.coercion/coerce-request-middleware
|
||||
reitit.ring.coercion/coerce-response-middleware]}}))]
|
||||
(testing "success"
|
||||
(let [{:keys [status body]} (app {:uri "/plus", :request-method :get, :query-params {"x" "1", "y" "2"}})]
|
||||
(is (= 200 status))
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@
|
|||
(deftest muuntaja-test
|
||||
(let [data {:kikka "kukka"}
|
||||
app (ring/ring-handler
|
||||
(ring/router
|
||||
["/ping" {:get (constantly {:status 200, :body data})}]
|
||||
{:data {:muuntaja m/instance
|
||||
:middleware [muuntaja/format-middleware]}}))]
|
||||
(ring/router
|
||||
["/ping" {:get (constantly {:status 200, :body data})}]
|
||||
{:data {:muuntaja m/instance
|
||||
:middleware [muuntaja/format-middleware]}}))]
|
||||
(is (= data (->> {:request-method :get, :uri "/ping"}
|
||||
(app)
|
||||
:body
|
||||
|
|
@ -22,26 +22,26 @@
|
|||
no-edn-decode (m/create (-> m/default-options (update-in [:formats "application/edn"] dissoc :decoder)))
|
||||
just-edn (m/create (-> m/default-options (m/select-formats ["application/edn"])))
|
||||
app (ring/ring-handler
|
||||
(ring/router
|
||||
[["/defaults"
|
||||
{:get identity}]
|
||||
["/explicit-defaults"
|
||||
{:muuntaja with-defaults
|
||||
:get identity}]
|
||||
["/no-edn-decode"
|
||||
{:muuntaja no-edn-decode
|
||||
:get identity}]
|
||||
["/just-edn"
|
||||
{:muuntaja just-edn
|
||||
:get identity}]
|
||||
["/form-params"
|
||||
{:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]
|
||||
{:data {:muuntaja m/instance
|
||||
:middleware [muuntaja/format-middleware]}}))
|
||||
(ring/router
|
||||
[["/defaults"
|
||||
{:get identity}]
|
||||
["/explicit-defaults"
|
||||
{:muuntaja with-defaults
|
||||
:get identity}]
|
||||
["/no-edn-decode"
|
||||
{:muuntaja no-edn-decode
|
||||
:get identity}]
|
||||
["/just-edn"
|
||||
{:muuntaja just-edn
|
||||
:get identity}]
|
||||
["/form-params"
|
||||
{:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]
|
||||
{:data {:muuntaja m/instance
|
||||
:middleware [muuntaja/format-middleware]}}))
|
||||
spec (fn [method path]
|
||||
(let [path (keyword path)]
|
||||
(-> {:request-method :get :uri "/swagger.json"}
|
||||
|
|
@ -97,41 +97,41 @@
|
|||
|
||||
(deftest muuntaja-swagger-parts-test
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
[["/request"
|
||||
{:middleware [muuntaja/format-negotiate-middleware
|
||||
muuntaja/format-request-middleware]
|
||||
:get identity}]
|
||||
["/response"
|
||||
{:middleware [muuntaja/format-negotiate-middleware
|
||||
muuntaja/format-response-middleware]
|
||||
:get identity}]
|
||||
["/both"
|
||||
{:middleware [muuntaja/format-negotiate-middleware
|
||||
muuntaja/format-response-middleware
|
||||
muuntaja/format-request-middleware]
|
||||
:get identity}]
|
||||
["/form-request"
|
||||
{:middleware [muuntaja/format-negotiate-middleware
|
||||
muuntaja/format-request-middleware]
|
||||
:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
["/form-response"
|
||||
{:middleware [muuntaja/format-negotiate-middleware
|
||||
muuntaja/format-response-middleware]
|
||||
:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
["/form-with-both"
|
||||
{:middleware [muuntaja/format-negotiate-middleware
|
||||
muuntaja/format-response-middleware
|
||||
muuntaja/format-request-middleware]
|
||||
:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
(ring/router
|
||||
[["/request"
|
||||
{:middleware [muuntaja/format-negotiate-middleware
|
||||
muuntaja/format-request-middleware]
|
||||
:get identity}]
|
||||
["/response"
|
||||
{:middleware [muuntaja/format-negotiate-middleware
|
||||
muuntaja/format-response-middleware]
|
||||
:get identity}]
|
||||
["/both"
|
||||
{:middleware [muuntaja/format-negotiate-middleware
|
||||
muuntaja/format-response-middleware
|
||||
muuntaja/format-request-middleware]
|
||||
:get identity}]
|
||||
["/form-request"
|
||||
{:middleware [muuntaja/format-negotiate-middleware
|
||||
muuntaja/format-request-middleware]
|
||||
:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
["/form-response"
|
||||
{:middleware [muuntaja/format-negotiate-middleware
|
||||
muuntaja/format-response-middleware]
|
||||
:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
["/form-with-both"
|
||||
{:middleware [muuntaja/format-negotiate-middleware
|
||||
muuntaja/format-response-middleware
|
||||
muuntaja/format-request-middleware]
|
||||
:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]
|
||||
{:data {:muuntaja m/instance}}))
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]
|
||||
{:data {:muuntaja m/instance}}))
|
||||
spec (fn [method path]
|
||||
(-> {:request-method :get :uri "/swagger.json"}
|
||||
(app) :body :paths (get path) method))
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
(deftest parameters-test
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
["/ping" {:get #(select-keys % [:params :query-params])}]
|
||||
{:data {:middleware [parameters/parameters-middleware]}}))]
|
||||
(ring/router
|
||||
["/ping" {:get #(select-keys % [:params :query-params])}]
|
||||
{:data {:middleware [parameters/parameters-middleware]}}))]
|
||||
(is (= {:query-params {"kikka" "kukka"}
|
||||
:params {"kikka" "kukka"}}
|
||||
(app {:request-method :get
|
||||
|
|
@ -17,14 +17,14 @@
|
|||
|
||||
(deftest parameters-swagger-test
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
[["/form-params" {:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
["/body-params" {:post {:parameters {:body {:x string?}}
|
||||
:handler identity}}]
|
||||
["/swagger.json" {:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]
|
||||
{:data {:middleware [parameters/parameters-middleware]}}))
|
||||
(ring/router
|
||||
[["/form-params" {:post {:parameters {:form {:x string?}}
|
||||
:handler identity}}]
|
||||
["/body-params" {:post {:parameters {:body {:x string?}}
|
||||
:handler identity}}]
|
||||
["/swagger.json" {:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]
|
||||
{:data {:middleware [parameters/parameters-middleware]}}))
|
||||
spec (fn [path]
|
||||
(-> {:request-method :get :uri "/swagger.json"}
|
||||
app
|
||||
|
|
|
|||
|
|
@ -12,23 +12,23 @@
|
|||
|
||||
(deftest coercion-test
|
||||
(let [r (r/router
|
||||
[["/schema" {:coercion reitit.coercion.schema/coercion}
|
||||
["/:number/:keyword" {:parameters {:path {:number s/Int
|
||||
:keyword s/Keyword}
|
||||
:query (s/maybe {:int s/Int, :ints [s/Int], :map {s/Int s/Int}})}}]]
|
||||
["/malli" {:coercion reitit.coercion.malli/coercion}
|
||||
["/:number/:keyword" {:parameters {:path [:map [:number int?] [:keyword keyword?]]
|
||||
:query [:maybe [:map [:int int?]
|
||||
[:ints [:vector int?]]
|
||||
[:map [:map-of int? int?]]]]}}]]
|
||||
["/spec" {:coercion reitit.coercion.spec/coercion}
|
||||
["/:number/:keyword" {:parameters {:path {:number int?
|
||||
:keyword keyword?}
|
||||
:query (ds/maybe {:int int?, :ints [int?], :map {int? int?}})}}]]
|
||||
["/none"
|
||||
["/:number/:keyword" {:parameters {:path {:number int?
|
||||
:keyword keyword?}}}]]]
|
||||
{:compile coercion/compile-request-coercers})]
|
||||
[["/schema" {:coercion reitit.coercion.schema/coercion}
|
||||
["/:number/:keyword" {:parameters {:path {:number s/Int
|
||||
:keyword s/Keyword}
|
||||
:query (s/maybe {:int s/Int, :ints [s/Int], :map {s/Int s/Int}})}}]]
|
||||
["/malli" {:coercion reitit.coercion.malli/coercion}
|
||||
["/:number/:keyword" {:parameters {:path [:map [:number int?] [:keyword keyword?]]
|
||||
:query [:maybe [:map [:int int?]
|
||||
[:ints [:vector int?]]
|
||||
[:map [:map-of int? int?]]]]}}]]
|
||||
["/spec" {:coercion reitit.coercion.spec/coercion}
|
||||
["/:number/:keyword" {:parameters {:path {:number int?
|
||||
:keyword keyword?}
|
||||
:query (ds/maybe {:int int?, :ints [int?], :map {int? int?}})}}]]
|
||||
["/none"
|
||||
["/:number/:keyword" {:parameters {:path {:number int?
|
||||
:keyword keyword?}}}]]]
|
||||
{:compile coercion/compile-request-coercers})]
|
||||
|
||||
(testing "schema-coercion"
|
||||
(testing "succeeds"
|
||||
|
|
@ -80,10 +80,10 @@
|
|||
|
||||
(deftest data-spec-example-test
|
||||
(let [router (r/router
|
||||
["/:company/users/:user-id" {:name ::user-view
|
||||
:coercion reitit.coercion.spec/coercion
|
||||
:parameters {:path {:company string?
|
||||
:user-id int?}}}]
|
||||
{:compile coercion/compile-request-coercers})]
|
||||
["/:company/users/:user-id" {:name ::user-view
|
||||
:coercion reitit.coercion.spec/coercion
|
||||
:parameters {:path {:company string?
|
||||
:user-id int?}}}]
|
||||
{:compile coercion/compile-request-coercers})]
|
||||
(is (= {:path {:user-id 123, :company "metosin"}}
|
||||
(:parameters (match-by-path-and-coerce! router "/metosin/users/123"))))))
|
||||
|
|
|
|||
|
|
@ -21,38 +21,38 @@
|
|||
(is (= nil
|
||||
(r/match-by-path router "/api")))
|
||||
(is (= (r/map->Match
|
||||
{:template "/api/ipa/:size"
|
||||
:data {:name ::beer}
|
||||
:path "/api/ipa/large"
|
||||
:path-params {:size "large"}})
|
||||
{:template "/api/ipa/:size"
|
||||
:data {:name ::beer}
|
||||
:path "/api/ipa/large"
|
||||
:path-params {:size "large"}})
|
||||
(r/match-by-path router "/api/ipa/large")))
|
||||
(is (= (r/map->Match
|
||||
{:template "/api/ipa/:size"
|
||||
:data {:name ::beer}
|
||||
:path "/api/ipa/large"
|
||||
:path-params {:size "large"}})
|
||||
{:template "/api/ipa/:size"
|
||||
:data {:name ::beer}
|
||||
:path "/api/ipa/large"
|
||||
:path-params {:size "large"}})
|
||||
(r/match-by-name router ::beer {:size "large"})))
|
||||
(is (= (r/map->Match
|
||||
{:template "/api/ipa/:size"
|
||||
:data {:name ::beer}
|
||||
:path "/api/ipa/large"
|
||||
:path-params {:size "large"}})
|
||||
{:template "/api/ipa/:size"
|
||||
:data {:name ::beer}
|
||||
:path "/api/ipa/large"
|
||||
:path-params {:size "large"}})
|
||||
(r/match-by-name router ::beer {:size :large})))
|
||||
(is (= nil (r/match-by-name router "ILLEGAL")))
|
||||
(is (= [::beer] (r/route-names router)))
|
||||
|
||||
(testing "name-based routing with missing parameters"
|
||||
(is (= (r/map->PartialMatch
|
||||
{:template "/api/ipa/:size"
|
||||
:data {:name ::beer}
|
||||
:required #{:size}
|
||||
:path-params nil})
|
||||
{:template "/api/ipa/:size"
|
||||
:data {:name ::beer}
|
||||
:required #{:size}
|
||||
:path-params nil})
|
||||
(r/match-by-name router ::beer)))
|
||||
(is (r/partial-match? (r/match-by-name router ::beer)))
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"^missing path-params for route /api/ipa/:size -> \#\{:size\}$"
|
||||
(r/match-by-name! router ::beer))))))
|
||||
ExceptionInfo
|
||||
#"^missing path-params for route /api/ipa/:size -> \#\{:size\}$"
|
||||
(r/match-by-name! router ::beer))))))
|
||||
|
||||
(testing "decode %-encoded path params"
|
||||
(let [router (r/router [["/one-param-path/:param1" ::one]
|
||||
|
|
@ -71,14 +71,14 @@
|
|||
|
||||
(testing "complex"
|
||||
(let [router (r/router
|
||||
[["/:abba" ::abba]
|
||||
["/abba/1" ::abba2]
|
||||
["/:jabba/2" ::jabba2]
|
||||
["/:abba/:dabba/doo" ::doo]
|
||||
["/abba/dabba/boo/baa" ::baa]
|
||||
["/abba/:dabba/boo" ::boo]
|
||||
["/:jabba/:dabba/:doo/:daa/*foo" ::wild]]
|
||||
{:router r})
|
||||
[["/:abba" ::abba]
|
||||
["/abba/1" ::abba2]
|
||||
["/:jabba/2" ::jabba2]
|
||||
["/:abba/:dabba/doo" ::doo]
|
||||
["/abba/dabba/boo/baa" ::baa]
|
||||
["/abba/:dabba/boo" ::boo]
|
||||
["/:jabba/:dabba/:doo/:daa/*foo" ::wild]]
|
||||
{:router r})
|
||||
by-path #(-> router (r/match-by-path %) :data :name)]
|
||||
(is (= ::abba (by-path "/abba")))
|
||||
(is (= ::abba2 (by-path "/abba/1")))
|
||||
|
|
@ -93,19 +93,19 @@
|
|||
(testing "bracket-params"
|
||||
(testing "successful"
|
||||
(let [router (r/router
|
||||
[["/{abba}" ::abba]
|
||||
["/abba/1" ::abba2]
|
||||
["/{jabba}/2" ::jabba2]
|
||||
["/{abba}/{dabba}/doo" ::doo]
|
||||
["/abba/dabba/boo/baa" ::baa]
|
||||
["/abba/{dabba}/boo" ::boo]
|
||||
["/{a/jabba}/{a.b/dabba}/{a.b.c/doo}/{a.b.c.d/daa}/{*foo/bar}" ::wild]
|
||||
["/files/file-{name}.html" ::html]
|
||||
["/files/file-{name}.json" ::json]
|
||||
["/{eskon}/{saum}/pium\u2215paum" ::loru]
|
||||
["/{🌈}🤔/🎈" ::emoji]
|
||||
["/extra-end}s-are/ok" ::bracket]]
|
||||
{:router r})
|
||||
[["/{abba}" ::abba]
|
||||
["/abba/1" ::abba2]
|
||||
["/{jabba}/2" ::jabba2]
|
||||
["/{abba}/{dabba}/doo" ::doo]
|
||||
["/abba/dabba/boo/baa" ::baa]
|
||||
["/abba/{dabba}/boo" ::boo]
|
||||
["/{a/jabba}/{a.b/dabba}/{a.b.c/doo}/{a.b.c.d/daa}/{*foo/bar}" ::wild]
|
||||
["/files/file-{name}.html" ::html]
|
||||
["/files/file-{name}.json" ::json]
|
||||
["/{eskon}/{saum}/pium\u2215paum" ::loru]
|
||||
["/{🌈}🤔/🎈" ::emoji]
|
||||
["/extra-end}s-are/ok" ::bracket]]
|
||||
{:router r})
|
||||
by-path #(-> router (r/match-by-path %) ((juxt (comp :name :data) :path-params)))]
|
||||
(is (= [::abba {:abba "abba"}] (by-path "/abba")))
|
||||
(is (= [::abba2 {}] (by-path "/abba/1")))
|
||||
|
|
@ -130,22 +130,22 @@
|
|||
(testing "invalid syntax fails fast"
|
||||
(testing "unclosed brackets"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#":reitit.trie/unclosed-brackets"
|
||||
(r/router ["/kikka/{kukka"]))))
|
||||
ExceptionInfo
|
||||
#":reitit.trie/unclosed-brackets"
|
||||
(r/router ["/kikka/{kukka"]))))
|
||||
(testing "multiple terminators"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#":reitit.trie/multiple-terminators"
|
||||
(r/router [["/{kukka}.json"]
|
||||
["/{kukka}-json"]]))))))
|
||||
ExceptionInfo
|
||||
#":reitit.trie/multiple-terminators"
|
||||
(r/router [["/{kukka}.json"]
|
||||
["/{kukka}-json"]]))))))
|
||||
|
||||
(testing "empty path segments"
|
||||
(let [router (r/router
|
||||
[["/items" ::list]
|
||||
["/items/:id" ::item]
|
||||
["/items/:id/:side" ::deep]]
|
||||
{:router r})
|
||||
[["/items" ::list]
|
||||
["/items/:id" ::item]
|
||||
["/items/:id/:side" ::deep]]
|
||||
{:router r})
|
||||
matches #(-> router (r/match-by-path %) :data :name)]
|
||||
(is (= ::list (matches "/items")))
|
||||
(is (= nil (matches "/items/")))
|
||||
|
|
@ -169,28 +169,28 @@
|
|||
(is (= nil
|
||||
(r/match-by-path router "/api")))
|
||||
(is (= (r/map->Match
|
||||
{:template "/api/ipa/large"
|
||||
:data {:name ::beer}
|
||||
:path "/api/ipa/large"
|
||||
:path-params {}})
|
||||
{:template "/api/ipa/large"
|
||||
:data {:name ::beer}
|
||||
:path "/api/ipa/large"
|
||||
:path-params {}})
|
||||
(r/match-by-path router "/api/ipa/large")))
|
||||
(is (= (r/map->Match
|
||||
{:template "/api/ipa/large"
|
||||
:data {:name ::beer}
|
||||
:path "/api/ipa/large"
|
||||
:path-params {:size "large"}})
|
||||
{:template "/api/ipa/large"
|
||||
:data {:name ::beer}
|
||||
:path "/api/ipa/large"
|
||||
:path-params {:size "large"}})
|
||||
(r/match-by-name router ::beer {:size "large"})))
|
||||
(is (= nil (r/match-by-name router "ILLEGAL")))
|
||||
(is (= [::beer] (r/route-names router)))
|
||||
|
||||
(testing "can't be created with wildcard routes"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"can't create :lookup-router with wildcard routes"
|
||||
(r/lookup-router
|
||||
(impl/resolve-routes
|
||||
["/api/:version/ping"]
|
||||
(r/default-router-options)))))))
|
||||
ExceptionInfo
|
||||
#"can't create :lookup-router with wildcard routes"
|
||||
(r/lookup-router
|
||||
(impl/resolve-routes
|
||||
["/api/:version/ping"]
|
||||
(r/default-router-options)))))))
|
||||
|
||||
r/lookup-router :lookup-router
|
||||
r/single-static-path-router :single-static-path-router
|
||||
|
|
@ -216,14 +216,14 @@
|
|||
(swap! compile-times inc)
|
||||
(constantly path))
|
||||
router (r/router
|
||||
["/api" {:roles #{:admin}}
|
||||
["/ping" ::ping]
|
||||
["/pong" ::pong]
|
||||
["/hidden" {:invalid? true}
|
||||
["/utter"]
|
||||
["/crap"]]]
|
||||
{:coerce coerce
|
||||
:compile compile})]
|
||||
["/api" {:roles #{:admin}}
|
||||
["/ping" ::ping]
|
||||
["/pong" ::pong]
|
||||
["/hidden" {:invalid? true}
|
||||
["/utter"]
|
||||
["/crap"]]]
|
||||
{:coerce coerce
|
||||
:compile compile})]
|
||||
|
||||
(testing "routes are coerced"
|
||||
(is (= [["/api/ping" {:name ::ping
|
||||
|
|
@ -281,10 +281,10 @@
|
|||
router (r/router routes)]
|
||||
(is (= expected (impl/resolve-routes routes (r/default-router-options))))
|
||||
(is (= (r/map->Match
|
||||
{:template "/api/user/:id/:sub-id"
|
||||
:data {:mw [:api], :parameters {:id "String", :sub-id "String"}}
|
||||
:path "/api/user/1/2"
|
||||
:path-params {:id "1", :sub-id "2"}})
|
||||
{:template "/api/user/:id/:sub-id"
|
||||
:data {:mw [:api], :parameters {:id "String", :sub-id "String"}}
|
||||
:path "/api/user/1/2"
|
||||
:path-params {:id "1", :sub-id "2"}})
|
||||
(r/match-by-path router "/api/user/1/2"))))))
|
||||
|
||||
(deftest conflicting-routes-test
|
||||
|
|
@ -334,10 +334,10 @@
|
|||
(testing "router with conflicting routes"
|
||||
(testing "throws by default"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Router contains conflicting route paths"
|
||||
(r/router
|
||||
[["/a"] ["/a"]]))))
|
||||
ExceptionInfo
|
||||
#"Router contains conflicting route paths"
|
||||
(r/router
|
||||
[["/a"] ["/a"]]))))
|
||||
(testing "can be configured to ignore with route data"
|
||||
(are [paths expected]
|
||||
(let [router (r/router paths)]
|
||||
|
|
@ -364,9 +364,9 @@
|
|||
(testing "unmarked path conflicts throw"
|
||||
(are [paths]
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Router contains conflicting route paths"
|
||||
(r/router paths)))
|
||||
ExceptionInfo
|
||||
#"Router contains conflicting route paths"
|
||||
(r/router paths)))
|
||||
[["/a"] ["/a" {:conflicting true}]]
|
||||
[["/a" {:conflicting true}] ["/a"]])))
|
||||
(testing "can be configured to ignore with router option"
|
||||
|
|
@ -375,10 +375,10 @@
|
|||
(testing "name conflicts"
|
||||
(testing "router with conflicting routes always throws"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Router contains conflicting route names"
|
||||
(r/router
|
||||
[["/1" ::1] ["/2" ::1]]))))))
|
||||
ExceptionInfo
|
||||
#"Router contains conflicting route names"
|
||||
(r/router
|
||||
[["/1" ::1] ["/2" ::1]]))))))
|
||||
|
||||
(deftest match->path-test
|
||||
(let [router (r/router ["/:a/:b" ::route])]
|
||||
|
|
@ -406,10 +406,10 @@
|
|||
(r/routes)))))
|
||||
(testing "sequential route definition fails"
|
||||
(is (thrown?
|
||||
#?(:clj Exception, :cljs js/Error)
|
||||
(-> ["/api"
|
||||
(list "/ipa")]
|
||||
(r/router))))))
|
||||
#?(:clj Exception, :cljs js/Error)
|
||||
(-> ["/api"
|
||||
(list "/ipa")]
|
||||
(r/router))))))
|
||||
|
||||
(defrecord Named [n]
|
||||
r/Expand
|
||||
|
|
@ -422,12 +422,12 @@
|
|||
|
||||
(deftest routing-order-test-229
|
||||
(let [router (r/router
|
||||
[["/" :root]
|
||||
["/" {:name :create :method :post}]]
|
||||
{:conflicts nil})
|
||||
[["/" :root]
|
||||
["/" {:name :create :method :post}]]
|
||||
{:conflicts nil})
|
||||
router2 (r/router
|
||||
[["/*a" :root]
|
||||
["/:a/b/c/d" {:name :create :method :post}]]
|
||||
{:conflicts nil})]
|
||||
[["/*a" :root]
|
||||
["/:a/b/c/d" {:name :create :method :post}]]
|
||||
{:conflicts nil})]
|
||||
(is (= :root (-> (r/match-by-path router "/") :data :name)))
|
||||
(is (= :root (-> (r/match-by-path router2 "/") :data :name)))))
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@
|
|||
(are [exception]
|
||||
(are [error routes]
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
error
|
||||
(r/router
|
||||
routes
|
||||
{:validate rs/validate
|
||||
:exception exception})))
|
||||
ExceptionInfo
|
||||
error
|
||||
(r/router
|
||||
routes
|
||||
{:validate rs/validate
|
||||
:exception exception})))
|
||||
|
||||
#"Router contains conflicting route paths"
|
||||
[["/:a/1"]
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@
|
|||
|
||||
(defn execute [interceptors ctx]
|
||||
(as-> ctx $
|
||||
(reduce #(%2 %1) $ (keep :enter interceptors))
|
||||
(reduce #(%2 %1) $ (reverse (keep :leave interceptors)))
|
||||
(:response $)))
|
||||
(reduce #(%2 %1) $ (keep :enter interceptors))
|
||||
(reduce #(%2 %1) $ (reverse (keep :leave interceptors)))
|
||||
(:response $)))
|
||||
|
||||
(defn f [value ctx]
|
||||
(update ctx :request conj value))
|
||||
|
|
@ -36,8 +36,8 @@
|
|||
(create interceptors nil))
|
||||
([interceptors opts]
|
||||
(let [chain (interceptor/chain
|
||||
(conj interceptors handler)
|
||||
:data opts)]
|
||||
(conj interceptors handler)
|
||||
:data opts)]
|
||||
(partial execute chain))))
|
||||
|
||||
(deftest expand-interceptor-test
|
||||
|
|
@ -74,9 +74,9 @@
|
|||
|
||||
(testing "missing keyword"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Interceptor :enter not found in registry"
|
||||
(create [:enter]))))
|
||||
ExceptionInfo
|
||||
#"Interceptor :enter not found in registry"
|
||||
(create [:enter]))))
|
||||
|
||||
(testing "existing keyword, compiling to nil"
|
||||
(let [app (create [:enter] {::interceptor/registry {:enter {:compile (constantly nil)}}})]
|
||||
|
|
@ -134,9 +134,9 @@
|
|||
(testing "too deeply compiled interceptor fails"
|
||||
(binding [interceptor/*max-compile-depth* 2]
|
||||
(is (thrown?
|
||||
ExceptionInfo
|
||||
#"Too deep Interceptor compilation"
|
||||
(create [[i3 :value]])))))
|
||||
ExceptionInfo
|
||||
#"Too deep Interceptor compilation"
|
||||
(create [[i3 :value]])))))
|
||||
|
||||
(testing "nil unmounts the interceptor"
|
||||
(let [app (create [{:compile (constantly nil)}
|
||||
|
|
@ -155,11 +155,11 @@
|
|||
(testing "interceptor-handler"
|
||||
(let [api-interceptor (interceptor :api)
|
||||
router (interceptor/router
|
||||
[["/ping" handler]
|
||||
["/api" {:interceptors [api-interceptor]}
|
||||
["/ping" handler]
|
||||
["/admin" {:interceptors [[interceptor :admin]]}
|
||||
["/ping" handler]]]])
|
||||
[["/ping" handler]
|
||||
["/api" {:interceptors [api-interceptor]}
|
||||
["/ping" handler]
|
||||
["/admin" {:interceptors [[interceptor :admin]]}
|
||||
["/ping" handler]]]])
|
||||
app (create-app router)]
|
||||
|
||||
(testing "not found"
|
||||
|
|
@ -179,8 +179,8 @@
|
|||
i2 {:name ::i2, :compile (constantly nil)}
|
||||
i3 (interceptor ::i3)
|
||||
router (interceptor/router
|
||||
["/api" {:interceptors [i1 i2 i3 i2]
|
||||
:handler handler}])
|
||||
["/api" {:interceptors [i1 i2 i3 i2]
|
||||
:handler handler}])
|
||||
app (create-app router)]
|
||||
|
||||
(is (= [::enter_i1 ::enter_i3 :ok ::leave_i3 ::leave_i1] (app "/api")))
|
||||
|
|
@ -221,12 +221,12 @@
|
|||
(let [debug-i (enter ::debug)
|
||||
create (fn [options]
|
||||
(create-app
|
||||
(interceptor/router
|
||||
["/ping" {:interceptors [(enter ::olipa)
|
||||
(enter ::kerran)
|
||||
(enter ::avaruus)]
|
||||
:handler handler}]
|
||||
options)))
|
||||
(interceptor/router
|
||||
["/ping" {:interceptors [(enter ::olipa)
|
||||
(enter ::kerran)
|
||||
(enter ::avaruus)]
|
||||
:handler handler}]
|
||||
options)))
|
||||
inject-debug (interceptor/transform-butlast #(interleave % (repeat debug-i)))
|
||||
sort-interceptors (interceptor/transform-butlast (partial sort-by :name))]
|
||||
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@
|
|||
(create middleware nil))
|
||||
([middleware opts]
|
||||
(middleware/chain
|
||||
middleware
|
||||
handler
|
||||
:data
|
||||
opts)))
|
||||
middleware
|
||||
handler
|
||||
:data
|
||||
opts)))
|
||||
|
||||
(deftest expand-middleware-test
|
||||
|
||||
|
|
@ -61,9 +61,9 @@
|
|||
|
||||
(testing "missing keyword"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Middleware :wrap not found in registry"
|
||||
(create [:wrap]))))
|
||||
ExceptionInfo
|
||||
#"Middleware :wrap not found in registry"
|
||||
(create [:wrap]))))
|
||||
|
||||
(testing "existing keyword, compiling to nil"
|
||||
(let [app (create [:wrap] {::middleware/registry {:wrap {:compile (constantly nil)}}})]
|
||||
|
|
@ -142,9 +142,9 @@
|
|||
(testing "too deeply compiled Middleware fails"
|
||||
(binding [middleware/*max-compile-depth* 2]
|
||||
(is (thrown?
|
||||
ExceptionInfo
|
||||
#"Too deep Middleware compilation"
|
||||
(create [[(middleware/map->Middleware mw3) :value]])))))
|
||||
ExceptionInfo
|
||||
#"Too deep Middleware compilation"
|
||||
(create [[(middleware/map->Middleware mw3) :value]])))))
|
||||
|
||||
(testing "nil unmounts the middleware"
|
||||
(let [app (create [{:compile (constantly nil)}
|
||||
|
|
@ -162,9 +162,9 @@
|
|||
|
||||
(testing "all paths should have a handler"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"path \"/ping\" doesn't have a :handler defined"
|
||||
(middleware/router ["/ping"]))))
|
||||
ExceptionInfo
|
||||
#"path \"/ping\" doesn't have a :handler defined"
|
||||
(middleware/router ["/ping"]))))
|
||||
|
||||
(testing "middleware-handler"
|
||||
(let [mw (fn [handler value]
|
||||
|
|
@ -173,11 +173,11 @@
|
|||
api-mw #(mw % :api)
|
||||
handler #(conj % :ok)
|
||||
router (middleware/router
|
||||
[["/ping" handler]
|
||||
["/api" {:middleware [api-mw]}
|
||||
["/ping" handler]
|
||||
["/admin" {:middleware [[mw :admin]]}
|
||||
["/ping" handler]]]])
|
||||
[["/ping" handler]
|
||||
["/api" {:middleware [api-mw]}
|
||||
["/ping" handler]
|
||||
["/admin" {:middleware [[mw :admin]]}
|
||||
["/ping" handler]]]])
|
||||
app (create-app router)]
|
||||
|
||||
(testing "not found"
|
||||
|
|
@ -197,9 +197,9 @@
|
|||
mw2 {:name ::mw2, :compile (constantly nil)}
|
||||
mw3 {:name ::mw3, :wrap #(mw % ::mw3)}
|
||||
router (middleware/router
|
||||
["/api" {:name ::api
|
||||
:middleware [mw1 mw2 mw3 mw2]
|
||||
:handler handler}])
|
||||
["/api" {:name ::api
|
||||
:middleware [mw1 mw2 mw3 mw2]
|
||||
:handler handler}])
|
||||
app (create-app router)]
|
||||
|
||||
(is (= [::mw1 ::mw3 :ok ::mw3 ::mw1] (app "/api")))
|
||||
|
|
@ -241,12 +241,12 @@
|
|||
debug-mw {:name ::debug, :wrap #(wrap % ::debug)}
|
||||
create (fn [options]
|
||||
(create-app
|
||||
(middleware/router
|
||||
["/ping" {:middleware [{:name ::olipa, :wrap #(wrap % ::olipa)}
|
||||
{:name ::kerran, :wrap #(wrap % ::kerran)}
|
||||
{:name ::avaruus, :wrap #(wrap % ::avaruus)}]
|
||||
:handler #(conj % :ok)}]
|
||||
options)))]
|
||||
(middleware/router
|
||||
["/ping" {:middleware [{:name ::olipa, :wrap #(wrap % ::olipa)}
|
||||
{:name ::kerran, :wrap #(wrap % ::kerran)}
|
||||
{:name ::avaruus, :wrap #(wrap % ::avaruus)}]
|
||||
:handler #(conj % :ok)}]
|
||||
options)))]
|
||||
|
||||
(testing "by default, all middleware are applied in order"
|
||||
(let [app (create nil)]
|
||||
|
|
|
|||
|
|
@ -77,19 +77,19 @@
|
|||
(deftest spec-coercion-test
|
||||
(let [create (fn [middleware]
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api"
|
||||
["/plus/:e"
|
||||
{:get {:parameters {:query {(ds/opt :a) int?}
|
||||
:body {:b int?}
|
||||
:form {:c int?}
|
||||
:header {:d int?}
|
||||
:path {:e int?}}
|
||||
:responses {200 {:body {:total pos-int?}}
|
||||
500 {:description "fail"}}
|
||||
:handler handler}}]]
|
||||
{:data {:middleware middleware
|
||||
:coercion spec/coercion}})))]
|
||||
(ring/router
|
||||
["/api"
|
||||
["/plus/:e"
|
||||
{:get {:parameters {:query {(ds/opt :a) int?}
|
||||
:body {:b int?}
|
||||
:form {:c int?}
|
||||
:header {:d int?}
|
||||
:path {:e int?}}
|
||||
:responses {200 {:body {:total pos-int?}}
|
||||
500 {:description "fail"}}
|
||||
:handler handler}}]]
|
||||
{:data {:middleware middleware
|
||||
:coercion spec/coercion}})))]
|
||||
|
||||
(testing "without exception handling"
|
||||
(let [app (create [rrc/coerce-request-middleware
|
||||
|
|
@ -111,15 +111,15 @@
|
|||
|
||||
(testing "invalid request"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Request coercion failed"
|
||||
(app invalid-request1))))
|
||||
ExceptionInfo
|
||||
#"Request coercion failed"
|
||||
(app invalid-request1))))
|
||||
|
||||
(testing "invalid response"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Response coercion failed"
|
||||
(app invalid-request2))))))
|
||||
ExceptionInfo
|
||||
#"Response coercion failed"
|
||||
(app invalid-request2))))))
|
||||
|
||||
(testing "with exception handling"
|
||||
(let [app (create [rrc/coerce-exceptions-middleware
|
||||
|
|
@ -144,19 +144,19 @@
|
|||
(deftest schema-coercion-test
|
||||
(let [create (fn [middleware]
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api"
|
||||
["/plus/:e"
|
||||
{:get {:parameters {:query {(s/optional-key :a) s/Int}
|
||||
:body {:b s/Int}
|
||||
:form {:c s/Int}
|
||||
:header {:d s/Int}
|
||||
:path {:e s/Int}}
|
||||
:responses {200 {:body {:total (s/constrained s/Int pos? 'positive)}}
|
||||
500 {:description "fail"}}
|
||||
:handler handler}}]]
|
||||
{:data {:middleware middleware
|
||||
:coercion schema/coercion}})))]
|
||||
(ring/router
|
||||
["/api"
|
||||
["/plus/:e"
|
||||
{:get {:parameters {:query {(s/optional-key :a) s/Int}
|
||||
:body {:b s/Int}
|
||||
:form {:c s/Int}
|
||||
:header {:d s/Int}
|
||||
:path {:e s/Int}}
|
||||
:responses {200 {:body {:total (s/constrained s/Int pos? 'positive)}}
|
||||
500 {:description "fail"}}
|
||||
:handler handler}}]]
|
||||
{:data {:middleware middleware
|
||||
:coercion schema/coercion}})))]
|
||||
|
||||
(testing "withut exception handling"
|
||||
(let [app (create [rrc/coerce-request-middleware
|
||||
|
|
@ -175,19 +175,19 @@
|
|||
|
||||
(testing "invalid request"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Request coercion failed"
|
||||
(app invalid-request1)))
|
||||
ExceptionInfo
|
||||
#"Request coercion failed"
|
||||
(app invalid-request1)))
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Request coercion failed"
|
||||
(app valid-request3))))
|
||||
ExceptionInfo
|
||||
#"Request coercion failed"
|
||||
(app valid-request3))))
|
||||
|
||||
(testing "invalid response"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Response coercion failed"
|
||||
(app invalid-request2))))))
|
||||
ExceptionInfo
|
||||
#"Response coercion failed"
|
||||
(app invalid-request2))))))
|
||||
|
||||
(testing "with exception handling"
|
||||
(let [app (create [rrc/coerce-exceptions-middleware
|
||||
|
|
@ -210,50 +210,50 @@
|
|||
(deftest malli-coercion-test
|
||||
(let [create (fn [middleware]
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api"
|
||||
(ring/router
|
||||
["/api"
|
||||
|
||||
["/validate" {:summary "just validation"
|
||||
:coercion (reitit.coercion.malli/create {:transformers {}})
|
||||
:post {:parameters {:body [:map [:x int?]]}
|
||||
:responses {200 {:body [:map [:x int?]]}}
|
||||
:handler (fn [req]
|
||||
{:status 200
|
||||
:body (-> req :parameters :body)})}}]
|
||||
["/validate" {:summary "just validation"
|
||||
:coercion (reitit.coercion.malli/create {:transformers {}})
|
||||
:post {:parameters {:body [:map [:x int?]]}
|
||||
:responses {200 {:body [:map [:x int?]]}}
|
||||
:handler (fn [req]
|
||||
{:status 200
|
||||
:body (-> req :parameters :body)})}}]
|
||||
|
||||
["/no-op" {:summary "no-operation"
|
||||
:coercion (reitit.coercion.malli/create {:transformers {}, :validate false})
|
||||
:post {:parameters {:body [:map [:x int?]]}
|
||||
:responses {200 {:body [:map [:x int?]]}}
|
||||
:handler (fn [req]
|
||||
{:status 200
|
||||
:body (-> req :parameters :body)})}}]
|
||||
["/no-op" {:summary "no-operation"
|
||||
:coercion (reitit.coercion.malli/create {:transformers {}, :validate false})
|
||||
:post {:parameters {:body [:map [:x int?]]}
|
||||
:responses {200 {:body [:map [:x int?]]}}
|
||||
:handler (fn [req]
|
||||
{:status 200
|
||||
:body (-> req :parameters :body)})}}]
|
||||
|
||||
["/skip" {:summary "skip"
|
||||
:coercion (reitit.coercion.malli/create {:enabled false})
|
||||
:post {:parameters {:body [:map [:x int?]]}
|
||||
:responses {200 {:body [:map [:x int?]]}}
|
||||
:handler (fn [req]
|
||||
{:status 200
|
||||
:body (-> req :parameters :body)})}}]
|
||||
|
||||
["/or" {:post {:summary "accepts either of two map schemas"
|
||||
:parameters {:body [:or [:map [:x int?]] [:map [:y int?]]]}
|
||||
:responses {200 {:body [:map [:msg string?]]}}
|
||||
:handler (fn [{{{:keys [x]} :body} :parameters}]
|
||||
["/skip" {:summary "skip"
|
||||
:coercion (reitit.coercion.malli/create {:enabled false})
|
||||
:post {:parameters {:body [:map [:x int?]]}
|
||||
:responses {200 {:body [:map [:x int?]]}}
|
||||
:handler (fn [req]
|
||||
{:status 200
|
||||
:body {:msg (if x "you sent x" "you sent y")}})}}]
|
||||
:body (-> req :parameters :body)})}}]
|
||||
|
||||
["/plus/:e" {:get {:parameters {:query [:map [:a {:optional true} int?]]
|
||||
:body [:map [:b int?]]
|
||||
:form [:map [:c [int? {:default 3}]]]
|
||||
:header [:map [:d int?]]
|
||||
:path [:map [:e int?]]}
|
||||
:responses {200 {:body [:map [:total pos-int?]]}
|
||||
500 {:description "fail"}}
|
||||
:handler handler}}]]
|
||||
{:data {:middleware middleware
|
||||
:coercion malli/coercion}})))]
|
||||
["/or" {:post {:summary "accepts either of two map schemas"
|
||||
:parameters {:body [:or [:map [:x int?]] [:map [:y int?]]]}
|
||||
:responses {200 {:body [:map [:msg string?]]}}
|
||||
:handler (fn [{{{:keys [x]} :body} :parameters}]
|
||||
{:status 200
|
||||
:body {:msg (if x "you sent x" "you sent y")}})}}]
|
||||
|
||||
["/plus/:e" {:get {:parameters {:query [:map [:a {:optional true} int?]]
|
||||
:body [:map [:b int?]]
|
||||
:form [:map [:c [int? {:default 3}]]]
|
||||
:header [:map [:d int?]]
|
||||
:path [:map [:e int?]]}
|
||||
:responses {200 {:body [:map [:total pos-int?]]}
|
||||
500 {:description "fail"}}
|
||||
:handler handler}}]]
|
||||
{:data {:middleware middleware
|
||||
:coercion malli/coercion}})))]
|
||||
|
||||
(testing "without exception handling"
|
||||
(let [app (create [rrc/coerce-request-middleware
|
||||
|
|
@ -279,15 +279,15 @@
|
|||
|
||||
(testing "invalid request"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Request coercion failed"
|
||||
(app invalid-request1))))
|
||||
ExceptionInfo
|
||||
#"Request coercion failed"
|
||||
(app invalid-request1))))
|
||||
|
||||
(testing "invalid response"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Response coercion failed"
|
||||
(app invalid-request2))))))
|
||||
ExceptionInfo
|
||||
#"Response coercion failed"
|
||||
(app invalid-request2))))))
|
||||
|
||||
(testing "with exception handling"
|
||||
(let [app (create [rrc/coerce-exceptions-middleware
|
||||
|
|
@ -350,15 +350,15 @@
|
|||
{:status 200, :body (assoc body :response true)})}})
|
||||
->app (fn [options]
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api"
|
||||
["/default" (endpoint [:map [:x int?]])]
|
||||
["/closed" (endpoint [:map {:closed true} [:x int?]])]
|
||||
["/open" (endpoint [:map {:closed false} [:x int?]])]]
|
||||
{:data {:middleware [rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion (malli/create options)}})))
|
||||
(ring/router
|
||||
["/api"
|
||||
["/default" (endpoint [:map [:x int?]])]
|
||||
["/closed" (endpoint [:map {:closed true} [:x int?]])]
|
||||
["/open" (endpoint [:map {:closed false} [:x int?]])]]
|
||||
{:data {:middleware [rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion (malli/create options)}})))
|
||||
->request (fn [uri] {:uri (str "/api/" uri)
|
||||
:request-method :get
|
||||
:muuntaja/request {:format "application/json"}
|
||||
|
|
@ -414,22 +414,22 @@
|
|||
|
||||
(testing "sequence schemas"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
["/ping" {:get {:parameters {:body [:vector [:map [:message string?]]]}
|
||||
:responses {200 {:body [:vector [:map [:pong string?]]]}
|
||||
501 {:body [:vector [:map [:error string?]]]}}
|
||||
:handler (fn [{{[{:keys [message]}] :body} :parameters :as req}]
|
||||
(condp = message
|
||||
"ping" {:status 200
|
||||
:body [{:pong message}]}
|
||||
"fail" {:status 501
|
||||
:body [{:error "fail"}]}
|
||||
{:status 200
|
||||
:body {:invalid "response"}}))}}]
|
||||
{:data {:middleware [rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion malli/coercion}}))
|
||||
(ring/router
|
||||
["/ping" {:get {:parameters {:body [:vector [:map [:message string?]]]}
|
||||
:responses {200 {:body [:vector [:map [:pong string?]]]}
|
||||
501 {:body [:vector [:map [:error string?]]]}}
|
||||
:handler (fn [{{[{:keys [message]}] :body} :parameters :as req}]
|
||||
(condp = message
|
||||
"ping" {:status 200
|
||||
:body [{:pong message}]}
|
||||
"fail" {:status 501
|
||||
:body [{:error "fail"}]}
|
||||
{:status 200
|
||||
:body {:invalid "response"}}))}}]
|
||||
{:data {:middleware [rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion malli/coercion}}))
|
||||
->request (fn [body]
|
||||
{:uri "/ping"
|
||||
:request-method :get
|
||||
|
|
@ -454,15 +454,15 @@
|
|||
(testing "encoding responses"
|
||||
(let [->app (fn [total-schema]
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/total" {:get {:parameters {:query [:map [:x :int]]}
|
||||
:responses {200 {:body [:map [:total total-schema]]}}
|
||||
:handler (fn [{{{:keys [x]} :query} :parameters}]
|
||||
{:status 200
|
||||
:body {:total (* x x)}})}}]
|
||||
{:data {:middleware [rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion malli/coercion}})))
|
||||
(ring/router
|
||||
["/total" {:get {:parameters {:query [:map [:x :int]]}
|
||||
:responses {200 {:body [:map [:total total-schema]]}}
|
||||
:handler (fn [{{{:keys [x]} :query} :parameters}]
|
||||
{:status 200
|
||||
:body {:total (* x x)}})}}]
|
||||
{:data {:middleware [rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion malli/coercion}})))
|
||||
call (fn [accept total-schema]
|
||||
((->app total-schema) {:uri "/total"
|
||||
:request-method :get
|
||||
|
|
@ -482,18 +482,18 @@
|
|||
#?(:clj
|
||||
(deftest muuntaja-test
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
["/api"
|
||||
["/plus"
|
||||
{:post {:parameters {:body {:int int?, :keyword keyword?}}
|
||||
:responses {200 {:body {:int int?, :keyword keyword?}}}
|
||||
:handler (fn [{{:keys [body]} :parameters}]
|
||||
{:status 200
|
||||
:body body})}}]]
|
||||
{:data {:middleware [muuntaja.middleware/wrap-format
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion spec/coercion}}))
|
||||
(ring/router
|
||||
["/api"
|
||||
["/plus"
|
||||
{:post {:parameters {:body {:int int?, :keyword keyword?}}
|
||||
:responses {200 {:body {:int int?, :keyword keyword?}}}
|
||||
:handler (fn [{{:keys [body]} :parameters}]
|
||||
{:status 200
|
||||
:body body})}}]]
|
||||
{:data {:middleware [muuntaja.middleware/wrap-format
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion spec/coercion}}))
|
||||
request (fn [content-type body]
|
||||
(-> {:request-method :post
|
||||
:headers {"content-type" content-type, "accept" content-type}
|
||||
|
|
|
|||
|
|
@ -15,69 +15,69 @@
|
|||
(deftest route-data-validation-test
|
||||
(testing "validation is turned off by default"
|
||||
(is (r/router?
|
||||
(r/router
|
||||
["/api" {:handler "identity"}]))))
|
||||
(r/router
|
||||
["/api" {:handler "identity"}]))))
|
||||
|
||||
(testing "with default spec validates :name, :handler and :middleware"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Invalid route data"
|
||||
(ring/router
|
||||
["/api" {:handler "identity"}]
|
||||
{:validate rrs/validate})))
|
||||
ExceptionInfo
|
||||
#"Invalid route data"
|
||||
(ring/router
|
||||
["/api" {:handler "identity"}]
|
||||
{:validate rrs/validate})))
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Invalid route data"
|
||||
(ring/router
|
||||
["/api" {:handler identity
|
||||
:name "kikka"}]
|
||||
{:validate rrs/validate}))))
|
||||
ExceptionInfo
|
||||
#"Invalid route data"
|
||||
(ring/router
|
||||
["/api" {:handler identity
|
||||
:name "kikka"}]
|
||||
{:validate rrs/validate}))))
|
||||
|
||||
(testing "all endpoints are validated"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Invalid route data"
|
||||
(ring/router
|
||||
["/api" {:patch {:handler "identity"}}]
|
||||
{:validate rrs/validate}))))
|
||||
ExceptionInfo
|
||||
#"Invalid route data"
|
||||
(ring/router
|
||||
["/api" {:patch {:handler "identity"}}]
|
||||
{:validate rrs/validate}))))
|
||||
|
||||
(testing "spec can be overridden"
|
||||
(is (r/router?
|
||||
(ring/router
|
||||
["/api" {:handler "identity"}]
|
||||
{:spec (s/spec any?)
|
||||
:validate rrs/validate})))
|
||||
(ring/router
|
||||
["/api" {:handler "identity"}]
|
||||
{:spec (s/spec any?)
|
||||
:validate rrs/validate})))
|
||||
|
||||
(testing "predicates are not allowed"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#":reitit.ring.spec/invalid-specs"
|
||||
(ring/router
|
||||
["/api" {:handler "identity"}]
|
||||
{:spec any?
|
||||
:validate rrs/validate})))))
|
||||
ExceptionInfo
|
||||
#":reitit.ring.spec/invalid-specs"
|
||||
(ring/router
|
||||
["/api" {:handler "identity"}]
|
||||
{:spec any?
|
||||
:validate rrs/validate})))))
|
||||
|
||||
(testing "middleware can contribute to specs"
|
||||
(is (r/router?
|
||||
(ring/router
|
||||
["/api" {:get {:handler identity
|
||||
:roles #{:admin}}}]
|
||||
{:validate rrs/validate
|
||||
:data {:middleware [{:spec (s/keys :opt-un [::roles])
|
||||
:wrap (fn [handler]
|
||||
(fn [request]
|
||||
(handler request)))}]}})))
|
||||
(ring/router
|
||||
["/api" {:get {:handler identity
|
||||
:roles #{:admin}}}]
|
||||
{:validate rrs/validate
|
||||
:data {:middleware [{:spec (s/keys :opt-un [::roles])
|
||||
:wrap (fn [handler]
|
||||
(fn [request]
|
||||
(handler request)))}]}})))
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Invalid route data"
|
||||
(ring/router
|
||||
["/api" {:get {:handler identity
|
||||
:roles #{:adminz}}}]
|
||||
{:validate rrs/validate
|
||||
:data {:middleware [{:spec (s/keys :opt-un [::roles])
|
||||
:wrap (fn [handler]
|
||||
(fn [request]
|
||||
(handler request)))}]}}))))
|
||||
ExceptionInfo
|
||||
#"Invalid route data"
|
||||
(ring/router
|
||||
["/api" {:get {:handler identity
|
||||
:roles #{:adminz}}}]
|
||||
{:validate rrs/validate
|
||||
:data {:middleware [{:spec (s/keys :opt-un [::roles])
|
||||
:wrap (fn [handler]
|
||||
(fn [request]
|
||||
(handler request)))}]}}))))
|
||||
(testing "middleware cannot be a list"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
|
|
@ -89,46 +89,46 @@
|
|||
|
||||
(deftest coercion-spec-test
|
||||
(is (r/router?
|
||||
(ring/router
|
||||
["/api"
|
||||
["/plus/:e"
|
||||
{:get {:parameters {:query {:a string?}
|
||||
:body {:b string?}
|
||||
:form {:c string?}
|
||||
:header {:d string?}
|
||||
:path {:e string?}}
|
||||
:responses {200 {:body {:total pos-int?}}
|
||||
400 {:description "fail"}
|
||||
500 {}}
|
||||
:handler identity}}]]
|
||||
{:data {:middleware [rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion reitit.coercion.spec/coercion}
|
||||
:validate rrs/validate})))
|
||||
(ring/router
|
||||
["/api"
|
||||
["/plus/:e"
|
||||
{:get {:parameters {:query {:a string?}
|
||||
:body {:b string?}
|
||||
:form {:c string?}
|
||||
:header {:d string?}
|
||||
:path {:e string?}}
|
||||
:responses {200 {:body {:total pos-int?}}
|
||||
400 {:description "fail"}
|
||||
500 {}}
|
||||
:handler identity}}]]
|
||||
{:data {:middleware [rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion reitit.coercion.spec/coercion}
|
||||
:validate rrs/validate})))
|
||||
|
||||
(is (r/router?
|
||||
(ring/router
|
||||
["/api"
|
||||
["/plus/:e"
|
||||
{:get {:parameters {:query (s/keys)}
|
||||
:handler identity}}]]
|
||||
{:data {:middleware [rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion reitit.coercion.spec/coercion}
|
||||
:validate rrs/validate})))
|
||||
(ring/router
|
||||
["/api"
|
||||
["/plus/:e"
|
||||
{:get {:parameters {:query (s/keys)}
|
||||
:handler identity}}]]
|
||||
{:data {:middleware [rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion reitit.coercion.spec/coercion}
|
||||
:validate rrs/validate})))
|
||||
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Invalid route data"
|
||||
(ring/router
|
||||
["/api"
|
||||
["/plus/:e"
|
||||
{:get {:responses {"200" {}}
|
||||
:handler identity}}]]
|
||||
{:data {:middleware [rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion reitit.coercion.spec/coercion}
|
||||
:validate rrs/validate}))))
|
||||
ExceptionInfo
|
||||
#"Invalid route data"
|
||||
(ring/router
|
||||
["/api"
|
||||
["/plus/:e"
|
||||
{:get {:responses {"200" {}}
|
||||
:handler identity}}]]
|
||||
{:data {:middleware [rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion reitit.coercion.spec/coercion}
|
||||
:validate rrs/validate}))))
|
||||
|
|
|
|||
|
|
@ -28,35 +28,35 @@
|
|||
(testing "nils are removed"
|
||||
(is (= 123
|
||||
((ring/routes
|
||||
(constantly nil)
|
||||
nil
|
||||
(constantly 123))
|
||||
(constantly nil)
|
||||
nil
|
||||
(constantly 123))
|
||||
::irrelevant))))
|
||||
(testing "can return nil"
|
||||
(is (= nil
|
||||
(ring/routes
|
||||
nil
|
||||
nil)))))
|
||||
nil
|
||||
nil)))))
|
||||
|
||||
(deftest ring-router-test
|
||||
|
||||
(testing "all paths should have a handler"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"path \"/ping\" doesn't have a :handler defined for :get"
|
||||
(ring/router ["/ping" {:get {}}]))))
|
||||
ExceptionInfo
|
||||
#"path \"/ping\" doesn't have a :handler defined for :get"
|
||||
(ring/router ["/ping" {:get {}}]))))
|
||||
|
||||
(testing "ring-handler"
|
||||
(let [api-mw #(mw % :api)
|
||||
router (ring/router
|
||||
["/api" {:middleware [api-mw]}
|
||||
["/all" handler]
|
||||
["/get" {:get handler}]
|
||||
["/users" {:middleware [[mw :users]]
|
||||
:get handler
|
||||
:post {:handler handler
|
||||
:middleware [[mw :post]]}
|
||||
:handler handler}]])
|
||||
["/api" {:middleware [api-mw]}
|
||||
["/all" handler]
|
||||
["/get" {:get handler}]
|
||||
["/users" {:middleware [[mw :users]]
|
||||
:get handler
|
||||
:post {:handler handler
|
||||
:middleware [[mw :post]]}
|
||||
:handler handler}]])
|
||||
app (ring/ring-handler router)]
|
||||
|
||||
(testing "router can be extracted"
|
||||
|
|
@ -95,8 +95,8 @@
|
|||
|
||||
(testing "with top-level middleware"
|
||||
(let [router (ring/router
|
||||
["/api" {:middleware [[mw :api]]}
|
||||
["/get" {:get handler}]])
|
||||
["/api" {:middleware [[mw :api]]}
|
||||
["/get" {:get handler}]])
|
||||
app (ring/ring-handler router nil {:middleware [[mw :top]]})]
|
||||
|
||||
(testing "router can be extracted"
|
||||
|
|
@ -111,14 +111,14 @@
|
|||
|
||||
(testing "named routes"
|
||||
(let [router (ring/router
|
||||
[["/api"
|
||||
["/all" {:handler handler :name ::all}]
|
||||
["/get" {:get {:handler handler :name ::HIDDEN}
|
||||
:name ::get}]
|
||||
["/users" {:get handler
|
||||
:post handler
|
||||
:handler handler
|
||||
:name ::users}]]])
|
||||
[["/api"
|
||||
["/all" {:handler handler :name ::all}]
|
||||
["/get" {:get {:handler handler :name ::HIDDEN}
|
||||
:name ::get}]
|
||||
["/users" {:get handler
|
||||
:post handler
|
||||
:handler handler
|
||||
:name ::users}]]])
|
||||
app (ring/ring-handler router)]
|
||||
|
||||
(testing "router can be extracted"
|
||||
|
|
@ -141,21 +141,21 @@
|
|||
|
||||
(deftest mw-variadic-test
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
["/" {:middleware [[mw-variadic "kikka" "kakka" "kukka"]]
|
||||
:handler handler}]))]
|
||||
(ring/router
|
||||
["/" {:middleware [[mw-variadic "kikka" "kakka" "kukka"]]
|
||||
:handler handler}]))]
|
||||
(is (= {:status 200, :body [:kikka_kakka_kukka :ok]}
|
||||
(app {:request-method :get, :uri "/"})))))
|
||||
|
||||
(deftest enforcing-data-rules-at-runtime-test
|
||||
(let [handler (constantly {:status 200, :body "ok"})
|
||||
app (ring/ring-handler
|
||||
(ring/router
|
||||
[["/api"
|
||||
["/ping" handler]
|
||||
["/admin" {::roles #{:admin}}
|
||||
["/ping" handler]]]]
|
||||
{:data {:middleware [wrap-enforce-roles]}}))]
|
||||
(ring/router
|
||||
[["/api"
|
||||
["/ping" handler]
|
||||
["/admin" {::roles #{:admin}}
|
||||
["/ping" handler]]]]
|
||||
{:data {:middleware [wrap-enforce-roles]}}))]
|
||||
|
||||
(testing "public handler"
|
||||
(is (= {:status 200, :body "ok"}
|
||||
|
|
@ -175,8 +175,8 @@
|
|||
(deftest default-handler-test
|
||||
(let [response {:status 200, :body "ok"}
|
||||
router (ring/router
|
||||
[["/ping" {:get (constantly response)}]
|
||||
["/pong" (constantly nil)]])
|
||||
[["/ping" {:get (constantly response)}]
|
||||
["/pong" (constantly nil)]])
|
||||
app (ring/ring-handler router)]
|
||||
|
||||
(testing "match"
|
||||
|
|
@ -202,9 +202,9 @@
|
|||
|
||||
(testing "with custom http responses"
|
||||
(let [app (ring/ring-handler router (ring/create-default-handler
|
||||
{:not-found (constantly {:status -404})
|
||||
:method-not-allowed (constantly {:status -405})
|
||||
:not-acceptable (constantly {:status -406})}))]
|
||||
{:not-found (constantly {:status -404})
|
||||
:method-not-allowed (constantly {:status -405})
|
||||
:not-acceptable (constantly {:status -406})}))]
|
||||
(testing "route doesn't match"
|
||||
(is (= -404 (:status (app {:request-method :get, :uri "/"})))))
|
||||
(testing "method doesn't match"
|
||||
|
|
@ -214,7 +214,7 @@
|
|||
|
||||
(testing "with some custom http responses"
|
||||
(let [app (ring/ring-handler router (ring/create-default-handler
|
||||
{:not-found (constantly {:status -404})}))]
|
||||
{:not-found (constantly {:status -404})}))]
|
||||
(testing "route doesn't match"
|
||||
(is (= 405 (:status (app {:request-method :post, :uri "/ping"}))))))))))
|
||||
|
||||
|
|
@ -227,11 +227,11 @@
|
|||
|
||||
(testing "with defaults"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
[["/get" {:get (constantly response)
|
||||
:post (constantly response)}]
|
||||
["/options" {:options (constantly response)}]
|
||||
["/any" (constantly response)]]))]
|
||||
(ring/router
|
||||
[["/get" {:get (constantly response)
|
||||
:post (constantly response)}]
|
||||
["/options" {:options (constantly response)}]
|
||||
["/any" (constantly response)]]))]
|
||||
|
||||
(testing "endpoint with a non-options handler"
|
||||
(let [request {:request-method :options, :uri "/get"}]
|
||||
|
|
@ -258,10 +258,10 @@
|
|||
(constantly {:status 200, :body "ok"})]]
|
||||
(let [response {:status 200, :body "ok"}
|
||||
app (ring/ring-handler
|
||||
(ring/router
|
||||
["/get" {:get (constantly response)
|
||||
:post (constantly response)}]
|
||||
{::ring/default-options-endpoint endpoint}))]
|
||||
(ring/router
|
||||
["/get" {:get (constantly response)
|
||||
:post (constantly response)}]
|
||||
{::ring/default-options-endpoint endpoint}))]
|
||||
|
||||
(testing "endpoint with a non-options handler"
|
||||
(let [request {:request-method :options, :uri "/get"}]
|
||||
|
|
@ -270,11 +270,11 @@
|
|||
|
||||
(testing "disabled via options"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
[["/get" {:get (constantly response)}]
|
||||
["/options" {:options (constantly response)}]
|
||||
["/any" (constantly response)]]
|
||||
{::ring/default-options-endpoint nil}))]
|
||||
(ring/router
|
||||
[["/get" {:get (constantly response)}]
|
||||
["/options" {:options (constantly response)}]
|
||||
["/any" (constantly response)]]
|
||||
{::ring/default-options-endpoint nil}))]
|
||||
|
||||
(testing "endpoint with a non-options handler"
|
||||
(is (= response (app {:request-method :get, :uri "/get"})))
|
||||
|
|
@ -297,8 +297,8 @@
|
|||
:post (constantly ok)}]]]
|
||||
(testing "using :method :add"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router routes)
|
||||
(ring/redirect-trailing-slash-handler {:method :add}))]
|
||||
(ring/router routes)
|
||||
(ring/redirect-trailing-slash-handler {:method :add}))]
|
||||
|
||||
(testing "exact matches work"
|
||||
(is (= ok (app {:request-method :get, :uri "/slash-less"})))
|
||||
|
|
@ -316,8 +316,8 @@
|
|||
|
||||
(testing "using :method :strip"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router routes)
|
||||
(ring/redirect-trailing-slash-handler {:method :strip}))]
|
||||
(ring/router routes)
|
||||
(ring/redirect-trailing-slash-handler {:method :strip}))]
|
||||
|
||||
(testing "stripping to empty string doesn't match"
|
||||
(is (= nil (:status (app {:request-method :get, :uri "/"})))))
|
||||
|
|
@ -342,8 +342,8 @@
|
|||
|
||||
(testing "without option (equivalent to using :method :both)"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router routes)
|
||||
(ring/redirect-trailing-slash-handler))]
|
||||
(ring/router routes)
|
||||
(ring/redirect-trailing-slash-handler))]
|
||||
|
||||
(testing "exact matches work"
|
||||
(is (= ok (app {:request-method :get, :uri "/slash-less"})))
|
||||
|
|
@ -370,10 +370,10 @@
|
|||
([x] (reset! value x))))
|
||||
response {:status 200, :body "ok"}
|
||||
router (ring/router
|
||||
[["/ping" {:get (fn [_ respond _]
|
||||
(respond response))}]
|
||||
["/pong" (fn [_ respond _]
|
||||
(respond nil))]])
|
||||
[["/ping" {:get (fn [_ respond _]
|
||||
(respond response))}]
|
||||
["/pong" (fn [_ respond _]
|
||||
(respond nil))]])
|
||||
app (ring/ring-handler router)]
|
||||
|
||||
(testing "match"
|
||||
|
|
@ -436,12 +436,12 @@
|
|||
request {:uri "/api/avaruus" :request-method :get}
|
||||
create (fn [options]
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api" {:middleware [(middleware :olipa)]}
|
||||
["/avaruus" {:middleware [(middleware :kerran)]
|
||||
:get {:handler handler
|
||||
:middleware [(middleware :avaruus)]}}]]
|
||||
options)))]
|
||||
(ring/router
|
||||
["/api" {:middleware [(middleware :olipa)]}
|
||||
["/avaruus" {:middleware [(middleware :kerran)]
|
||||
:get {:handler handler
|
||||
:middleware [(middleware :avaruus)]}}]]
|
||||
options)))]
|
||||
|
||||
(testing "by default, all middleware are applied in order"
|
||||
(let [app (create nil)]
|
||||
|
|
@ -510,9 +510,9 @@
|
|||
|
||||
(testing "from path"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
["/files/*" (create nil)])
|
||||
(ring/create-default-handler))
|
||||
(ring/router
|
||||
["/files/*" (create nil)])
|
||||
(ring/create-default-handler))
|
||||
request #(request (str "/files" %))
|
||||
redirect #(redirect (str "/files" %))]
|
||||
(testing "different file-types"
|
||||
|
|
@ -553,10 +553,10 @@
|
|||
|
||||
(testing "from root"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router [])
|
||||
(ring/routes
|
||||
(create {:path "/" :not-found-handler (fn [x] {:status 404 :body "resource-handler"})})
|
||||
(ring/create-default-handler)))]
|
||||
(ring/router [])
|
||||
(ring/routes
|
||||
(create {:path "/" :not-found-handler (fn [x] {:status 404 :body "resource-handler"})})
|
||||
(ring/create-default-handler)))]
|
||||
(testing "different file-types"
|
||||
(let [response (app (request "/hello.json"))]
|
||||
(is (= "application/json" (get-in response [:headers "Content-Type"])))
|
||||
|
|
@ -594,10 +594,10 @@
|
|||
|
||||
(testing "from path"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router [])
|
||||
(ring/routes
|
||||
(create {:path "/files" :not-found-handler (fn [x] {:status 404 :body "resource-handler"})})
|
||||
(ring/create-default-handler)))
|
||||
(ring/router [])
|
||||
(ring/routes
|
||||
(create {:path "/files" :not-found-handler (fn [x] {:status 404 :body "resource-handler"})})
|
||||
(ring/create-default-handler)))
|
||||
request #(request (str "/files" %))
|
||||
redirect #(redirect (str "/files" %))]
|
||||
(testing "different file-types"
|
||||
|
|
@ -638,12 +638,11 @@
|
|||
(is (get-in @result [:headers "Last-Modified"]))
|
||||
(is (= "<xml><hello>file</hello></xml>\n" (slurp (:body @result))))))))))))))
|
||||
|
||||
|
||||
#?(:clj
|
||||
(deftest file-resource-handler-not-found-test
|
||||
(let [redirect (fn [uri] {:status 302, :body "", :headers {"Location" uri}})
|
||||
request (fn [uri] {:uri uri, :request-method :get})
|
||||
not-found-handler (fn [_] {:status 404, :body "not-found-handler"})]
|
||||
(deftest file-resource-handler-not-found-test
|
||||
(let [redirect (fn [uri] {:status 302, :body "", :headers {"Location" uri}})
|
||||
request (fn [uri] {:uri uri, :request-method :get})
|
||||
not-found-handler (fn [_] {:status 404, :body "not-found-handler"})]
|
||||
|
||||
(doseq [[name create] [["resource-handler" ring/create-resource-handler]
|
||||
["file-handler" #(ring/create-file-handler (assoc % :root "dev-resources/public"))]]]
|
||||
|
|
@ -681,15 +680,15 @@
|
|||
(deftest router-available-in-default-branch
|
||||
(testing "1-arity"
|
||||
((ring/ring-handler
|
||||
(ring/router [])
|
||||
(fn [{::r/keys [router]}]
|
||||
(is router)))
|
||||
(ring/router [])
|
||||
(fn [{::r/keys [router]}]
|
||||
(is router)))
|
||||
{}))
|
||||
(testing "3-arity"
|
||||
((ring/ring-handler
|
||||
(ring/router [])
|
||||
(fn [{::r/keys [router]} _ _]
|
||||
(is router)))
|
||||
(ring/router [])
|
||||
(fn [{::r/keys [router]} _ _]
|
||||
(is router)))
|
||||
{} ::respond ::raise)))
|
||||
|
||||
#?(:clj
|
||||
|
|
@ -697,11 +696,11 @@
|
|||
(testing "in enough concurrent system, path-parameters can bleed"
|
||||
(doseq [compiler [trie/java-trie-compiler trie/clojure-trie-compiler]]
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
["/:id" (fn [request]
|
||||
{:status 200
|
||||
:body (-> request :path-params :id)})])
|
||||
{::trie/trie-compiler compiler})]
|
||||
(ring/router
|
||||
["/:id" (fn [request]
|
||||
{:status 200
|
||||
:body (-> request :path-params :id)})])
|
||||
{::trie/trie-compiler compiler})]
|
||||
(dotimes [_ 10]
|
||||
(future
|
||||
(dotimes [n 100000]
|
||||
|
|
|
|||
|
|
@ -38,10 +38,10 @@
|
|||
(testing "with invalid routes"
|
||||
(are [data]
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Call to #'reitit.core/router did not conform to spec"
|
||||
(r/router
|
||||
data)))
|
||||
ExceptionInfo
|
||||
#"Call to #'reitit.core/router did not conform to spec"
|
||||
(r/router
|
||||
data)))
|
||||
|
||||
;; path
|
||||
[:invalid {}]
|
||||
|
|
@ -68,10 +68,10 @@
|
|||
|
||||
(are [opts]
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Call to #'reitit.core/router did not conform to spec"
|
||||
(r/router
|
||||
["/api"] opts)))
|
||||
ExceptionInfo
|
||||
#"Call to #'reitit.core/router did not conform to spec"
|
||||
(r/router
|
||||
["/api"] opts)))
|
||||
|
||||
{:path :api}
|
||||
{:path nil}
|
||||
|
|
@ -85,52 +85,52 @@
|
|||
(deftest route-data-validation-test
|
||||
(testing "validation is turned off by default"
|
||||
(is (r/router? (r/router
|
||||
["/api" {:handler "identity"}]))))
|
||||
["/api" {:handler "identity"}]))))
|
||||
|
||||
(testing "with default spec validates :name and :handler"
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Invalid route data"
|
||||
(r/router
|
||||
["/api" {:handler "identity"}]
|
||||
{:validate rs/validate})))
|
||||
ExceptionInfo
|
||||
#"Invalid route data"
|
||||
(r/router
|
||||
["/api" {:handler "identity"}]
|
||||
{:validate rs/validate})))
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Invalid route data"
|
||||
(r/router
|
||||
["/api" {:name "kikka"}]
|
||||
{:validate rs/validate}))))
|
||||
ExceptionInfo
|
||||
#"Invalid route data"
|
||||
(r/router
|
||||
["/api" {:name "kikka"}]
|
||||
{:validate rs/validate}))))
|
||||
|
||||
(testing "spec can be overridden"
|
||||
(is (r/router? (r/router
|
||||
["/api" {:handler "identity"}]
|
||||
{:spec any?
|
||||
:validate rs/validate})))))
|
||||
["/api" {:handler "identity"}]
|
||||
{:spec any?
|
||||
:validate rs/validate})))))
|
||||
|
||||
(deftest parameters-test
|
||||
(is (s/valid?
|
||||
::rs/parameters
|
||||
{:parameters {:query {:a string?}
|
||||
:body {:b string?}
|
||||
:form {:c string?}
|
||||
:header {:d string?}
|
||||
:path {:e string?}}}))
|
||||
::rs/parameters
|
||||
{:parameters {:query {:a string?}
|
||||
:body {:b string?}
|
||||
:form {:c string?}
|
||||
:header {:d string?}
|
||||
:path {:e string?}}}))
|
||||
|
||||
(is (s/valid?
|
||||
::rs/parameters
|
||||
{:parameters {:header (s/keys)}}))
|
||||
::rs/parameters
|
||||
{:parameters {:header (s/keys)}}))
|
||||
|
||||
(is (s/valid?
|
||||
::rs/responses
|
||||
{:responses {200 {:description "ok", :body string?}
|
||||
400 {:description "fail"}
|
||||
500 {:body string?}
|
||||
:default {}}}))
|
||||
::rs/responses
|
||||
{:responses {200 {:description "ok", :body string?}
|
||||
400 {:description "fail"}
|
||||
500 {:body string?}
|
||||
:default {}}}))
|
||||
|
||||
(is (not (s/valid?
|
||||
::rs/responses
|
||||
{:responses {"200" {:description "ok", :body string?}}})))
|
||||
::rs/responses
|
||||
{:responses {"200" {:description "ok", :body string?}}})))
|
||||
|
||||
(is (not (s/valid?
|
||||
::rs/responses
|
||||
{:responses {200 {:description :ok, :body string?}}}))))
|
||||
::rs/responses
|
||||
{:responses {200 {:description :ok, :body string?}}}))))
|
||||
|
|
|
|||
|
|
@ -13,93 +13,93 @@
|
|||
|
||||
(def app
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api"
|
||||
{:swagger {:id ::math}}
|
||||
(ring/router
|
||||
["/api"
|
||||
{:swagger {:id ::math}}
|
||||
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:swagger {:info {:title "my-api"}}
|
||||
:handler (swagger/create-swagger-handler)}}]
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:swagger {:info {:title "my-api"}}
|
||||
:handler (swagger/create-swagger-handler)}}]
|
||||
|
||||
["/spec" {:coercion spec/coercion}
|
||||
["/plus/:z"
|
||||
{:patch {:summary "patch"
|
||||
["/spec" {:coercion spec/coercion}
|
||||
["/plus/:z"
|
||||
{:patch {:summary "patch"
|
||||
:handler (constantly {:status 200})}
|
||||
:options {:summary "options"
|
||||
:middleware [{:data {:swagger {:responses {200 {:description "200"}}}}}]
|
||||
:handler (constantly {:status 200})}
|
||||
:options {:summary "options"
|
||||
:middleware [{:data {:swagger {:responses {200 {:description "200"}}}}}]
|
||||
:handler (constantly {:status 200})}
|
||||
:get {:summary "plus"
|
||||
:parameters {:query {:x int?, :y int?}
|
||||
:path {:z int?}}
|
||||
:swagger {:responses {400 {:schema {:type "string"}
|
||||
:description "kosh"}}}
|
||||
:responses {200 {:body {:total int?}}
|
||||
500 {:description "fail"}}
|
||||
:handler (fn [{{{:keys [x y]} :query
|
||||
{:keys [z]} :path} :parameters}]
|
||||
{:status 200, :body {:total (+ x y z)}})}
|
||||
:post {:summary "plus with body"
|
||||
:parameters {:body (ds/maybe [int?])
|
||||
:path {:z int?}}
|
||||
:swagger {:responses {400 {:schema {:type "string"}
|
||||
:description "kosh"}}}
|
||||
:responses {200 {:body {:total int?}}
|
||||
500 {:description "fail"}}
|
||||
:handler (fn [{{{:keys [z]} :path
|
||||
xs :body} :parameters}]
|
||||
{:status 200, :body {:total (+ (reduce + xs) z)}})}}]]
|
||||
:get {:summary "plus"
|
||||
:parameters {:query {:x int?, :y int?}
|
||||
:path {:z int?}}
|
||||
:swagger {:responses {400 {:schema {:type "string"}
|
||||
:description "kosh"}}}
|
||||
:responses {200 {:body {:total int?}}
|
||||
500 {:description "fail"}}
|
||||
:handler (fn [{{{:keys [x y]} :query
|
||||
{:keys [z]} :path} :parameters}]
|
||||
{:status 200, :body {:total (+ x y z)}})}
|
||||
:post {:summary "plus with body"
|
||||
:parameters {:body (ds/maybe [int?])
|
||||
:path {:z int?}}
|
||||
:swagger {:responses {400 {:schema {:type "string"}
|
||||
:description "kosh"}}}
|
||||
:responses {200 {:body {:total int?}}
|
||||
500 {:description "fail"}}
|
||||
:handler (fn [{{{:keys [z]} :path
|
||||
xs :body} :parameters}]
|
||||
{:status 200, :body {:total (+ (reduce + xs) z)}})}}]]
|
||||
|
||||
["/malli" {:coercion malli/coercion}
|
||||
["/plus/*z"
|
||||
{:get {:summary "plus"
|
||||
:parameters {:query [:map [:x int?] [:y int?]]
|
||||
:path [:map [:z int?]]}
|
||||
:swagger {:responses {400 {:schema {:type "string"}
|
||||
:description "kosh"}}}
|
||||
:responses {200 {:body [:map [:total int?]]}
|
||||
500 {:description "fail"}}
|
||||
:handler (fn [{{{:keys [x y]} :query
|
||||
{:keys [z]} :path} :parameters}]
|
||||
{:status 200, :body {:total (+ x y z)}})}
|
||||
:post {:summary "plus with body"
|
||||
:parameters {:body [:maybe [:vector int?]]
|
||||
:path [:map [:z int?]]}
|
||||
:swagger {:responses {400 {:schema {:type "string"}
|
||||
:description "kosh"}}}
|
||||
:responses {200 {:body [:map [:total int?]]}
|
||||
500 {:description "fail"}}
|
||||
:handler (fn [{{{:keys [z]} :path
|
||||
xs :body} :parameters}]
|
||||
{:status 200, :body {:total (+ (reduce + xs) z)}})}}]]
|
||||
["/malli" {:coercion malli/coercion}
|
||||
["/plus/*z"
|
||||
{:get {:summary "plus"
|
||||
:parameters {:query [:map [:x int?] [:y int?]]
|
||||
:path [:map [:z int?]]}
|
||||
:swagger {:responses {400 {:schema {:type "string"}
|
||||
:description "kosh"}}}
|
||||
:responses {200 {:body [:map [:total int?]]}
|
||||
500 {:description "fail"}}
|
||||
:handler (fn [{{{:keys [x y]} :query
|
||||
{:keys [z]} :path} :parameters}]
|
||||
{:status 200, :body {:total (+ x y z)}})}
|
||||
:post {:summary "plus with body"
|
||||
:parameters {:body [:maybe [:vector int?]]
|
||||
:path [:map [:z int?]]}
|
||||
:swagger {:responses {400 {:schema {:type "string"}
|
||||
:description "kosh"}}}
|
||||
:responses {200 {:body [:map [:total int?]]}
|
||||
500 {:description "fail"}}
|
||||
:handler (fn [{{{:keys [z]} :path
|
||||
xs :body} :parameters}]
|
||||
{:status 200, :body {:total (+ (reduce + xs) z)}})}}]]
|
||||
|
||||
["/schema" {:coercion schema/coercion}
|
||||
["/plus/*z"
|
||||
{:get {:summary "plus"
|
||||
:parameters {:query {:x s/Int, :y s/Int}
|
||||
:path {:z s/Int}}
|
||||
:swagger {:responses {400 {:schema {:type "string"}
|
||||
:description "kosh"}}}
|
||||
:responses {200 {:body {:total s/Int}}
|
||||
500 {:description "fail"}}
|
||||
:handler (fn [{{{:keys [x y]} :query
|
||||
{:keys [z]} :path} :parameters}]
|
||||
{:status 200, :body {:total (+ x y z)}})}
|
||||
:post {:summary "plus with body"
|
||||
:parameters {:body (s/maybe [s/Int])
|
||||
:path {:z s/Int}}
|
||||
:swagger {:responses {400 {:schema {:type "string"}
|
||||
:description "kosh"}}}
|
||||
:responses {200 {:body {:total s/Int}}
|
||||
500 {:description "fail"}}
|
||||
:handler (fn [{{{:keys [z]} :path
|
||||
xs :body} :parameters}]
|
||||
{:status 200, :body {:total (+ (reduce + xs) z)}})}}]]]
|
||||
["/schema" {:coercion schema/coercion}
|
||||
["/plus/*z"
|
||||
{:get {:summary "plus"
|
||||
:parameters {:query {:x s/Int, :y s/Int}
|
||||
:path {:z s/Int}}
|
||||
:swagger {:responses {400 {:schema {:type "string"}
|
||||
:description "kosh"}}}
|
||||
:responses {200 {:body {:total s/Int}}
|
||||
500 {:description "fail"}}
|
||||
:handler (fn [{{{:keys [x y]} :query
|
||||
{:keys [z]} :path} :parameters}]
|
||||
{:status 200, :body {:total (+ x y z)}})}
|
||||
:post {:summary "plus with body"
|
||||
:parameters {:body (s/maybe [s/Int])
|
||||
:path {:z s/Int}}
|
||||
:swagger {:responses {400 {:schema {:type "string"}
|
||||
:description "kosh"}}}
|
||||
:responses {200 {:body {:total s/Int}}
|
||||
500 {:description "fail"}}
|
||||
:handler (fn [{{{:keys [z]} :path
|
||||
xs :body} :parameters}]
|
||||
{:status 200, :body {:total (+ (reduce + xs) z)}})}}]]]
|
||||
|
||||
{:data {:middleware [swagger/swagger-feature
|
||||
rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]}})))
|
||||
{:data {:middleware [swagger/swagger-feature
|
||||
rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]}})))
|
||||
|
||||
(require '[fipp.edn])
|
||||
(deftest swagger-test
|
||||
|
|
@ -300,21 +300,21 @@
|
|||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]
|
||||
app (ring/ring-handler
|
||||
(ring/router
|
||||
[["/common" {:swagger {:id #{::one ::two}}}
|
||||
ping-route]
|
||||
(ring/router
|
||||
[["/common" {:swagger {:id #{::one ::two}}}
|
||||
ping-route]
|
||||
|
||||
["/one" {:swagger {:id ::one}}
|
||||
ping-route
|
||||
spec-route]
|
||||
["/one" {:swagger {:id ::one}}
|
||||
ping-route
|
||||
spec-route]
|
||||
|
||||
["/two" {:swagger {:id ::two}}
|
||||
ping-route
|
||||
spec-route
|
||||
["/deep" {:swagger {:id ::one}}
|
||||
ping-route]]
|
||||
["/one-two" {:swagger {:id #{::one ::two}}}
|
||||
spec-route]]))]
|
||||
["/two" {:swagger {:id ::two}}
|
||||
ping-route
|
||||
spec-route
|
||||
["/deep" {:swagger {:id ::one}}
|
||||
ping-route]]
|
||||
["/one-two" {:swagger {:id #{::one ::two}}}
|
||||
spec-route]]))]
|
||||
(is (= ["/common/ping" "/one/ping" "/two/deep/ping"]
|
||||
(spec-paths app "/one/swagger.json")))
|
||||
(is (= ["/common/ping" "/two/ping"]
|
||||
|
|
@ -324,8 +324,8 @@
|
|||
|
||||
(deftest swagger-ui-config-test
|
||||
(let [app (swagger-ui/create-swagger-ui-handler
|
||||
{:path "/"
|
||||
:config {:jsonEditor true}})]
|
||||
{:path "/"
|
||||
:config {:jsonEditor true}})]
|
||||
(is (= 302 (:status (app {:request-method :get, :uri "/"}))))
|
||||
(is (= 200 (:status (app {:request-method :get, :uri "/index.html"}))))
|
||||
(is (= {:jsonEditor true, :url "/swagger.json"}
|
||||
|
|
@ -334,12 +334,12 @@
|
|||
|
||||
(deftest without-swagger-id-test
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
[["/ping"
|
||||
{:get (constantly "ping")}]
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]))]
|
||||
(ring/router
|
||||
[["/ping"
|
||||
{:get (constantly "ping")}]
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]))]
|
||||
(is (= ["/ping"] (spec-paths app "/swagger.json")))
|
||||
(is (= #{::swagger/default}
|
||||
(-> {:request-method :get :uri "/swagger.json"}
|
||||
|
|
@ -347,14 +347,14 @@
|
|||
|
||||
(deftest with-options-endpoint-test
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
[["/ping"
|
||||
{:options (constantly "options")}]
|
||||
["/pong"
|
||||
(constantly "options")]
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]))]
|
||||
(ring/router
|
||||
[["/ping"
|
||||
{:options (constantly "options")}]
|
||||
["/pong"
|
||||
(constantly "options")]
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]))]
|
||||
(is (= ["/ping" "/pong"] (spec-paths app "/swagger.json")))
|
||||
(is (= #{::swagger/default}
|
||||
(-> {:request-method :get :uri "/swagger.json"}
|
||||
|
|
@ -362,18 +362,18 @@
|
|||
|
||||
(deftest all-parameter-types-test
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
[["/parameters"
|
||||
{:post {:coercion spec/coercion
|
||||
:parameters {:query {:q string?}
|
||||
:body {:b string?}
|
||||
:form {:f string?}
|
||||
:header {:h string?}
|
||||
:path {:p string?}}
|
||||
:handler identity}}]
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]))
|
||||
(ring/router
|
||||
[["/parameters"
|
||||
{:post {:coercion spec/coercion
|
||||
:parameters {:query {:q string?}
|
||||
:body {:b string?}
|
||||
:form {:f string?}
|
||||
:header {:h string?}
|
||||
:path {:p string?}}
|
||||
:handler identity}}]
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]))
|
||||
spec (:body (app {:request-method :get, :uri "/swagger.json"}))]
|
||||
(is (= ["query" "body" "formData" "header" "path"]
|
||||
(map :in (get-in spec [:paths "/parameters" :post :parameters]))))))
|
||||
|
|
|
|||
Loading…
Reference in a new issue