'use strict';
|
|
var _regenerator = require('babel-runtime/regenerator');
|
|
var _regenerator2 = _interopRequireDefault(_regenerator);
|
|
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
var assert = require('assert');
|
|
var debug = require('debug')('mns:client');
|
var httpx = require('httpx');
|
var kitx = require('kitx');
|
|
var _require = require('./helper'),
|
getEndpoint = _require.getEndpoint,
|
toXMLBuffer = _require.toXMLBuffer,
|
parseXML = _require.parseXML,
|
extract = _require.extract,
|
getResponseHeaders = _require.getResponseHeaders,
|
getCanonicalizedMNSHeaders = _require.getCanonicalizedMNSHeaders;
|
|
var Client = function () {
|
function Client(accountid, opts) {
|
_classCallCheck(this, Client);
|
|
assert(accountid, '"accountid" must be passed in');
|
this.accountid = accountid;
|
assert(opts, 'must pass in "opts"');
|
// 兼容
|
var accessKeyID = opts.accessKeyId || opts.accessKeyID;
|
assert(accessKeyID, 'must pass in "opts.accessKeyID"');
|
this.accessKeyID = accessKeyID;
|
assert(opts.accessKeySecret, 'must pass in "opts.accessKeySecret"');
|
this.accessKeySecret = opts.accessKeySecret;
|
assert(opts.region, 'must pass in "opts.region"');
|
|
var _getEndpoint = getEndpoint(accountid, opts),
|
domain = _getEndpoint.domain,
|
endpoint = _getEndpoint.endpoint;
|
|
this.endpointDomain = domain;
|
this.endpoint = endpoint;
|
|
// security token
|
this.securityToken = opts.securityToken;
|
}
|
|
_createClass(Client, [{
|
key: 'request',
|
value: function () {
|
var _ref = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee(method, resource, type, requestBody) {
|
var attentions = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : [];
|
var opts = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
|
var url, headers, response, code, contentType, responseBody, body, responseData, e, message, requestid, hostid, err;
|
return _regenerator2.default.wrap(function _callee$(_context) {
|
while (1) {
|
switch (_context.prev = _context.next) {
|
case 0:
|
url = `${this.endpoint}${resource}`;
|
|
debug('url: %s', url);
|
debug('method: %s', method);
|
headers = this.buildHeaders(method, requestBody, resource, opts.headers);
|
|
debug('request headers: %j', headers);
|
debug('request body: %s', requestBody.toString());
|
_context.next = 8;
|
return httpx.request(url, Object.assign(opts, {
|
method: method,
|
headers: headers,
|
data: requestBody
|
}));
|
|
case 8:
|
response = _context.sent;
|
|
|
debug('statusCode %s', response.statusCode);
|
debug('response headers: %j', response.headers);
|
code = response.statusCode;
|
contentType = response.headers['content-type'] || '';
|
// const contentLength = response.headers['content-length'];
|
|
_context.next = 15;
|
return httpx.read(response, 'utf8');
|
|
case 15:
|
responseBody = _context.sent;
|
|
debug('response body: %s', responseBody);
|
|
if (!(responseBody && (contentType.startsWith('text/xml') || contentType.startsWith('application/xml')))) {
|
_context.next = 31;
|
break;
|
}
|
|
_context.next = 20;
|
return parseXML(responseBody);
|
|
case 20:
|
responseData = _context.sent;
|
|
if (!responseData.Error) {
|
_context.next = 29;
|
break;
|
}
|
|
e = responseData.Error;
|
message = extract(e.Message);
|
requestid = extract(e.RequestId);
|
hostid = extract(e.HostId);
|
err = new Error(`${method} ${url} failed with ${code}. ` + `requestid: ${requestid}, hostid: ${hostid}, message: ${message}`);
|
|
err.name = 'MNS' + extract(e.Code) + err.name;
|
throw err;
|
|
case 29:
|
|
body = {};
|
Object.keys(responseData[type]).forEach(function (key) {
|
if (key !== '$') {
|
body[key] = extract(responseData[type][key]);
|
}
|
});
|
|
case 31:
|
return _context.abrupt('return', {
|
code,
|
headers: getResponseHeaders(response.headers, attentions),
|
body: body
|
});
|
|
case 32:
|
case 'end':
|
return _context.stop();
|
}
|
}
|
}, _callee, this);
|
}));
|
|
function request(_x3, _x4, _x5, _x6) {
|
return _ref.apply(this, arguments);
|
}
|
|
return request;
|
}()
|
}, {
|
key: 'get',
|
value: function get(resource, type, opts) {
|
return this.request('GET', resource, type, '', [], opts);
|
}
|
}, {
|
key: 'put',
|
value: function put(resource, type, body) {
|
var attentions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
|
var opts = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
|
|
return this.request('PUT', resource, type, body, attentions, opts);
|
}
|
}, {
|
key: 'post',
|
value: function post(resource, type, body) {
|
return this.request('POST', resource, type, body);
|
}
|
}, {
|
key: 'delete',
|
value: function _delete(resource, type, body) {
|
return this.request('DELETE', resource, type, body);
|
}
|
}, {
|
key: 'sign',
|
value: function sign(verb, headers, resource) {
|
var canonicalizedMNSHeaders = getCanonicalizedMNSHeaders(headers);
|
var md5 = headers['content-md5'] || '';
|
var date = headers['date'];
|
var type = headers['content-type'] || '';
|
|
var toSignString = `${verb}\n${md5}\n${type}\n${date}\n${canonicalizedMNSHeaders}${resource}`;
|
// Signature = base64(hmac-sha1(VERB + "\n"
|
// + CONTENT-MD5 + "\n"
|
// + CONTENT-TYPE + "\n"
|
// + DATE + "\n"
|
// + CanonicalizedMNSHeaders
|
// + CanonicalizedResource))
|
var buff = Buffer.from(toSignString, 'utf8');
|
var degist = kitx.sha1(buff, this.accessKeySecret, 'binary');
|
return Buffer.from(degist, 'binary').toString('base64');
|
}
|
}, {
|
key: 'buildHeaders',
|
value: function buildHeaders(method, body, resource, customHeaders) {
|
var date = new Date().toGMTString();
|
|
var headers = {
|
'date': date,
|
'host': this.endpointDomain,
|
'x-mns-date': date,
|
'x-mns-version': '2015-06-06'
|
};
|
|
if (method !== 'GET' && method !== 'HEAD') {
|
var contentType = 'text/xml';
|
var digest = kitx.md5(body, 'hex');
|
var md5 = Buffer.from(digest, 'utf8').toString('base64');
|
Object.assign(headers, {
|
'content-length': body.length,
|
'content-type': contentType,
|
'content-md5': md5
|
});
|
}
|
|
Object.assign(headers, customHeaders);
|
|
var signature = this.sign(method, headers, resource);
|
|
headers['authorization'] = `MNS ${this.accessKeyID}:${signature}`;
|
|
if (this.securityToken) {
|
headers['security-token'] = this.securityToken;
|
}
|
|
return headers;
|
}
|
|
// Queue
|
|
}, {
|
key: 'createQueue',
|
value: function createQueue(name) {
|
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
var body = toXMLBuffer('Queue', params);
|
var url = `/queues/${name}`;
|
return this.put(url, 'Queue', body, ['location']);
|
}
|
}, {
|
key: 'deleteQueue',
|
value: function deleteQueue(name) {
|
return this.delete(`/queues/${name}`, 'Queue', '');
|
}
|
}, {
|
key: 'listQueue',
|
value: function () {
|
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee2(start, limit, prefix) {
|
var customHeaders, subType, response;
|
return _regenerator2.default.wrap(function _callee2$(_context2) {
|
while (1) {
|
switch (_context2.prev = _context2.next) {
|
case 0:
|
customHeaders = {};
|
|
if (typeof start !== 'undefined') {
|
customHeaders['x-mns-marker'] = start;
|
}
|
|
if (typeof limit !== 'undefined') {
|
customHeaders['x-mns-ret-number'] = limit;
|
}
|
|
if (typeof limit !== 'undefined') {
|
customHeaders['x-mns-prefix'] = prefix;
|
}
|
|
subType = 'Queue';
|
_context2.next = 7;
|
return this.get('/queues', 'Queues', {
|
headers: customHeaders
|
});
|
|
case 7:
|
response = _context2.sent;
|
|
response.body = response.body[subType];
|
return _context2.abrupt('return', response);
|
|
case 10:
|
case 'end':
|
return _context2.stop();
|
}
|
}
|
}, _callee2, this);
|
}));
|
|
function listQueue(_x10, _x11, _x12) {
|
return _ref2.apply(this, arguments);
|
}
|
|
return listQueue;
|
}()
|
}, {
|
key: 'getQueueAttributes',
|
value: function getQueueAttributes(queueName) {
|
return this.get(`/queues/${queueName}`, 'Queue');
|
}
|
}, {
|
key: 'setQueueAttributes',
|
value: function setQueueAttributes(queueName) {
|
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
var body = toXMLBuffer('Queue', params);
|
var url = `/queues/${queueName}?metaoverride=true`;
|
return this.put(url, 'Queue', body);
|
}
|
|
// Message
|
|
}, {
|
key: 'sendMessage',
|
value: function sendMessage(queueName, params) {
|
var url = `/queues/${queueName}/messages`;
|
var body = toXMLBuffer('Message', params);
|
return this.post(url, 'Message', body);
|
}
|
}, {
|
key: 'batchSendMessage',
|
value: function () {
|
var _ref3 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee3(queueName, params) {
|
var url, subType, body, response;
|
return _regenerator2.default.wrap(function _callee3$(_context3) {
|
while (1) {
|
switch (_context3.prev = _context3.next) {
|
case 0:
|
url = `/queues/${queueName}/messages`;
|
subType = 'Message';
|
body = toXMLBuffer('Messages', params, subType);
|
_context3.next = 5;
|
return this.post(url, 'Messages', body);
|
|
case 5:
|
response = _context3.sent;
|
|
response.body = response.body[subType];
|
return _context3.abrupt('return', response);
|
|
case 8:
|
case 'end':
|
return _context3.stop();
|
}
|
}
|
}, _callee3, this);
|
}));
|
|
function batchSendMessage(_x14, _x15) {
|
return _ref3.apply(this, arguments);
|
}
|
|
return batchSendMessage;
|
}()
|
}, {
|
key: 'receiveMessage',
|
value: function receiveMessage(queueName, waitSeconds) {
|
var url = `/queues/${queueName}/messages`;
|
if (waitSeconds) {
|
url += `?waitseconds=${waitSeconds}`;
|
}
|
|
// 31000 31s +1s max waitSeconds is 30s
|
return this.get(url, 'Message', { timeout: 31000 });
|
}
|
}, {
|
key: 'batchReceiveMessage',
|
value: function () {
|
var _ref4 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee4(queueName, numOfMessages, waitSeconds) {
|
var url, subType, response;
|
return _regenerator2.default.wrap(function _callee4$(_context4) {
|
while (1) {
|
switch (_context4.prev = _context4.next) {
|
case 0:
|
url = `/queues/${queueName}/messages?numOfMessages=${numOfMessages}`;
|
|
if (waitSeconds) {
|
url += `&waitseconds=${waitSeconds}`;
|
}
|
|
subType = 'Message';
|
// 31000 31s +1s max waitSeconds is 30s
|
|
_context4.next = 5;
|
return this.get(url, 'Messages', { timeout: 31000 });
|
|
case 5:
|
response = _context4.sent;
|
|
response.body = response.body[subType];
|
return _context4.abrupt('return', response);
|
|
case 8:
|
case 'end':
|
return _context4.stop();
|
}
|
}
|
}, _callee4, this);
|
}));
|
|
function batchReceiveMessage(_x16, _x17, _x18) {
|
return _ref4.apply(this, arguments);
|
}
|
|
return batchReceiveMessage;
|
}()
|
}, {
|
key: 'peekMessage',
|
value: function peekMessage(queueName) {
|
return this.get(`/queues/${queueName}/messages?peekonly=true`, 'Message');
|
}
|
}, {
|
key: 'batchPeekMessage',
|
value: function () {
|
var _ref5 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee5(queueName, numOfMessages) {
|
var url, subType, response;
|
return _regenerator2.default.wrap(function _callee5$(_context5) {
|
while (1) {
|
switch (_context5.prev = _context5.next) {
|
case 0:
|
url = `/queues/${queueName}/messages?` + `peekonly=true&numOfMessages=${numOfMessages}`;
|
subType = 'Message';
|
// 31000 31s +1s max waitSeconds is 30s
|
|
_context5.next = 4;
|
return this.get(url, 'Messages');
|
|
case 4:
|
response = _context5.sent;
|
|
response.body = response.body[subType];
|
return _context5.abrupt('return', response);
|
|
case 7:
|
case 'end':
|
return _context5.stop();
|
}
|
}
|
}, _callee5, this);
|
}));
|
|
function batchPeekMessage(_x19, _x20) {
|
return _ref5.apply(this, arguments);
|
}
|
|
return batchPeekMessage;
|
}()
|
}, {
|
key: 'deleteMessage',
|
value: function deleteMessage(queueName, receiptHandle) {
|
var url = `/queues/${queueName}/messages?ReceiptHandle=${receiptHandle}`;
|
return this.delete(url, 'Message', '');
|
}
|
}, {
|
key: 'batchDeleteMessage',
|
value: function () {
|
var _ref6 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee6(queueName, receiptHandles) {
|
var body, url, response, subType;
|
return _regenerator2.default.wrap(function _callee6$(_context6) {
|
while (1) {
|
switch (_context6.prev = _context6.next) {
|
case 0:
|
body = toXMLBuffer('ReceiptHandles', receiptHandles, 'ReceiptHandle');
|
url = `/queues/${queueName}/messages`;
|
_context6.next = 4;
|
return this.delete(url, 'Errors', body);
|
|
case 4:
|
response = _context6.sent;
|
|
// 3种情况,普通失败,部分失败,全部成功
|
if (response.body) {
|
subType = 'Error';
|
// 部分失败
|
|
response.body = response.body[subType];
|
}
|
return _context6.abrupt('return', response);
|
|
case 7:
|
case 'end':
|
return _context6.stop();
|
}
|
}
|
}, _callee6, this);
|
}));
|
|
function batchDeleteMessage(_x21, _x22) {
|
return _ref6.apply(this, arguments);
|
}
|
|
return batchDeleteMessage;
|
}()
|
}, {
|
key: 'changeMessageVisibility',
|
value: function changeMessageVisibility(queueName, receiptHandle, visibilityTimeout) {
|
var url = `/queues/${queueName}/messages?` + `receiptHandle=${receiptHandle}&visibilityTimeout=${visibilityTimeout}`;
|
return this.put(url, 'ChangeVisibility', '');
|
}
|
|
// Topic
|
|
}, {
|
key: 'createTopic',
|
value: function createTopic(name) {
|
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
var body = toXMLBuffer('Topic', params);
|
return this.put(`/topics/${name}`, 'Topic', body, ['location']);
|
}
|
}, {
|
key: 'deleteTopic',
|
value: function deleteTopic() {}
|
}, {
|
key: 'listTopic',
|
value: function () {
|
var _ref7 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee7(start, limit, prefix) {
|
var customHeaders, subType, response;
|
return _regenerator2.default.wrap(function _callee7$(_context7) {
|
while (1) {
|
switch (_context7.prev = _context7.next) {
|
case 0:
|
customHeaders = {};
|
|
if (typeof start !== 'undefined') {
|
customHeaders['x-mns-marker'] = start;
|
}
|
|
if (typeof limit !== 'undefined') {
|
customHeaders['x-mns-ret-number'] = limit;
|
}
|
|
if (typeof limit !== 'undefined') {
|
customHeaders['x-mns-prefix'] = prefix;
|
}
|
|
subType = 'Topic';
|
_context7.next = 7;
|
return this.get('/topics', 'Topics', {
|
headers: customHeaders
|
});
|
|
case 7:
|
response = _context7.sent;
|
|
response.body = response.body[subType];
|
return _context7.abrupt('return', response);
|
|
case 10:
|
case 'end':
|
return _context7.stop();
|
}
|
}
|
}, _callee7, this);
|
}));
|
|
function listTopic(_x24, _x25, _x26) {
|
return _ref7.apply(this, arguments);
|
}
|
|
return listTopic;
|
}()
|
}, {
|
key: 'getTopicAttributes',
|
value: function getTopicAttributes(name) {
|
return this.get(`/topics/${name}`, 'Topic');
|
}
|
}, {
|
key: 'setTopicAttributes',
|
value: function setTopicAttributes(name) {
|
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
var body = toXMLBuffer('Topic', params);
|
var url = `/topics/${name}?metaoverride=true`;
|
return this.put(url, 'Topic', body);
|
}
|
|
// Subscription
|
|
}, {
|
key: 'subscribe',
|
value: function subscribe() {}
|
}, {
|
key: 'unsubscribe',
|
value: function unsubscribe() {}
|
}, {
|
key: 'listSubscriptionByTopic',
|
value: function listSubscriptionByTopic() {}
|
}, {
|
key: 'getSubscriptionAttributes',
|
value: function getSubscriptionAttributes() {}
|
}, {
|
key: 'setSubscriptionAttributes',
|
value: function setSubscriptionAttributes() {}
|
|
// Message
|
|
}, {
|
key: 'publishMessage',
|
value: function publishMessage(topic, params) {
|
var url = `/topics/${topic}/messages`;
|
var body = toXMLBuffer('Message', params);
|
return this.post(url, 'Message', body);
|
}
|
|
// Notifications
|
|
}, {
|
key: 'httpEndpoint',
|
value: function httpEndpoint() {}
|
}]);
|
|
return Client;
|
}();
|
|
module.exports = Client;
|