-
Notifications
You must be signed in to change notification settings - Fork 149
/
coercion.clj
98 lines (89 loc) · 3.55 KB
/
coercion.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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
(ns compojure.api.coercion
(:require [clojure.walk :as walk]
[compojure.api.exception :as ex]
[compojure.api.request :as request]
[compojure.api.coercion.core :as cc]
[compojure.api.coercion.schema]
[compojure.api.coercion.spec])
(:import (compojure.api.coercion.core CoercionError)))
(def default-coercion :schema)
(defn set-request-coercion [request coercion]
(assoc request ::request/coercion coercion))
(defn get-request-coercion [request]
(if-let [entry (find request ::request/coercion)]
(val entry)
default-coercion))
(defn resolve-coercion [coercion]
(cond
(nil? coercion) nil
(keyword? coercion) (cc/named-coercion coercion)
(satisfies? cc/Coercion coercion) coercion
:else (throw (ex-info (str "invalid coercion " coercion) {:coercion coercion}))))
(defn get-apidocs [maybe-coercion spec info]
(if-let [coercion (resolve-coercion maybe-coercion)]
(cc/get-apidocs coercion spec info)))
(defn coerce-request! [model in type keywordize? open? request]
(let [transform (if keywordize? walk/keywordize-keys identity)
value (transform (in request))]
(if-let [coercion (-> request
(get-request-coercion)
(resolve-coercion))]
(let [model (if open? (cc/make-open coercion model) model)
format (some-> request :muuntaja/request :format)
result (cc/coerce-request coercion model value type format request)]
(if (instance? CoercionError result)
(throw (ex-info
(str "Request validation failed: " (pr-str result))
(merge
(into {} result)
{:type ::ex/request-validation
:coercion coercion
:value value
:in [:request in]
:request request})))
result))
value)))
(defn coerce-response! [request {:keys [status body] :as response} responses]
(if-let [model (or (:schema (get responses status))
(:schema (get responses :default)))]
(if-let [coercion (-> request
(get-request-coercion)
(resolve-coercion))]
(let [format (or (-> response :muuntaja/content-type)
(some-> request :muuntaja/response :format))
accept? (cc/accept-response? coercion model)]
(if accept?
(let [result (cc/coerce-response coercion model body :response format response)]
(if (instance? CoercionError result)
(throw (ex-info
(str "Response validation failed: " (pr-str result))
(merge
(into {} result)
{:type ::ex/response-validation
:coercion coercion
:value body
:in [:response :body]
:request request
:response response})))
(assoc response
:compojure.api.meta/serializable? true
:body result)))
response))
response)
response))
;;
;; middleware
;;
(defn wrap-coerce-response [handler responses]
(fn
([request]
(coerce-response! request (handler request) responses))
([request respond raise]
(handler
request
(fn [response]
(try
(respond (coerce-response! request response responses))
(catch Exception e
(raise e))))
raise))))