/
core.clj
83 lines (68 loc) · 2.6 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
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
(ns liberator-mixin.json.core
(:require
[clojure.string :refer [starts-with?]]
[jason.convenience :as jason-conv]
[liberator.representation :as r]
[liberator-mixin.context.core :refer [with-attribute-in-context]])
(:import
[com.fasterxml.jackson.core JsonParseException]))
(defn- json-request? [request]
(if-let [type (get-in request [:headers "content-type"])]
(seq (re-find #"^application/(.+\+)?json" type))))
(defn- read-json-body [request decoder]
(if (json-request? request)
(if-let [body (:body request)]
(let [body-string (slurp body)]
(try
[true (decoder body-string)]
(catch JsonParseException _
[false nil]))))))
(defn- read-json-params [request decoder]
(letfn [(parse-param [value]
(try
(if (coll? value)
(into (empty value) (map parse-param value))
(decoder value))
(catch JsonParseException _
value)))]
(let [params (:params request)]
(into {}
(map (fn [[k v]] [k (parse-param v)])
params)))))
(def json-media-type "application/json")
(defmethod r/render-map-generic json-media-type [data {:keys [json]}]
((get json :encoder jason-conv/->wire-json) data))
(defmethod r/render-seq-generic json-media-type [data {:keys [json]}]
((get json :encoder jason-conv/->wire-json) data))
(defn with-json-media-type []
{:available-media-types [json-media-type]})
(defn with-json-decoder [decoder]
(with-attribute-in-context :json {:decoder decoder}))
(defn with-json-encoder [encoder]
(with-attribute-in-context :json {:encoder encoder}))
(defn with-body-parsed-as-json []
{:initialize-context
(fn [{:keys [request json]}]
(let [decoder (get json :decoder jason-conv/<-wire-json)]
(if-let [[valid? json] (read-json-body request decoder)]
(if valid?
{:request {:body json}}
{:malformed? true}))))
:malformed?
(fn [{:keys [malformed?]}] malformed?)})
(defn with-params-parsed-as-json []
{:initialize-context
(fn [{:keys [request json]}]
(let [decoder (get json :decoder jason-conv/<-wire-json)
params (read-json-params request decoder)]
{:request {:params (with-meta params {:replace true})}}))})
(defn with-json-mixin
([] (with-json-mixin {}))
([dependencies]
[(with-json-encoder
(get-in dependencies [:json :encoder] jason-conv/->wire-json))
(with-json-decoder
(get-in dependencies [:json :decoder] jason-conv/<-wire-json))
(with-json-media-type)
(with-body-parsed-as-json)
(with-params-parsed-as-json)]))