feat: moved prepare request logic to electron

This commit is contained in:
Anoop M D 2023-01-24 19:34:06 +05:30
parent 1ec24d1138
commit 3d63db806d
6 changed files with 111 additions and 104 deletions

View File

@ -6,7 +6,8 @@ import {
collectionChangeFileEvent,
collectionUnlinkFileEvent,
collectionUnlinkDirectoryEvent,
collectionUnlinkEnvFileEvent
collectionUnlinkEnvFileEvent,
requestSentEvent
} from 'providers/ReduxStore/slices/collections';
import toast from 'react-hot-toast';
import { openCollectionEvent, collectionAddEnvFileEvent } from 'providers/ReduxStore/slices/collections/actions';
@ -80,18 +81,24 @@ const useCollectionTreeSync = () => {
toast.error(message || 'Something went wrong!');
};
const _httpRequestSent = (val) => {
dispatch(requestSentEvent(val));
};
ipcRenderer.invoke('renderer:ready');
const removeListener1 = ipcRenderer.on('main:collection-opened', _openCollection);
const removeListener2 = ipcRenderer.on('main:collection-tree-updated', _collectionTreeUpdated);
const removeListener3 = ipcRenderer.on('main:collection-already-opened', _collectionAlreadyOpened);
const removeListener4 = ipcRenderer.on('main:display-error', _displayError);
const removeListener5 = ipcRenderer.on('main:http-request-sent', _httpRequestSent);
return () => {
removeListener1();
removeListener2();
removeListener3();
removeListener4();
removeListener5();
};
}, [isElectron]);
};

View File

