From a1f939e3a0f7c0e2a056c18e658efecc0092951f Mon Sep 17 00:00:00 2001 From: azivner Date: Mon, 17 Dec 2018 21:34:02 +0100 Subject: [PATCH] refactoring of network code into separate service --- src/services/request.js | 86 +++++++++++++++++++++++++++++++++++++++++ src/services/sync.js | 80 ++++---------------------------------- 2 files changed, 93 insertions(+), 73 deletions(-) create mode 100644 src/services/request.js diff --git a/src/services/request.js b/src/services/request.js new file mode 100644 index 000000000..19e4fd21d --- /dev/null +++ b/src/services/request.js @@ -0,0 +1,86 @@ +"use strict"; + +const utils = require('./utils'); +const url = require('url'); + +// this service provides abstraction over node's HTTP/HTTPS and electron net.client APIs +// this allows to support system proxy + +// TODO: add proxy support - see https://stackoverflow.com/questions/3862813/how-can-i-use-an-http-proxy-with-node-js-http-client + +function exec(opts) { + const client = getClient(opts); + const parsedUrl = url.parse(opts.url); + + return new Promise(async (resolve, reject) => { + try { + const request = client.request({ + method: opts.method, + // url is used by electron net module + url: opts.url, + // 4 fields below are used by http and https node modules + protocol: parsedUrl.protocol, + host: parsedUrl.hostname, + port: parsedUrl.port, + path: parsedUrl.path, + timeout: opts.timeout, + headers: { + Cookie: (opts.cookieJar && opts.cookieJar.header) || "", + 'Content-Type': 'application/json' + } + }); + + request.on('response', response => { + if (opts.cookieJar && response.headers['set-cookie']) { + opts.cookieJar.header = response.headers['set-cookie']; + } + + let responseStr = ''; + + response.on('data', chunk => responseStr += chunk); + + response.on('end', () => { + try { + const jsonObj = responseStr.trim() ? JSON.parse(responseStr) : null; + + resolve(jsonObj); + } + catch (e) { + log.error("Failed to deserialize sync response: " + responseStr); + + reject(generateError(e)); + } + }); + }); + + request.end(opts.body ? JSON.stringify(opts.body) : undefined); + } + catch (e) { + reject(generateError(e)); + } + }) +} + +function getClient(opts) { + if (utils.isElectron()) { + return require('electron').net; + } + else { + const {protocol} = url.parse(opts.url); + + if (protocol === 'http:' || protocol === 'https:') { + return require(protocol.substr(0, protocol.length - 1)); + } + else { + throw new Error(`Unrecognized protocol "${protocol}"`); + } + } +} + +function generateError(e) { + return new Error(`Request to ${method} ${syncServerHost}${requestPath} failed, error: ${e.message}`); +} + +module.exports = { + exec +}; \ No newline at end of file diff --git a/src/services/sync.js b/src/services/sync.js index ecf3e0fbb..5ef1fb0e3 100644 --- a/src/services/sync.js +++ b/src/services/sync.js @@ -14,6 +14,7 @@ const appInfo = require('./app_info'); const syncOptions = require('./sync_options'); const syncMutexService = require('./sync_mutex'); const cls = require('./cls'); +const request = require('./request'); let proxyToggle = true; @@ -216,80 +217,13 @@ async function checkContentHash(syncContext) { await contentHashService.checkContentHashes(resp.hashes); } -async function getClient() { - if (utils.isElectron()) { - return require('electron').net; - } - else { - const {protocol} = url.parse(await syncOptions.getSyncServerHost()); - - if (protocol === 'http:' || protocol === 'https:') { - return require(protocol.substr(0, protocol.length - 1)); - } - else { - throw new Error(`Unrecognized protocol "${protocol}"`); - } - } -} - async function syncRequest(syncContext, method, requestPath, body) { - const client = await getClient(); - const syncServerHost = await syncOptions.getSyncServerHost(); - - function generateError(e) { - return new Error(`Request to ${method} ${syncServerHost}${requestPath} failed, error: ${e.message}`); - } - - const parsedUrl = url.parse(syncServerHost); - - // TODO: add proxy support - see https://stackoverflow.com/questions/3862813/how-can-i-use-an-http-proxy-with-node-js-http-client - - return new Promise(async (resolve, reject) => { - try { - const request = client.request({ - method, - // url is used by electron net module - url: syncServerHost + requestPath, - // 4 fields below are used by http and https node modules - protocol: parsedUrl.protocol, - host: parsedUrl.hostname, - port: parsedUrl.port, - path: requestPath, - timeout: await syncOptions.getSyncTimeout(), - headers: { - Cookie: syncContext.cookieJar.header || "", - 'Content-Type': 'application/json' - } - }); - - request.on('response', response => { - if (response.headers['set-cookie']) { - syncContext.cookieJar.header = response.headers['set-cookie']; - } - - let responseStr = ''; - - response.on('data', chunk => responseStr += chunk); - - response.on('end', () => { - try { - const jsonObj = responseStr.trim() ? JSON.parse(responseStr) : null; - - resolve(jsonObj); - } - catch (e) { - log.error("Failed to deserialize sync response: " + responseStr); - - reject(generateError(e)); - } - }); - }); - - request.end(JSON.stringify(body)); - } - catch (e) { - reject(generateError(e)); - } + return await request.exec({ + method, + url: await syncOptions.getSyncServerHost() + requestPath, + cookieJar: syncContext.cookieJar, + timeout: await syncOptions.getSyncTimeout(), + body }); }