-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathQcloudApi.js
169 lines (145 loc) · 4.74 KB
/
QcloudApi.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
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
var request = require('request')
var assign = require('object-assign')
var qs = require('querystring')
var dotQs = require('dot-qs');
var crypto = require('crypto')
var baseHost = 'api.qcloud.com'
/**
* API 构造函数
* @param {Object} [defaults] 默认参数及配置
* @param {String} defaults.serviceType 服务类型. 如: cvm, vpc, dfw, lb 等. 根据 `serviceType` 和 `baseHost` 将拼装成请求域名, 如: `vpc.api.qcloud.com`
* @param {String} defaults.path='/v2/index.php' Api 请求路径
* @param {String} defaults.method='POST' 请求方法
* @param {String} defaults.baseHost='api.qcloud.com' Api 的基础域名. 与 `serviceType` 拼装成请求域名.
* @param {String} defaults.SecretId secretId
* @param {String} defaults.SecretKey secretKey
* @constructor
*/
var QcloudApi = function (defaults) {
this.defaults = assign({
path: '/v2/index.php',
method: 'POST',
baseHost: baseHost
}, defaults)
}
/**
* 生成 API 的请求地址
* @param {Object} opts
* @returns {string}
*/
QcloudApi.prototype.generateUrl = function (opts) {
opts = opts || {}
var host = this._getHost(opts)
return 'https://' + host + (opts.path || this.defaults.path)
}
/**
* 生成请求参数.
* @param {Object} data 该次请求的参数. 同 `request` 方法的 `data` 参数
* @param {Object} [opts] 请求配置. 同 `request` 方法的 `opts` 参数
* @returns {string} 包括签名的参数字符串
*/
QcloudApi.prototype.generateQueryString = function (data, opts) {
opts = opts || this.defaults
var defaults = this.defaults
var param = assign({
Region: this.defaults.Region,
SecretId: opts.SecretId || this.defaults.SecretId,
Timestamp: Math.round(Date.now() / 1000),
Nonce: Math.round(Math.random() * 65535)
}, data)
param = dotQs.flatten(param)
var keys = Object.keys(param)
var qstr = '',
signStr
var host = this._getHost(opts)
var method = (opts.method || defaults.method)
.toUpperCase()
keys.sort()
//拼接 querystring, 注意这里拼接的参数要和下面 `qs.stringify` 里的参数一致
keys.forEach(function (key) {
var val = param[key]
// 排除上传文件的参数
if (method === 'POST' && val && val[0] === '@') {
return
}
if (key === '') {
return
}
if (val === undefined || val === null || (typeof val === 'number' && isNaN(val))) {
val = ''
}
//把参数中的 _ 替换成 .
qstr += '&' + key.replace('_', '.') + '=' + val
})
qstr = qstr.slice(1)
signStr = this.sign(method + host + (opts.path || defaults.path) + '?' + qstr, opts.SecretKey || defaults.SecretKey)
param.Signature = signStr
return qs.stringify(param)
}
/**
* 请求 API
* @param {Object} data 该次请求的参数.
* @param {Object} [data.SecretId] Api SecrectId, 通过 `data` 参数传入时将覆盖 `opt` 传入及默认的 `secretId`
* @param {Object} [opts] 请求配置. 配置里的参数缺省使用默认配置 (`this.defaults`) 里的对应项
* @param {String} opts.host 该次请求使用的 API host. 当传入该参数的时候, 将忽略 `serviceType` 及默认 `host`
* @param {requestCallback} callback
*/
QcloudApi.prototype.request = function (data, opts, callback) {
if (typeof opts === 'function') {
callback = opts
opts = this.defaults
}
opts = opts || this.defaults
callback = callback || Function.prototype
var url = this.generateUrl(opts)
var method = (opts.method || this.defaults.method)
.toUpperCase()
var dataStr = this.generateQueryString(data, opts)
var option = {
url: url,
method: method,
json: true,
strictSSL: false
}
if (method === 'POST') {
option.form = qs.parse(dataStr)
} else {
option.url += '?' + dataStr
}
request(option, function (error, response, body) {
/**
* `.request` 的请求回调
* @callback requestCallback
* @param {Error} error 请求错误
* @param {Object} body API 请求结果
*/
callback(error, body)
})
}
/**
* 生成签名
* @param {String} str 需签名的参数串
* @param {String} secretKey
* @returns {String} 签名
*/
QcloudApi.prototype.sign = function (str, secretKey) {
var hmac = crypto.createHmac('sha1', secretKey || '')
return hmac.update(new Buffer(str, 'utf8'))
.digest('base64')
}
/**
* 获取 API host
* @param opts 请求配置
* @param {String} [opts.serviceType] 服务类型. 如: cvm, vpc, dfw, lb 等
* @param {String} [opts.host] 如果配置中直接传入 host, 则直接返回该 host
* @returns {String}
* @private
*/
QcloudApi.prototype._getHost = function (opts) {
var host = opts.host
if (!host) {
host = (opts.serviceType || this.defaults.serviceType) + '.' + (opts.baseHost || this.defaults.baseHost)
}
return host
}
module.exports = QcloudApi