@ -25,7 +25,6 @@ import { saveCollectionToIdb } from 'utils/idb';
import { sendNetworkRequest, cancelNetworkRequest } from 'utils/network';
import {
requestSent,
requestCancelled,
responseReceived,
newItem as _newItem,
@ -100,24 +99,12 @@ export const saveRequest = (itemUid, collectionUid) => (dispatch, getState) => {
export const sendRequest = (item, collectionUid) => (dispatch, getState) => {
const state = getState();
const collection = findCollectionByUid(state.collections.collections, collectionUid);
const cancelTokenUid = uuid();
return new Promise((resolve, reject) => {
if (!collection) {
return reject(new Error('Collection not found'));
}
const onRequestSent = (req) => {
dispatch(
requestSent({
requestSent: req,
itemUid: item.uid,
collectionUid: collectionUid,
cancelTokenUid: cancelTokenUid
})
);
};
const itemCopy = cloneDeep(item);
const collectionCopy = cloneDeep(collection);
@ -128,7 +115,7 @@ export const sendRequest = (item, collectionUid) => (dispatch, getState) => {
}
}
sendNetworkRequest(itemCopy, { cancelTokenUid: cancelTokenUid }, onRequestSent)
sendNetworkRequest(itemCopy, collectionUid)
.then((response) => {
return dispatch(
responseReceived({

View File

@ -147,7 +147,7 @@ export const collectionsSlice = createSlice({
}
}
},
requestSent: (state, action) => {
requestSentEvent: (state, action) => {
const { itemUid, collectionUid, cancelTokenUid, requestSent } = action.payload;
const collection = findCollectionByUid(state.collections, collectionUid);
@ -795,7 +795,7 @@ export const {
deleteItem,
renameItem,
cloneItem,
requestSent,
requestSentEvent,
requestCancelled,
responseReceived,
saveRequest,

View File

@ -1,13 +1,8 @@
import get from 'lodash/get';
import each from 'lodash/each';
import filter from 'lodash/filter';
import qs from 'qs';
export const sendNetworkRequest = async (item, options, onRequestSent) => {
export const sendNetworkRequest = async (item, collectionUid) => {
return new Promise((resolve, reject) => {
if (['http-request', 'graphql-request'].includes(item.type)) {
const timeStart = Date.now();
sendHttpRequest(item.draft ? item.draft.request : item.request, options, onRequestSent)
sendHttpRequest(item, collectionUid)
.then((response) => {
const timeEnd = Date.now();
resolve({
@ -25,76 +20,12 @@ export const sendNetworkRequest = async (item, options, onRequestSent) => {
});
};
const sendHttpRequest = async (request, options, onRequestSent) => {
const sendHttpRequest = async (item, collectionUid) => {
return new Promise((resolve, reject) => {
const { ipcRenderer } = window;
const headers = {};
each(request.headers, (h) => {
if (h.enabled) {
headers[h.name] = h.value;
}
});
let axiosRequest = {
method: request.method,
url: request.url,
headers: headers
};
if (request.body.mode === 'json') {
axiosRequest.headers['content-type'] = 'application/json';
try {
axiosRequest.data = JSON.parse(request.body.json);
} catch (ex) {
axiosRequest.data = request.body.json;
}
}
if (request.body.mode === 'text') {
axiosRequest.headers['content-type'] = 'text/plain';
axiosRequest.data = request.body.text;
}
if (request.body.mode === 'xml') {
axiosRequest.headers['content-type'] = 'text/xml';
axiosRequest.data = request.body.xml;
}
if (request.body.mode === 'formUrlEncoded') {
axiosRequest.headers['content-type'] = 'application/x-www-form-urlencoded';
const params = {};
const enabledParams = filter(request.body.formUrlEncoded, (p) => p.enabled);
each(enabledParams, (p) => (params[p.name] = p.value));
axiosRequest.data = qs.stringify(params);
}
if (request.body.mode === 'multipartForm') {
const params = {};
const enabledParams = filter(request.body.multipartForm, (p) => p.enabled);
each(enabledParams, (p) => (params[p.name] = p.value));
axiosRequest.headers['content-type'] = 'multipart/form-data';
axiosRequest.data = params;
}
if (request.body.mode === 'graphql') {
const graphqlQuery = {
query: get(request, 'body.graphql.query'),
variables: JSON.parse(get(request, 'body.graphql.variables') || '{}')
};
axiosRequest.headers['content-type'] = 'application/json';
axiosRequest.data = graphqlQuery;
}
if (request.script && request.script.length) {
axiosRequest.script = request.script;
}
console.log(axiosRequest);
onRequestSent(axiosRequest);
ipcRenderer
.invoke('send-http-request', axiosRequest, options)
.invoke('send-http-request', item, collectionUid)
.then(resolve)
.catch(reject);
});

View File

@ -3,12 +3,19 @@ const FormData = require('form-data');
const { ipcMain } = require('electron');
const { forOwn, extend } = require('lodash');
const { ScriptRuntime } = require('@usebruno/js');
const { cancelTokens, saveCancelToken, deleteCancelToken } = require('../utils/cancel-token');
const prepareRequest = require('./prepare-request');
const { cancelTokens, saveCancelToken, deleteCancelToken } = require('../../utils/cancel-token');
const { uuid } = require('../../utils/common');
const registerNetworkIpc = () => {
const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => {
// handler for sending http request
ipcMain.handle('send-http-request', async (event, request, options) => {
ipcMain.handle('send-http-request', async (event, item, collectionUid) => {
const cancelTokenUid = uuid();
try {
const _request = item.draft ? item.draft.request : item.request;
const request = prepareRequest(_request);
// 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') {
@ -20,11 +27,9 @@ const registerNetworkIpc = () => {
request.data = form;
}
if(options && options.cancelTokenUid) {
const cancelToken = axios.CancelToken.source();
request.cancelToken = cancelToken.token;
saveCancelToken(options.cancelTokenUid, cancelToken);
}
saveCancelToken(cancelTokenUid, cancelToken);
if(request.script && request.script.length) {
request.script = request.script += '\n onRequest(brunoRequest);';
@ -32,11 +37,21 @@ const registerNetworkIpc = () => {
scriptRuntime.run(request.script, request);
}
mainWindow.webContents.send('main:http-request-sent', {
requestSent: {
url: request.url,
method: request.method,
headers: request.headers,
data: request.data
},
collectionUid,
itemUid: item.uid,
cancelTokenUid
});
const result = await axios(request);
if(options && options.cancelTokenUid) {
deleteCancelToken(options.cancelTokenUid);
}
deleteCancelToken(cancelTokenUid);
return {
status: result.status,
@ -45,9 +60,7 @@ const registerNetworkIpc = () => {
data: result.data
};
} catch (error) {
if(options && options.cancelTokenUid) {
deleteCancelToken(options.cancelTokenUid);
}
deleteCancelToken(cancelTokenUid);
if(error.response) {
return {

View File

@ -0,0 +1,69 @@
const { get, each, filter } = require('lodash');
const qs = require('qs');
const prepareRequest = (request) => {
const headers = {};
each(request.headers, (h) => {
if (h.enabled) {
headers[h.name] = h.value;
}
});
let axiosRequest = {
method: request.method,
url: request.url,
headers: headers
};
if (request.body.mode === 'json') {
axiosRequest.headers['content-type'] = 'application/json';
try {
axiosRequest.data = JSON.parse(request.body.json);
} catch (ex) {
axiosRequest.data = request.body.json;
}
}
if (request.body.mode === 'text') {
axiosRequest.headers['content-type'] = 'text/plain';
axiosRequest.data = request.body.text;
}
if (request.body.mode === 'xml') {
axiosRequest.headers['content-type'] = 'text/xml';
axiosRequest.data = request.body.xml;
}
if (request.body.mode === 'formUrlEncoded') {
axiosRequest.headers['content-type'] = 'application/x-www-form-urlencoded';
const params = {};
const enabledParams = filter(request.body.formUrlEncoded, (p) => p.enabled);
each(enabledParams, (p) => (params[p.name] = p.value));
axiosRequest.data = qs.stringify(params);
}
if (request.body.mode === 'multipartForm') {
const params = {};
const enabledParams = filter(request.body.multipartForm, (p) => p.enabled);
each(enabledParams, (p) => (params[p.name] = p.value));
axiosRequest.headers['content-type'] = 'multipart/form-data';
axiosRequest.data = params;
}
if (request.body.mode === 'graphql') {
const graphqlQuery = {
query: get(request, 'body.graphql.query'),
variables: JSON.parse(get(request, 'body.graphql.variables') || '{}')
};
axiosRequest.headers['content-type'] = 'application/json';
axiosRequest.data = graphqlQuery;
}
if (request.script && request.script.length) {
axiosRequest.script = request.script;
}
return axiosRequest;
};
module.exports = prepareRequest;