-
Notifications
You must be signed in to change notification settings - Fork 250
/
coercion.cljc
70 lines (67 loc) · 3.03 KB
/
coercion.cljc
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
58
59
60
61
62
63
64
65
66
67
68
69
70
(ns reitit.http.coercion
(:require [reitit.coercion :as coercion]
[reitit.impl :as impl]
[reitit.spec :as rs]))
(defn coerce-request-interceptor
"Interceptor for pluggable request coercion.
Expects a :coercion of type `reitit.coercion/Coercion`
and :parameters from route data, otherwise does not mount."
[]
{:name ::coerce-request
:spec ::rs/parameters
:compile (fn [{:keys [coercion parameters]} opts]
(cond
;; no coercion, skip
(not coercion) nil
;; just coercion, don't mount
(not parameters) {}
;; mount
:else
(if-let [coercers (coercion/request-coercers coercion parameters opts)]
{:enter (fn [ctx]
(let [request (:request ctx)
coerced (coercion/coerce-request coercers request)
request (impl/fast-assoc request :parameters coerced)]
(assoc ctx :request request)))}
{})))})
(defn coerce-response-interceptor
"Interceptor for pluggable response coercion.
Expects a :coercion of type `reitit.coercion/Coercion`
and :responses from route data, otherwise does not mount."
[]
{:name ::coerce-response
:spec ::rs/responses
:compile (fn [{:keys [coercion responses]} opts]
(cond
;; no coercion, skip
(not coercion) nil
;; just coercion, don't mount
(not responses) {}
;; mount
:else
(if-let [coercers (coercion/response-coercers coercion responses opts)]
{:leave (fn [ctx]
(let [request (:request ctx)
response (:response ctx)
response (coercion/coerce-response coercers request response)]
(assoc ctx :response response)))}
{})))})
(defn coerce-exceptions-interceptor
"Interceptor for handling coercion exceptions.
Expects a :coercion of type `reitit.coercion/Coercion`
and :parameters or :responses from route data, otherwise does not mount."
[]
{:name ::coerce-exceptions
:compile (fn [{:keys [coercion parameters responses]} _]
(if (and coercion (or parameters responses))
{:error (fn [ctx]
(let [data (ex-data (:error ctx))]
(if-let [status (case (:type data)
::coercion/request-coercion 400
::coercion/response-coercion 500
nil)]
(let [response {:status status, :body (coercion/encode-error data)}]
(-> ctx
(assoc :response response)
(assoc :error nil)))
ctx)))}))})