/
middleware.clj
134 lines (121 loc) · 4.94 KB
/
middleware.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
(ns muuntaja.middleware
(:require [muuntaja.core :as m]))
; [^Exception e format request]
(defn- default-on-exception [_ format _]
{:status 400
:headers {"Content-Type" "text/plain"}
:body (str "Malformed " format " request.")})
(defn- handle-exception [exception request on-exception respond raise]
(if-let [data (ex-data exception)]
(if (-> data :type (= :muuntaja/decode))
(respond (on-exception exception (:format data) request))
(raise exception))
(raise exception)))
(defn wrap-exception
"Middleware that catches exceptions of type `:muuntaja/decode`
and invokes a 3-arity callback [^Exception e format request] which
returns a response. Support async-ring."
([handler]
(wrap-exception handler default-on-exception))
([handler on-exception]
(let [throw #(throw %)]
(fn
([request]
(try
(handler request)
(catch Exception e
(handle-exception e request on-exception identity throw))))
([request respond raise]
(try
(handler request respond #(handle-exception % request on-exception respond raise))
(catch Exception e
(handle-exception e request on-exception respond throw))))))))
(defn wrap-params
"Middleware that merges request `:body-params` into `:params`.
Supports async-ring."
[handler]
(letfn [(set-params
([request]
(let [params (:params request)
body-params (:body-params request)]
(cond
(not (map? body-params)) request
(empty? body-params) request
(empty? params) (assoc request :params body-params)
:else (update request :params merge body-params)))))]
(fn
([request]
(handler (set-params request)))
([request respond raise]
(handler (set-params request) respond raise)))))
(defn wrap-format
"Middleware that negotiates a request body based on accept, accept-charset
and content-type headers and decodes the body with an attached Muuntaja
instance into `:body-params`. Encodes also the response body with the same
Muuntaja instance based on the negotiation information or override information
provided by the handler.
Takes a pre-configured Muuntaja or options maps as second argument.
See https://github.com/metosin/muuntaja for all options and defaults.
Supports async-ring."
([handler]
(wrap-format handler m/default-options))
([handler prototype]
(let [m (m/create prototype)]
(fn
([request]
(let [req (m/negotiate-and-format-request m request)]
(some->> (handler req) (m/format-response m req))))
([request respond raise]
(let [req (m/negotiate-and-format-request m request)]
(handler req #(respond (m/format-response m req %)) raise)))))))
;;
;; separate mw for negotiate, request & response
;;
(defn wrap-format-negotiate
"Middleware that negotiates a request body based on accept, accept-charset
and content-type headers with an attached Muuntaja instance. Injects negotiation
results into request for `wrap-format-request` to use.
Takes a pre-configured Muuntaja or options maps as second argument.
See https://github.com/metosin/muuntaja for all options and defaults.
Supports async-ring."
([handler]
(wrap-format-negotiate handler m/default-options))
([handler prototype]
(let [m (m/create prototype)]
(fn
([request]
(handler (m/negotiate-request-response m request)))
([request respond raise]
(handler (m/negotiate-request-response m request) respond raise))))))
(defn wrap-format-request
"Middleware that decodes the request body with an attached Muuntaja
instance into `:body-params` based on the negotiation information provided
by `wrap-format-negotiate`.
Takes a pre-configured Muuntaja or options maps as second argument.
See https://github.com/metosin/muuntaja for all options and defaults.
Supports async-ring."
([handler]
(wrap-format-request handler m/default-options))
([handler prototype]
(let [m (m/create prototype)]
(fn
([request]
(handler (m/format-request m request)))
([request respond raise]
(handler (m/format-request m request) respond raise))))))
(defn wrap-format-response
"Middleware that encodes also the response body with the attached
Muuntaja instance, based on request negotiation information provided by
`wrap-format-negotiate` or override information provided by the handler.
Takes a pre-configured Muuntaja or options maps as second argument.
See https://github.com/metosin/muuntaja for all options and defaults.
Supports async-ring."
([handler]
(wrap-format-response handler m/default-options))
([handler prototype]
(let [m (m/create prototype)]
(fn
([request]
(some->> (handler request) (m/format-response m request)))
([request respond raise]
(handler request #(respond (m/format-response m request %)) raise))))))