-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.clj
129 lines (105 loc) · 3.23 KB
/
client.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
(ns dynamodb.client
(:require
[cheshire.core :as json]
[dynamodb.sign :as sign]
[clojure.java.io :as io]
[dynamodb.mask :as mask]
[dynamodb.time :as time]
[org.httpkit.client :as http])
(:import
dynamodb.mask.Mask
java.io.InputStream
java.net.URI
java.util.Map))
(def defaults
{:user-agent "com.github.igrishaev/dynamodb"
:keepalive (* 30 1000)
:insecure? true
:follow-redirects false})
(defrecord Client
[^Mask access-key
^Mask secret-key
^String endpoint
^String content-type
^String host
^String path
^String service
^String version
^String region
^Boolean throw?
^Map http-opt])
(defn make-request
[{:keys [host
path
region
access-key
secret-key
content-type
version
service
throw?
http-opt]}
target
data]
(let [payload
(json/generate-string data)
date
(time/aws-now)
amz-target
(format "DynamoDB_%s.%s" version target)
auth-header
(sign/authorize
{:method "POST"
:uri path
:date date
:headers {"host" host
"content-type" content-type
"x-amz-date" date
"x-amz-target" amz-target}
:payload payload
:service service
:region region
:access-key (mask/unmask access-key)
:secret-key (mask/unmask secret-key)})
headers
{"authorization" auth-header
"content-type" content-type
"x-amz-target" amz-target
"x-amz-date" date}]
(-> http-opt
(assoc :body payload
:headers headers)
(http/request
(fn [{:keys [status ^InputStream body]}]
(-> (with-open [r (io/reader body :encoding "UTF-8")]
(json/parse-stream r keyword))
(as-> data-parsed
(let [{:keys [__type
message ;; yandexdb
Message]}
data-parsed]
(if __type
(let [uri
(new URI __type)
exception
(.getFragment uri)
path
(.getPath uri)]
{:error? true
:status status
:path path
:exception exception
:message (or Message message)
:payload data
:target target})
data-parsed)))
(as-> response
(if (and (get response :error?) throw?)
(throw (ex-info "DynamoDB failure" response))
response)))))
(as-> response
(let [{:as response :keys [error]}
@response]
(if error
(throw error)
response))))))