From e6d5f09b4bdc6eeeeeaaf9e08c7e517d3e1a29da Mon Sep 17 00:00:00 2001 From: Michael Dunaevsky Date: Tue, 23 Oct 2018 16:01:32 +0300 Subject: [PATCH 1/3] updated all funcs with limiter --- app.js | 260 ++++++++++++++++++++------------------------------- package.json | 3 +- 2 files changed, 103 insertions(+), 160 deletions(-) diff --git a/app.js b/app.js index 1052bbb..5908e8e 100644 --- a/app.js +++ b/app.js @@ -1,17 +1,15 @@ -/** - * Created by harel on 15/08/2017. - */ const request = require("request"); +const RateLimiter = require('request-rate-limiter'); +const limiter = new RateLimiter(120); //120 requests per minute -var api_key, short_domain; - +let api_key, short_domain; const cm_short = { auth: function (apiKey, shortDomain) { api_key = apiKey; short_domain = shortDomain || "smart.short.cm"; }, domainApi: function (apiKey) { - var options = { + const options = { method: 'GET', url: 'https://api.short.cm/api/domains', headers: { @@ -19,23 +17,10 @@ const cm_short = { 'Authorization': apiKey } }; - return new Promise(function (resolve, reject) { - request(options, function (error, response, body) { - if (!error && response.statusCode == 200) { - var info = checkIfJsonStringAndParse(body); - info.error? reject(info) : resolve(info);; - } else { - reject({ - msg: "error in domain api request", - error: error, - response: response - }); - } - }) - }); + return makeLimitedRequest(options); }, shorten: function (url) { - var options = { + const options = { method: 'POST', url: 'https://api.short.cm/links', form: { @@ -47,20 +32,7 @@ const cm_short = { 'Authorization': api_key } }; - return new Promise(function (resolve, reject) { - request(options, function (error, response, body) { - if (!error && response.statusCode == 200) { - var info = checkIfJsonStringAndParse(body); - info.error? reject(info) : resolve(info);; - } else { - reject({ - msg: "error in shorten api request", - error: error, - response: response - }); - } - }) - }); + return makeLimitedRequest(options); }, getPathFromUrl: function (url) { return url.replace(short_domain, '').replace(/(http:\/\/|https:\/\/|\/)/g, '') @@ -83,7 +55,7 @@ const cm_short = { }, delete: function (link_id) { return new Promise(function (resolve, reject) { - var options = { + const options = { method: 'DELETE', url: 'https://api.short.cm/links/' + link_id, headers: { @@ -94,7 +66,8 @@ const cm_short = { request(options, function (error, response, body) { if (!error && response.statusCode == 200) { var info = checkIfJsonStringAndParse(body); - info.error? reject(info) : resolve(info);; + info.error ? reject(info) : resolve(info); + ; } else { console.log('Status:', response.statusCode); console.log('Headers:', JSON.stringify(response.headers)); @@ -111,135 +84,73 @@ const cm_short = { }, expand: function (url) { - return new Promise(function (resolve, reject) { - var options = { - method: 'GET', - url: 'https://api.short.cm/links/expand?domain=' + encodeURI(short_domain) + '&path=' + encodeURI(cm_short.getPathFromUrl(url)), - headers: { - 'Content-Type': 'application/json', - 'Authorization': api_key - } - }; - request(options, function (error, response, body) { - if (!error && response.statusCode == 200) { - var info = checkIfJsonStringAndParse(body); - info.error? reject(info) : resolve(info);; - } else { - reject({ - msg: "error in expand api request", - error: error, - response: response - }); - } - }) - }); + const options = { + method: 'GET', + url: 'https://api.short.cm/links/expand?domain=' + encodeURI(short_domain) + '&path=' + encodeURI(cm_short.getPathFromUrl(url)), + headers: { + 'Content-Type': 'application/json', + 'Authorization': api_key + } + }; + return makeLimitedRequest(options); }, + expandByLongUrl: function (url) { - return new Promise(function (resolve, reject) { - var options = { - method: 'GET', - url: 'https://api.short.cm/links/by-original-url?domain=' + encodeURI(short_domain) + '&originalURL=' + encodeURIComponent(url), - headers: { - 'Content-Type': 'application/json', - 'Authorization': api_key - } - }; - request(options, function (error, response, body) { - if (!error && response.statusCode == 200) { - var info = checkIfJsonStringAndParse(body); - info.error? reject(info) : resolve(info);; - } else { - reject({ - msg: "error in expand api request", - error: error, - response: response - }); - } - }) - }); + const options = { + method: 'GET', + url: 'https://api.short.cm/links/by-original-url?domain=' + encodeURI(short_domain) + '&originalURL=' + encodeURIComponent(url), + headers: { + 'Content-Type': 'application/json', + 'Authorization': api_key + } + }; + return makeLimitedRequest(options); }, analyticsById: function (link_id) { - return new Promise(function (resolve, reject) { - var options = { - method: 'GET', - url: 'https://api.short.cm/links/statistics/' + link_id + '?period=total', - // url: 'https://api.short.cm/links/' + link_id + '/statistics', - headers: { - 'Content-Type': 'application/json', - 'Authorization': api_key - } - }; - request(options, function (error, response, body) { - if (!error && response.statusCode == 200) { - var info = checkIfJsonStringAndParse(body); - info.error? reject(info) : resolve(info);; - } else { - reject({ - msg: "error in analytics shorten api request", - error: error, - response: response - }); - } - }) - }); + const options = { + method: 'GET', + url: 'https://api.short.cm/links/statistics/' + link_id + '?period=total', + // url: 'https://api.short.cm/links/' + link_id + '/statistics', + headers: { + 'Content-Type': 'application/json', + 'Authorization': api_key + } + }; + return makeLimitedRequest(options); }, updateShortUrlByLinkId: function (link_id, newLongUrl) { - return new Promise(function (resolve, reject) { - var options = { - method: 'POST', - url: 'https://api.short.cm/links/' + link_id, - form: { - originalURL: newLongUrl, - // title: title || "title_placeholder" - }, - headers: { - 'Content-Type': 'application/json', - 'Authorization': api_key - } - }; - request(options, function (error, response, body) { - if (!error && response.statusCode == 200) { - var info = checkIfJsonStringAndParse(body); - info.error ? reject(info) : resolve(info); - } else { - reject({ - msg: "error in update shorten api request", - error: error, - response: response - }); - } - }) - }); + const options = { + method: 'POST', + url: 'https://api.short.cm/links/' + link_id, + form: { + originalURL: newLongUrl, + // title: title || "title_placeholder" + }, + headers: { + 'Content-Type': 'application/json', + 'Authorization': api_key + } + }; + return makeLimitedRequest(options); }, + updateLocaleById: function (link_id, country, url) { - return new Promise(function (resolve, reject) { - var options = { - method: 'POST', - url: 'https://api.short.cm/link_country/' + link_id, - form: { - originalURL: url, - country: country - // title: title || "title_placeholder" - }, - headers: { - 'Content-Type': 'application/json', - 'Authorization': api_key - } - }; - request(options, function (error, response, body) { - if (!error && response.statusCode == 200) { - var info = checkIfJsonStringAndParse(body); - info.error ? reject(info) : resolve(info); - } else { - reject({ - msg: "error in updateLocale api request", - error: error, - response: response - }); - } - }) - }); + const options = { + method: 'POST', + url: 'https://api.short.cm/link_country/' + link_id, + form: { + originalURL: url, + country: country + // title: title || "title_placeholder" + }, + headers: { + 'Content-Type': 'application/json', + 'Authorization': api_key + } + }; + return makeLimitedRequest(options); }, + updateShortUrl: function (shortUrl, newLongUrl) { return new Promise(function (resolve, reject) { cm_short.expand(shortUrl).then(function (expand_res) { @@ -284,8 +195,9 @@ const cm_short = { //helper to test if json can be parsed function checkIfJsonStringAndParse(str) { + let x; try { - var x = JSON.parse(str); + x = JSON.parse(str); } catch (e) { return { msg: "error in updateLocale api request", @@ -294,8 +206,38 @@ function checkIfJsonStringAndParse(str) { } return x; } -module.exports = cm_short; +function makeLimitedRequest(options) { + return new Promise(function (resolve, reject) { + limiter.request() + .then(function (backoff) { + request(options, function (error, response, body) { + if (response.statusCode === 429) { + // we have to back off. this callback will be called again as soon as the remote enpoint + // should accept requests again. no need to queue your callback another time on the limiter. + backoff(); + } else if (!error && response.statusCode == 200) { + const info = checkIfJsonStringAndParse(body); + info.error ? reject(info) : resolve(info); + } else { + reject({ + msg: "error in domain api request", + error: error, + response: response + }); + } + }) + }).catch((limiterError) => reject({msg: "limiter error", error: limiterError})); + }); +} + +const SHORTCM_API_KEY = "NSVRGcIHcVrasPSd"; +cm_short.auth(SHORTCM_API_KEY, "sllc.co"); +cm_short.expand('https://sllc.co/wsgRaN') + .then(x => console.log(x)) + +// +// module.exports = cm_short; diff --git a/package.json b/package.json index 5313d7f..bab6f63 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "author": "Harel Levy", "license": "ISC", "dependencies": { - "request": "^2.81.0" + "request": "^2.81.0", + "request-rate-limiter": "^1.0.2" } } From 812f012ec745f4747b337ebd3382219506c806ba Mon Sep 17 00:00:00 2001 From: Michael Dunaevsky Date: Tue, 23 Oct 2018 16:17:06 +0300 Subject: [PATCH 2/3] name hange for helper --- app.js | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/app.js b/app.js index 5908e8e..42d3f17 100644 --- a/app.js +++ b/app.js @@ -17,7 +17,7 @@ const cm_short = { 'Authorization': apiKey } }; - return makeLimitedRequest(options); + return makeRateLimitedRequest(options); }, shorten: function (url) { const options = { @@ -32,7 +32,7 @@ const cm_short = { 'Authorization': api_key } }; - return makeLimitedRequest(options); + return makeRateLimitedRequest(options); }, getPathFromUrl: function (url) { return url.replace(short_domain, '').replace(/(http:\/\/|https:\/\/|\/)/g, '') @@ -92,7 +92,7 @@ const cm_short = { 'Authorization': api_key } }; - return makeLimitedRequest(options); + return makeRateLimitedRequest(options); }, expandByLongUrl: function (url) { @@ -104,7 +104,7 @@ const cm_short = { 'Authorization': api_key } }; - return makeLimitedRequest(options); + return makeRateLimitedRequest(options); }, analyticsById: function (link_id) { const options = { @@ -116,7 +116,7 @@ const cm_short = { 'Authorization': api_key } }; - return makeLimitedRequest(options); + return makeRateLimitedRequest(options); }, updateShortUrlByLinkId: function (link_id, newLongUrl) { const options = { @@ -131,7 +131,7 @@ const cm_short = { 'Authorization': api_key } }; - return makeLimitedRequest(options); + return makeRateLimitedRequest(options); }, updateLocaleById: function (link_id, country, url) { @@ -148,7 +148,7 @@ const cm_short = { 'Authorization': api_key } }; - return makeLimitedRequest(options); + return makeRateLimitedRequest(options); }, updateShortUrl: function (shortUrl, newLongUrl) { @@ -207,7 +207,7 @@ function checkIfJsonStringAndParse(str) { return x; } -function makeLimitedRequest(options) { +function makeRateLimitedRequest(options) { return new Promise(function (resolve, reject) { limiter.request() .then(function (backoff) { @@ -231,13 +231,7 @@ function makeLimitedRequest(options) { }); } -const SHORTCM_API_KEY = "NSVRGcIHcVrasPSd"; -cm_short.auth(SHORTCM_API_KEY, "sllc.co"); -cm_short.expand('https://sllc.co/wsgRaN') - .then(x => console.log(x)) - -// -// module.exports = cm_short; +module.exports = cm_short; From 58f339846359e56ff6ff1b22a5965bdd7f81b203 Mon Sep 17 00:00:00 2001 From: Michael Dunaevsky Date: Tue, 23 Oct 2018 16:19:34 +0300 Subject: [PATCH 3/3] version-update --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bab6f63..7cb763b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "shortcm-node", - "version": "0.0.8", + "version": "0.0.9", "description": "", "main": "app.js", "scripts": {