This repository has been archived by the owner on Jan 15, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
dynamo_client.js
141 lines (109 loc) · 3.84 KB
/
dynamo_client.js
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
var dynamo = exports
var http = require("http")
var https = require("https")
var aws4 = require("aws4")
function Database(region, credentials) {
if (typeof region === "object") {
this.host = region.host
this.port = region.port
this.region = region.region
this.version = region.version // '20120810' or '20111205'
this.agent = region.agent
this.https = region.https
credentials = region.credentials || credentials
} else {
if (/^[a-z]{2}\-[a-z]+\-\d$/.test(region))
this.region = region
else
// Backwards compatibility for when 1st param was host
this.host = region
}
if (!this.region) this.region = (this.host || "").split(".", 2)[1] || "us-east-1"
if (!this.host) this.host = "dynamodb." + this.region + ".amazonaws.com"
if (!this.version) this.version = "20120810"
this.credentials = new Credentials(credentials || {})
}
Database.prototype.request = function(target, data, cb) {
!function retry(database, i) {
var req = new Request(database, target, data || {})
aws4.sign(req, database.credentials)
req.send(function(err, data) {
if (err) {
if (i < Request.prototype.maxRetries && (
err.statusCode >= 500 ||
err.name == "ProvisionedThroughputExceededException" ||
err.name == "ThrottlingException"
)) {
setTimeout(retry, 50 << i, database, i + 1)
}
else cb(err)
}
else cb(null, data)
})
}(this, 0)
}
function Request(opts, target, data) {
var headers = this.headers = {}
this.host = opts.host
this.port = opts.port
this.http = opts.https ? https : http
if ("agent" in opts) this.agent = opts.agent
this.body = JSON.stringify(data)
this.method = Request.prototype.method
this.path = Request.prototype.path
this.maxRetries = Request.prototype.maxRetries
this.contentType = Request.prototype.contentType
headers["Host"] = this.host
headers["Date"] = new Date().toUTCString()
headers["Content-Length"] = Buffer.byteLength(this.body)
headers["Content-Type"] = Request.prototype.contentType
headers["X-Amz-Target"] = "DynamoDB_" + opts.version + "." + target
}
Request.prototype.method = "POST"
Request.prototype.path = "/"
Request.prototype.maxRetries = 10
Request.prototype.contentType = "application/x-amz-json-1.0"
Request.prototype.send = function(cb) {
var request = this.http.request(this, function(res) {
var json = ""
res.setEncoding("utf8")
res.on("data", function(chunk){ json += chunk })
res.on("end", function() {
var response
try { response = JSON.parse(json) } catch (e) { }
if (res.statusCode == 200 && response != null) return cb(null, response)
error.statusCode = res.statusCode
if (response != null) {
error.name = (response.__type || "").split("#").pop()
error.message = response.message || response.Message || JSON.stringify(response)
} else {
if (res.statusCode == 413) json = "Request Entity Too Large"
error.message = "HTTP/1.1 " + res.statusCode + " " + json
}
cb(error)
})
})
var error = new Error
request.on("error", cb)
request.write(this.body)
request.end()
}
function Credentials(attrs) {
var env = process.env
this.secretAccessKey = attrs.secretAccessKey || env.AWS_SECRET_ACCESS_KEY
this.accessKeyId = attrs.accessKeyId || env.AWS_ACCESS_KEY_ID
if (!this.secretAccessKey) {
throw new Error("No secret access key available.")
}
if (!this.accessKeyId) {
throw new Error("No access key id available.")
}
// Optional session token, if the user wants to supply one
this.sessionToken = attrs.sessionToken
}
dynamo.Database = Database
dynamo.Request = Request
dynamo.Credentials = Credentials
dynamo.createClient = function(region, credentials) {
return new Database(region, credentials)
}