-
Notifications
You must be signed in to change notification settings - Fork 11
/
core.clj
57 lines (52 loc) · 2.56 KB
/
core.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
(ns framework.coercion.core
"Request and response validation by given malli rules.
The rule can be defined at route definition,
the schema can be defined with registry function.
Path definition example:
[\"/api/siege-machines/{mydomain/id}\" {:hander ws/handler-fn
:action mydomain.siege-machines/get-by-id
:parameters {:path [:map [:mydomain/id int?]]}
:responses {200 {:body :mydomain/SiegeMachine}}}]
Registry example:
(registry {:mydomain/SiegeMachine [:map
[:id int?]
[:name keyword?]
[:range {:optional true} int?]
[:created {:optional true} inst?]]
:mydomain/Infantry [:map
[:id int?]
[:name keyword?]
[:attack {:optional true} int?]]})"
(:require
[malli.core :as m]
[malli.registry :as mr]
[malli.util :as mu]
[reitit.coercion :as coercion]
[xiana.core :as xiana]))
(defn registry
"Registers a given schema in malli"
[schema]
(mr/set-default-registry!
(merge
(m/default-schemas)
(mu/schemas)
schema)))
(def interceptor
"On enter: validates request parameters
On leave: validates response body
on request error: responds {:status 400, :body \"Request coercion failed\"}
on response error: responds {:status 400, :body \"Response validation failed\"}"
{:enter (fn [state]
(let [cc (-> (get-in state [:request-data :match])
coercion/coerce!)]
(xiana/ok (update-in state [:request :params] merge cc))))
:error (fn [state]
(xiana/error (assoc state :response {:status 400
:body "Request coercion failed"})))
:leave (fn [{{:keys [:status :body]} :response
:as state}]
(let [schema (get-in state [:request-data :match :data :responses status :body])]
(cond (and schema body (m/validate schema body)) (xiana/ok state)
(and schema body) (xiana/error (assoc state :response {:status 400
:body "Response validation failed"}))
:else (xiana/ok state))))})