/
dev.clj
192 lines (164 loc) · 5.31 KB
/
dev.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
; Copyright (c) Shantanu Kumar. All rights reserved.
; The use and distribution terms for this software are covered by the
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
; which can be found in the file LICENSE at the root of this distribution.
; By using this software in any fashion, you are agreeing to be bound by
; the terms of this license.
; You must not remove this notice, or any other, from this software.
(ns bract.ring.dev
"Development support for bract.ring module."
(:require
[clojure.stacktrace :as st]
[bract.core.dev :as core-dev]
[bract.core.echo :as core-echo]
[bract.core.util :as core-util]
[bract.ring.keydef :as ring-kdef]))
;; ----- lein-ring support -----
(defn- unprepared-handler
[request]
(throw (ex-info "Ring handler is not yet initialized" {})))
(def ^:redef handler unprepared-handler)
(defn init!
"Initialize environment and the Ring handler."
([]
(init! (core-dev/init)))
([context]
(let [ctx-handler (ring-kdef/ctx-ring-handler context)]
(alter-var-root #'handler (constantly ctx-handler))
(core-echo/echo "Updated bract.ring.dev/handler")
context)))
(defn init-once!
"Given a var e.g. `(defonce a-var nil)` having logical false value, set it to `true` and initialize app in DEV mode,
finally updating the [[bract.ring.dev/handler]] var."
([]
(when-let [context (core-dev/init-once!)]
(init! context)))
([a-var]
(when-let [context (core-dev/init-once! a-var)]
(init! context))))
;; ----- Ring traffic logging support -----
(def http-method
{:delete "DELETE"
:get "GET"
:head "HEAD"
:options "OPTIONS"
:patch "PATH"
:post "POST"
:put "PUT"})
(def http-status
{;; 1xx
100 "Continue"
101 "Switching protocol"
102 "Processing (WebDAV)"
103 "Early Hints"
;; 2xx
200 "OK"
201 "Created"
202 "Accepted"
203 "Non-Authoritative Information"
204 "No Content"
205 "Reset Content"
206 "Partial Content"
207 "Multi-Status (WebDAV)"
208 "Already Reported (WebDAV)"
226 "IM Used (HTTP Delta Encoding)"
;; 3xx
300 "Multiple Choice"
301 "Moved Permanently"
302 "Found"
303 "See Other"
304 "Not Modified"
305 "Use Proxy"
306 "Switch Proxy"
307 "Temporary Redirect"
308 "Permanent Redirect"
;; 4xx
400 "Bad Request"
401 "Unauthorized"
402 "Payment Required"
403 "Forbidden"
404 "Not Found"
405 "Method Not Allowed"
406 "Not Acceptable"
407 "Proxy Authentication Required"
408 "Request Timeout"
409 "Conflict"
410 "Gone"
411 "Length Required"
412 "Precondition Failed"
413 "Payload Too Large"
414 "URI Too Long"
415 "Unsupported Media Type"
416 "Range Not Satisfiable"
417 "Expectation Failed"
418 "I'm a teapot"
421 "Misdirected Request"
422 "Unprocessable Entity (WebDAV)"
423 "Locked (WebDAV)"
424 "Failed Dependency (WebDAV)"
425 "Too Early"
426 "Upgrade Required"
428 "Precondition Required"
429 "Too Many Requests"
431 "Request Header Fields Too Large"
451 "Unavailable For Legal Reasons"
;; 5xx
500 "Internal Server Error"
501 "Not Implemented"
502 "Bad Gateway"
503 "Service Unavailable"
504 "Gateway Timeout"
505 "HTTP Version Not Supported"
506 "Variant Also Negotiates"
507 "Insufficient Storage (WebDAV)"
508 "Loop Detected (WebDAV)"
510 "Not Extended"
511 "Network Authentication Required"
})
(def nop (constantly nil))
(defn log-request
"Log Ring request.
See: `bract.ring.middleware/traffic-log-middleware`, `bract.ring.wrapper/traffic-log-wrapper`"
[request]
(let [{:keys [request-method
uri
headers]} request]
(-> "%7s %s | %s"
(format (http-method request-method) uri (pr-str headers))
core-util/err-println)))
(defn log-outcome
"Common function to log response and exception.
See: [[log-response]], [[log-exception]]"
[request outcome-string ^double duration-millis]
(let [{:keys [request-method
uri
headers]} request
[request-methstr
request-uri
request-headers] [(http-method request-method) uri (pr-str headers)]]
(-> "%10.2fms | %-60s | %7s %s %s"
(format duration-millis outcome-string
request-methstr request-uri request-headers)
core-util/err-println)))
(defn log-response
"Log Ring response.
See: `bract.ring.middleware/traffic-log-middleware`, `bract.ring.wrapper/traffic-log-wrapper`"
[request response ^double duration-millis]
(log-outcome
request
(if (map? response)
(let [{:keys [status
headers]} response
[response-status response-statusmsg response-headers] [status (http-status status) (pr-str headers)]]
(format "%d %-15s %-40s" response-status response-statusmsg response-headers))
(format "Bad response: (%s) %s" (.getName (class response)) (pr-str response)))
duration-millis))
(defn log-exception
"Log Ring request processing exception.
See: `bract.ring.middleware/traffic-log-middleware`, `bract.ring.wrapper/traffic-log-wrapper`"
[request exception ^double duration-millis]
(log-outcome
request
(format "%s: %s" (.getName ^Class (class exception)) (.getMessage ^Throwable exception))
duration-millis)
(st/print-stack-trace exception))