From 068b85667c3ad2ff3cd75cd64b05faf2b5ffab10 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 7 May 2019 11:56:32 -0230 Subject: [PATCH 1/3] Add custom fetch wrapper with abort on timeout --- package-lock.json | 6 ++++ package.json | 1 + test/helper.js | 1 + ui/app/helpers/utils/fetch.js | 25 ++++++++++++++ ui/app/helpers/utils/fetch.test.js | 54 ++++++++++++++++++++++++++++++ 5 files changed, 87 insertions(+) create mode 100644 ui/app/helpers/utils/fetch.js create mode 100644 ui/app/helpers/utils/fetch.test.js diff --git a/package-lock.json b/package-lock.json index 99aac3d53c43..5a8c63c256d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1884,6 +1884,12 @@ } } }, + "abortcontroller-polyfill": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.3.0.tgz", + "integrity": "sha512-lbWQgf+eRvku3va8poBlDBO12FigTQr9Zb7NIjXrePrhxWVKdCP2wbDl1tLDaYa18PWTom3UEWwdH13S46I+yA==", + "dev": true + }, "abstract-leveldown": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", diff --git a/package.json b/package.json index 0626b4ac8d6f..e692a15123e2 100644 --- a/package.json +++ b/package.json @@ -194,6 +194,7 @@ "@storybook/addon-info": "^3.4.2", "@storybook/addon-knobs": "^3.4.2", "@storybook/react": "^3.4.2", + "abortcontroller-polyfill": "^1.3.0", "addons-linter": "^1.3.4", "babel-core": "^6.24.1", "babel-eslint": "^8.0.0", diff --git a/test/helper.js b/test/helper.js index 51f28de17bb3..ddc2aba408ef 100644 --- a/test/helper.js +++ b/test/helper.js @@ -27,6 +27,7 @@ global.log = log // fetch global.fetch = require('isomorphic-fetch') +require('abortcontroller-polyfill/dist/polyfill-patch-fetch') // dom require('jsdom-global')() diff --git a/ui/app/helpers/utils/fetch.js b/ui/app/helpers/utils/fetch.js new file mode 100644 index 000000000000..7bb483818d2e --- /dev/null +++ b/ui/app/helpers/utils/fetch.js @@ -0,0 +1,25 @@ +/* global AbortController */ + +export default function ({ timeout = 120000 } = {}) { + return function _fetch (url, opts) { + return new Promise(async (resolve, reject) => { + const abortController = new AbortController() + const abortSignal = abortController.signal + const f = fetch(url, { + ...opts, + signal: abortSignal, + }) + + const timer = setTimeout(() => abortController.abort(), timeout) + + try { + const res = await f + clearTimeout(timer) + return resolve(res) + } catch (e) { + clearTimeout(timer) + return reject(e) + } + }) + } +} diff --git a/ui/app/helpers/utils/fetch.test.js b/ui/app/helpers/utils/fetch.test.js new file mode 100644 index 000000000000..12724525a2b7 --- /dev/null +++ b/ui/app/helpers/utils/fetch.test.js @@ -0,0 +1,54 @@ +import assert from 'assert' +import nock from 'nock' + +import http from './fetch' + +describe('custom fetch fn', () => { + it('fetches a url', async () => { + nock('https://api.infura.io') + .get('/money') + .reply(200, '{"hodl": false}') + + const fetch = http() + const response = await (await fetch('https://api.infura.io/money')).json() + assert.deepEqual(response, { + hodl: false, + }) + }) + + it('throws when the request hits a custom timeout', async () => { + nock('https://api.infura.io') + .get('/moon') + .delay(2000) + .reply(200, '{"moon": "2012-12-21T11:11:11Z"}') + + const fetch = http({ + timeout: 123, + }) + + try { + await fetch('https://api.infura.io/moon').then(r => r.json()) + assert.fail('Request should throw') + } catch (e) { + assert.ok(e) + } + }) + + it('should abort the request when the custom timeout is hit', async () => { + nock('https://api.infura.io') + .get('/moon') + .delay(2000) + .reply(200, '{"moon": "2012-12-21T11:11:11Z"}') + + const fetch = http({ + timeout: 123, + }) + + try { + await fetch('https://api.infura.io/moon').then(r => r.json()) + assert.fail('Request should be aborted') + } catch (e) { + assert.deepEqual(e.message, 'Aborted') + } + }) +}) From b8fb7071f7ca4bafbe2b8d17597922ea33e31fd1 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 7 May 2019 15:35:49 -0230 Subject: [PATCH 2/3] Use opts and cacheRefreshTime in fetch-with-cache util --- ui/app/helpers/utils/fetch-with-cache.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/app/helpers/utils/fetch-with-cache.js b/ui/app/helpers/utils/fetch-with-cache.js index 852dcb58092d..5ace081b1ad0 100644 --- a/ui/app/helpers/utils/fetch-with-cache.js +++ b/ui/app/helpers/utils/fetch-with-cache.js @@ -7,7 +7,7 @@ export default function fetchWithCache (url, opts, cacheRefreshTime = 360000) { const currentTime = Date.now() const cachedFetch = loadLocalStorageData('cachedFetch') || {} const { cachedUrl, cachedTime } = cachedFetch[url] || {} - if (cachedUrl && currentTime - cachedTime < 360000) { + if (cachedUrl && currentTime - cachedTime < cacheRefreshTime) { return cachedFetch[url] } else { cachedFetch[url] = { cachedUrl: url, cachedTime: currentTime } @@ -17,6 +17,7 @@ export default function fetchWithCache (url, opts, cacheRefreshTime = 360000) { body: null, method: 'GET', mode: 'cors', + ...opts, }) } } From b3c7cb38fa613544c069d83adc014ef9aa5a544f Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 7 May 2019 15:38:18 -0230 Subject: [PATCH 3/3] Use custom fetch wrapper with timeout for fetch-with-cache --- ui/app/helpers/utils/fetch-with-cache.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ui/app/helpers/utils/fetch-with-cache.js b/ui/app/helpers/utils/fetch-with-cache.js index 5ace081b1ad0..ac641c3c4d09 100644 --- a/ui/app/helpers/utils/fetch-with-cache.js +++ b/ui/app/helpers/utils/fetch-with-cache.js @@ -2,6 +2,11 @@ import { loadLocalStorageData, saveLocalStorageData, } from '../../../lib/local-storage-helpers' +import http from './fetch' + +const fetch = http({ + timeout: 30000, +}) export default function fetchWithCache (url, opts, cacheRefreshTime = 360000) { const currentTime = Date.now()