-
-
Notifications
You must be signed in to change notification settings - Fork 48
/
common.clj
89 lines (77 loc) · 3.51 KB
/
common.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
(ns ring.adapter.jetty9.common
(:require [ring.core.protocols :as protocols])
(:import [org.eclipse.jetty.http HttpHeader HttpField MimeTypes MimeTypes$Type]
[org.eclipse.jetty.server.handler BufferedResponseHandler]
[org.eclipse.jetty.server Request Response SecureRequestCustomizer]
[org.eclipse.jetty.io Content$Sink EndPoint$SslSessionData]
[org.eclipse.jetty.http ImmutableHttpFields HttpFields$Mutable HttpURI]
[java.util Locale]))
(defn set-headers!
"Update response with a map of headers."
[^Response response headers]
(let [^HttpFields$Mutable header-writer (.getHeaders response)]
(doseq [[key val-or-vals] headers]
(if (string? val-or-vals)
(.add header-writer ^String key ^String val-or-vals)
(doseq [val val-or-vals]
(.add header-writer ^String key ^String val))))))
(defn- header-kv*
[^HttpField header]
[(.getLowerCaseName header) (.getValue header)])
(defn get-headers
"Creates a name/value map of all the request headers."
[^Request request]
(into {} (map header-kv*) (.getHeaders request)))
(defonce noop (constantly nil))
(defn normalize-response
"Normalize response for ring spec"
[response]
(if (string? response)
{:body response}
response))
(defn websocket-upgrade-response?
[resp]
(contains? resp :ring.websocket/listener))
(defn get-charset [^Request request]
(when-let [content-type (.. request getHeaders (get HttpHeader/CONTENT_TYPE))]
(or (when-let [^MimeTypes$Type mime (.get MimeTypes/CACHE content-type)]
(when-let [charset (.getCharset mime)]
(str charset)))
(MimeTypes/getCharsetFromContentType content-type))))
(defn- get-client-cert [^Request request]
(when-let [session-data (.getAttribute request EndPoint$SslSessionData/ATTRIBUTE)]
(.peerCertificates ^EndPoint$SslSessionData session-data)))
(defn build-request-map
"Create the request map from the Request object."
[^Request request]
(let [^HttpURI uri (.getHttpURI request)
^ImmutableHttpFields headers (.getHeaders request)]
{:server-port (Request/getServerPort request)
:server-name (Request/getServerName request)
:remote-addr (Request/getRemoteAddr request)
:uri (when uri (.getPath uri))
:query-string (when uri (.getQuery uri))
:scheme (when uri (keyword (.getScheme uri)))
:request-method (keyword (.toLowerCase ^String (.getMethod request) Locale/ENGLISH))
:protocol (.getProtocol (.getConnectionMetaData request))
:headers (get-headers request)
:content-type (.. headers (get HttpHeader/CONTENT_TYPE))
:content-length (when-let [l (.. headers (get HttpHeader/CONTENT_LENGTH))]
(Integer/valueOf l))
:character-encoding (get-charset request)
:ssl-client-cert (get-client-cert request)
:body (Request/asInputStream request)}))
(defn update-response
"Update Jetty Response from given Ring response map"
[^Request request ^Response response response-map]
(let [{:keys [status headers body]} response-map]
(cond
(nil? response) (throw (NullPointerException. "Response is nil"))
(nil? response-map) (throw (NullPointerException. "Ring response map is nil"))
:else
(do
(some->> status (.setStatus response))
(set-headers! response headers)
(->>
(Response/asBufferedOutputStream request response)
(protocols/write-body-to-stream body response-map))))))