diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js index 5bbefa54..e1964776 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js @@ -18,9 +18,8 @@ import { } from 'utils/collections'; import { collectionSchema, itemSchema } from '@usebruno/schema'; import { waitForNextTick } from 'utils/common'; -import cancelTokens, { saveCancelToken, deleteCancelToken } from 'utils/network/cancelTokens'; import { getCollectionsFromIdb, saveCollectionToIdb, deleteCollectionInIdb } from 'utils/idb'; -import { sendNetworkRequest } from 'utils/network'; +import { sendNetworkRequest, cancelNetworkRequest } from 'utils/network'; import { loadCollections, @@ -208,17 +207,15 @@ export const saveRequest = (itemUid, collectionUid) => (dispatch, getState) => { }; export const sendRequest = (item, collectionUid) => (dispatch) => { - const axiosRequest = axios.CancelToken.source(); const cancelTokenUid = uuid(); - saveCancelToken(cancelTokenUid, axiosRequest); dispatch(requestSent({ itemUid: item.uid, collectionUid: collectionUid, cancelTokenUid: cancelTokenUid })); - sendNetworkRequest(item, {cancelToken: axiosRequest.token}) + sendNetworkRequest(item, {cancelTokenUid: cancelTokenUid}) .then((response) => { if(response && response.status !== -1) { return dispatch(responseReceived({ @@ -228,18 +225,18 @@ export const sendRequest = (item, collectionUid) => (dispatch) => { })); } }) - .then(() => deleteCancelToken(cancelTokenUid)) .catch((err) => console.log(err)); }; export const cancelRequest = (cancelTokenUid, item, collection) => (dispatch) => { - if(cancelTokenUid && cancelTokens[cancelTokenUid]) { - cancelTokens[cancelTokenUid].cancel(); - dispatch(requestCancelled({ - itemUid: item.uid, - collectionUid: collection.uid - })) - } + cancelNetworkRequest(cancelTokenUid) + .then(() => { + dispatch(requestCancelled({ + itemUid: item.uid, + collectionUid: collection.uid + })) + }) + .catch((err) => console.log(err)); }; export const newFolder = (folderName, collectionUid, itemUid) => (dispatch, getState) => { diff --git a/packages/bruno-app/src/utils/network/browser.js b/packages/bruno-app/src/utils/network/browser.js index 1b96e418..98a65a2a 100644 --- a/packages/bruno-app/src/utils/network/browser.js +++ b/packages/bruno-app/src/utils/network/browser.js @@ -1,22 +1,20 @@ const axios = require('axios'); -const FormData = require('form-data'); -const { forOwn, extend } = require('lodash'); +import { saveCancelToken, deleteCancelToken } from 'utils/network/cancelTokens'; -export const sendHttpRequestInBrowser = async (request) => { +export const sendHttpRequestInBrowser = async (request, options) => { try { - // make axios work in node using form data - // reference: https://github.com/axios/axios/issues/1006#issuecomment-320165427 - if(request.headers && request.headers['content-type'] === 'multipart/form-data') { - const form = new FormData(); - forOwn(request.data, (value, key) => { - form.append(key, value); - }); - extend(request.headers, form.getHeaders()); - request.data = form; + if(options && options.cancelTokenUid) { + const cancelToken = axios.CancelToken.source(); + request.cancelToken = cancelToken.token; + saveCancelToken(options.cancelTokenUid, cancelToken); } const result = await axios(request); + if(options && options.cancelTokenUid) { + deleteCancelToken(options.cancelTokenUid); + } + return { status: result.status, headers: result.headers, diff --git a/packages/bruno-app/src/utils/network/index.js b/packages/bruno-app/src/utils/network/index.js index 92279e9f..f57bde47 100644 --- a/packages/bruno-app/src/utils/network/index.js +++ b/packages/bruno-app/src/utils/network/index.js @@ -3,8 +3,10 @@ import filter from 'lodash/filter'; import qs from 'qs'; import { rawRequest, gql } from 'graphql'; import { sendHttpRequestInBrowser } from './browser'; +import { isElectron } from 'utils/common/platform'; +import cancelTokens, { deleteCancelToken } from 'utils/network/cancelTokens'; -const sendNetworkRequest = async (item, options) => { +export const sendNetworkRequest = async (item, options) => { return new Promise((resolve, reject) => { if(item.type === 'http-request') { const timeStart = Date.now(); @@ -42,10 +44,6 @@ const sendHttpRequest = async (request, options) => { headers: headers }; - if(options && options.cancelToken) { - axiosRequest.cancelToken = options.cancelToken; - } - if(request.body.mode === 'json') { axiosRequest.headers['content-type'] = 'application/json'; try { @@ -84,15 +82,16 @@ const sendHttpRequest = async (request, options) => { console.log('>>> Sending Request'); console.log(axiosRequest); - // Todo: Choose based on platform (web/desktop) - sendHttpRequestInBrowser(axiosRequest) + if(isElectron()) { + ipcRenderer + .invoke('send-http-request', axiosRequest, options) .then(resolve) .catch(reject); - - // ipcRenderer - // .invoke('send-http', axiosRequest) - // .then(resolve) - // .catch(reject); + } else { + sendHttpRequestInBrowser(axiosRequest, options) + .then(resolve) + .catch(reject); + } }); }; @@ -109,6 +108,23 @@ const sendGraphqlRequest = async (request,) => { } }; -export { - sendNetworkRequest +export const cancelNetworkRequest = async (cancelTokenUid) => { + if(isElectron()) { + return new Promise((resolve, reject) => { + ipcRenderer + .invoke('cancel-http-request', cancelTokenUid) + .then(resolve) + .catch(reject); + }); + } + + return new Promise((resolve, reject) => { + if(cancelTokenUid && cancelTokens[cancelTokenUid]) { + cancelTokens[cancelTokenUid].cancel(); + deleteCancelToken(cancelTokenUid); + resolve(); + } else { + reject(new Error("cancel token not found")); + } + }); }; diff --git a/packages/bruno-electron/src/ipc/network.js b/packages/bruno-electron/src/ipc/network.js index 35322db3..fda58e95 100644 --- a/packages/bruno-electron/src/ipc/network.js +++ b/packages/bruno-electron/src/ipc/network.js @@ -2,10 +2,11 @@ const axios = require('axios'); const FormData = require('form-data'); const { ipcMain } = require('electron'); const { forOwn, extend } = require('lodash'); +const { cancelTokens, saveCancelToken, deleteCancelToken } = require('../utils/cancel-token'); const registerNetworkIpc = () => { // handler for sending http request - ipcMain.handle('send-http-request', async (event, request) => { + ipcMain.handle('send-http-request', async (event, request, options) => { try { // make axios work in node using form data // reference: https://github.com/axios/axios/issues/1006#issuecomment-320165427 @@ -18,8 +19,18 @@ const registerNetworkIpc = () => { request.data = form; } + if(options && options.cancelTokenUid) { + const cancelToken = axios.CancelToken.source(); + request.cancelToken = cancelToken.token; + saveCancelToken(options.cancelTokenUid, cancelToken); + } + const result = await axios(request); + if(options && options.cancelTokenUid) { + deleteCancelToken(options.cancelTokenUid); + } + return { status: result.status, headers: result.headers, @@ -41,6 +52,18 @@ const registerNetworkIpc = () => { }; } }); + + ipcMain.handle('cancel-http-request', async (event, cancelTokenUid) => { + return new Promise((resolve, reject) => { + if(cancelTokenUid && cancelTokens[cancelTokenUid]) { + cancelTokens[cancelTokenUid].cancel(); + deleteCancelToken(cancelTokenUid); + resolve(); + } else { + reject(new Error("cancel token not found")); + } + }); + }); }; module.exports = registerNetworkIpc; diff --git a/packages/bruno-electron/src/utils/cancel-token.js b/packages/bruno-electron/src/utils/cancel-token.js new file mode 100644 index 00000000..aa1a1de3 --- /dev/null +++ b/packages/bruno-electron/src/utils/cancel-token.js @@ -0,0 +1,15 @@ +const cancelTokens = {}; + +const saveCancelToken = (uid, axiosRequest) => { + cancelTokens[uid] = axiosRequest; +} + +const deleteCancelToken = (uid) => { + delete cancelTokens[uid]; +} + +module.exports = { + cancelTokens, + saveCancelToken, + deleteCancelToken +};