forked from dakrone/clj-http
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlinks.clj
59 lines (48 loc) · 1.77 KB
/
links.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
(ns clj-http.links
"Namespace dealing with HTTP link headers")
(def ^:private quoted-string
#"\"((?:[^\"]|\\\")*)\"")
(def ^:private token
#"([^,\";]*)")
(def ^:private link-param
(re-pattern (str "(\\w+)=(?:" quoted-string "|" token ")")))
(def ^:private uri-reference
#"<([^>]*)>")
(def ^:private link-value
(re-pattern (str uri-reference "((?:\\s*;\\s*" link-param ")*)")))
(def ^:private link-header
(re-pattern (str "(?:\\s*(" link-value ")\\s*,?\\s*)")))
(defn read-link-params [params]
(into {}
(for [[_ name quot tok] (re-seq link-param params)]
[(keyword name) (or quot tok)])))
(defn read-link-value [value]
(let [[_ uri params] (re-matches link-value value)
param-map (read-link-params params)]
[(keyword (:rel param-map))
(-> param-map
(assoc :href uri)
(dissoc :rel))]))
(defn read-link-headers [header]
(->> (re-seq link-header header)
(map second)
(map read-link-value)
(into {})))
(defn wrap-links
"Add a :links key to the response map that contains parsed Link headers. The
links will be represented as a map, with the 'rel' value being the key. The
URI is placed under the 'href' key, to mimic the HTML link element.
e.g. Link: <http://example.com/page2.html>; rel=next; title=\"Page 2\"
=> {:links {:next {:href \"http://example.com/page2.html\"
:title \"Page 2\"}}}"
[client]
(fn [request]
(let [response (client request)]
(if-let [link-headers (get-in response [:headers "link"])]
(let [link-headers (if (coll? link-headers)
link-headers
[link-headers])]
(assoc response
:links
(into {} (map read-link-headers link-headers))))
response))))