From e6e25a65e7fc731b186d24db7e47cbf32c9d4090 Mon Sep 17 00:00:00 2001 From: Yarmo Mackenbach Date: Thu, 25 Mar 2021 15:37:30 +0100 Subject: [PATCH] Add timeout to fetcher functions --- src/fetcher/dns.js | 17 +++++++++++++++-- src/fetcher/index.js | 2 +- src/fetcher/irc.js | 17 +++++++++++++++-- src/fetcher/matrix.js | 17 +++++++++++++++-- src/fetcher/twitter.js | 17 +++++++++++++++-- src/fetcher/xmpp.js | 34 +++++++++++++++++++++------------- 6 files changed, 82 insertions(+), 22 deletions(-) diff --git a/src/fetcher/dns.js b/src/fetcher/dns.js index c6afc8b..503e142 100644 --- a/src/fetcher/dns.js +++ b/src/fetcher/dns.js @@ -16,7 +16,15 @@ limitations under the License. const dns = require('dns') module.exports = async (hostname) => { - return new Promise((resolve, reject) => { + let timeoutHandle + const timeoutPromise = new Promise((resolve, reject) => { + timeoutHandle = setTimeout( + () => reject(new Error('Request was timed out')), + 5000 + ) + }) + + const fetchPromise = new Promise((resolve, reject) => { dns.resolveTxt(hostname, (err, records) => { if (err) { reject(err) @@ -31,4 +39,9 @@ module.exports = async (hostname) => { }) }) }) -} \ No newline at end of file + + return Promise.race([fetchPromise, timeoutPromise]).then((result) => { + clearTimeout(timeoutHandle) + return result + }) +} diff --git a/src/fetcher/index.js b/src/fetcher/index.js index 9761ac7..cb49a95 100644 --- a/src/fetcher/index.js +++ b/src/fetcher/index.js @@ -17,4 +17,4 @@ exports.dns = require('./dns') exports.irc = require('./irc') exports.matrix = require('./matrix') exports.twitter = require('./twitter') -exports.xmpp = require('./xmpp') \ No newline at end of file +exports.xmpp = require('./xmpp') diff --git a/src/fetcher/irc.js b/src/fetcher/irc.js index a3ef0e9..793f1da 100644 --- a/src/fetcher/irc.js +++ b/src/fetcher/irc.js @@ -16,7 +16,15 @@ limitations under the License. const irc = require('irc-upd') module.exports = async (nickQuery, opts) => { - return new Promise((resolve, reject) => { + let timeoutHandle + const timeoutPromise = new Promise((resolve, reject) => { + timeoutHandle = setTimeout( + () => reject(new Error('Request was timed out')), + 5000 + ) + }) + + const fetchPromise = new Promise((resolve, reject) => { try { const client = new irc.Client(opts.hostname, opts.nick, { port: 6697, @@ -44,4 +52,9 @@ module.exports = async (nickQuery, opts) => { reject(error) } }) -} \ No newline at end of file + + return Promise.race([fetchPromise, timeoutPromise]).then((result) => { + clearTimeout(timeoutHandle) + return result + }) +} diff --git a/src/fetcher/matrix.js b/src/fetcher/matrix.js index 25caf7d..141e0c2 100644 --- a/src/fetcher/matrix.js +++ b/src/fetcher/matrix.js @@ -17,9 +17,17 @@ const bent = require('bent') const bentReq = bent('GET') module.exports = async (roomId, eventId, opts) => { + let timeoutHandle + const timeoutPromise = new Promise((resolve, reject) => { + timeoutHandle = setTimeout( + () => reject(new Error('Request was timed out')), + 5000 + ) + }) + const url = `https://${opts.instance}/_matrix/client/r0/rooms/${roomId}/event/${eventId}?access_token=${opts.accessToken}` - return bentReq(url, null, { + const fetchPromise = bentReq(url, null, { Accept: 'application/json', }) .then(async (data) => { @@ -31,4 +39,9 @@ module.exports = async (roomId, eventId, opts) => { .catch((error) => { return error }) -} \ No newline at end of file + + return Promise.race([fetchPromise, timeoutPromise]).then((result) => { + clearTimeout(timeoutHandle) + return result + }) +} diff --git a/src/fetcher/twitter.js b/src/fetcher/twitter.js index 448474b..169c6a2 100644 --- a/src/fetcher/twitter.js +++ b/src/fetcher/twitter.js @@ -17,7 +17,15 @@ const bent = require('bent') const bentReq = bent('GET') module.exports = async (tweetId, opts) => { - return bentReq( + let timeoutHandle + const timeoutPromise = new Promise((resolve, reject) => { + timeoutHandle = setTimeout( + () => reject(new Error('Request was timed out')), + 5000 + ) + }) + + const fetchPromise = bentReq( `https://api.twitter.com/1.1/statuses/show.json?id=${tweetId}&tweet_mode=extended`, null, { @@ -34,4 +42,9 @@ module.exports = async (tweetId, opts) => { .catch((error) => { return error }) -} \ No newline at end of file + + return Promise.race([fetchPromise, timeoutPromise]).then((result) => { + clearTimeout(timeoutHandle) + return result + }) +} diff --git a/src/fetcher/xmpp.js b/src/fetcher/xmpp.js index 4eb92b2..4ad6aef 100644 --- a/src/fetcher/xmpp.js +++ b/src/fetcher/xmpp.js @@ -43,7 +43,15 @@ const xmppStart = async (service, username, password) => { } module.exports = async (id, data, opts) => { - return new Promise(async (resolve, reject) => { + let timeoutHandle + const timeoutPromise = new Promise((resolve, reject) => { + timeoutHandle = setTimeout( + () => reject(new Error('Request was timed out')), + 5000 + ) + }) + + const fetchPromise = new Promise(async (resolve, reject) => { if (!xmpp) { const xmppStartRes = await xmppStart( opts.service, @@ -55,20 +63,16 @@ module.exports = async (id, data, opts) => { } const response = await iqCaller.request( - xml( - 'iq', - { type: 'get', to: id }, - xml('vCard', 'vcard-temp') - ), + xml('iq', { type: 'get', to: id }, xml('vCard', 'vcard-temp')), 30 * 1000 ) - + const vcardRow = response.getChild('vCard', 'vcard-temp').toString() const dom = new jsdom.JSDOM(vcardRow) - + try { let vcard - + switch (data.toLowerCase()) { case 'desc': case 'note': @@ -82,10 +86,9 @@ module.exports = async (id, data, opts) => { throw new Error('No DESC or NOTE field found in vCard') } break - + default: - vcard = dom.window.document.querySelector(data) - .textContent + vcard = dom.window.document.querySelector(data).textContent break } xmpp.stop() @@ -94,4 +97,9 @@ module.exports = async (id, data, opts) => { reject(error) } }) -} \ No newline at end of file + + return Promise.race([fetchPromise, timeoutPromise]).then((result) => { + clearTimeout(timeoutHandle) + return result + }) +}