mirror of
https://github.com/usebruno/bruno.git
synced 2025-06-25 14:31:44 +02:00
feat: moved prepare request logic to electron
This commit is contained in:
parent
1ec24d1138
commit
3d63db806d
@ -6,7 +6,8 @@ import {
|
|||||||
collectionChangeFileEvent,
|
collectionChangeFileEvent,
|
||||||
collectionUnlinkFileEvent,
|
collectionUnlinkFileEvent,
|
||||||
collectionUnlinkDirectoryEvent,
|
collectionUnlinkDirectoryEvent,
|
||||||
collectionUnlinkEnvFileEvent
|
collectionUnlinkEnvFileEvent,
|
||||||
|
requestSentEvent
|
||||||
} from 'providers/ReduxStore/slices/collections';
|
} from 'providers/ReduxStore/slices/collections';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import { openCollectionEvent, collectionAddEnvFileEvent } from 'providers/ReduxStore/slices/collections/actions';
|
import { openCollectionEvent, collectionAddEnvFileEvent } from 'providers/ReduxStore/slices/collections/actions';
|
||||||
@ -80,18 +81,24 @@ const useCollectionTreeSync = () => {
|
|||||||
toast.error(message || 'Something went wrong!');
|
toast.error(message || 'Something went wrong!');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const _httpRequestSent = (val) => {
|
||||||
|
dispatch(requestSentEvent(val));
|
||||||
|
};
|
||||||
|
|
||||||
ipcRenderer.invoke('renderer:ready');
|
ipcRenderer.invoke('renderer:ready');
|
||||||
|
|
||||||
const removeListener1 = ipcRenderer.on('main:collection-opened', _openCollection);
|
const removeListener1 = ipcRenderer.on('main:collection-opened', _openCollection);
|
||||||
const removeListener2 = ipcRenderer.on('main:collection-tree-updated', _collectionTreeUpdated);
|
const removeListener2 = ipcRenderer.on('main:collection-tree-updated', _collectionTreeUpdated);
|
||||||
const removeListener3 = ipcRenderer.on('main:collection-already-opened', _collectionAlreadyOpened);
|
const removeListener3 = ipcRenderer.on('main:collection-already-opened', _collectionAlreadyOpened);
|
||||||
const removeListener4 = ipcRenderer.on('main:display-error', _displayError);
|
const removeListener4 = ipcRenderer.on('main:display-error', _displayError);
|
||||||
|
const removeListener5 = ipcRenderer.on('main:http-request-sent', _httpRequestSent);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
removeListener1();
|
removeListener1();
|
||||||
removeListener2();
|
removeListener2();
|
||||||
removeListener3();
|
removeListener3();
|
||||||
removeListener4();
|
removeListener4();
|
||||||
|
removeListener5();
|
||||||
};
|
};
|
||||||
}, [isElectron]);
|
}, [isElectron]);
|
||||||
};
|
};
|
||||||
|
@ -25,7 +25,6 @@ import { saveCollectionToIdb } from 'utils/idb';
|
|||||||
import { sendNetworkRequest, cancelNetworkRequest } from 'utils/network';
|
import { sendNetworkRequest, cancelNetworkRequest } from 'utils/network';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
requestSent,
|
|
||||||
requestCancelled,
|
requestCancelled,
|
||||||
responseReceived,
|
responseReceived,
|
||||||
newItem as _newItem,
|
newItem as _newItem,
|
||||||
@ -100,24 +99,12 @@ export const saveRequest = (itemUid, collectionUid) => (dispatch, getState) => {
|
|||||||
export const sendRequest = (item, collectionUid) => (dispatch, getState) => {
|
export const sendRequest = (item, collectionUid) => (dispatch, getState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const collection = findCollectionByUid(state.collections.collections, collectionUid);
|
const collection = findCollectionByUid(state.collections.collections, collectionUid);
|
||||||
const cancelTokenUid = uuid();
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!collection) {
|
if (!collection) {
|
||||||
return reject(new Error('Collection not found'));
|
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 itemCopy = cloneDeep(item);
|
||||||
const collectionCopy = cloneDeep(collection);
|
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) => {
|
.then((response) => {
|
||||||
return dispatch(
|
return dispatch(
|
||||||
responseReceived({
|
responseReceived({
|
||||||
|
@ -147,7 +147,7 @@ export const collectionsSlice = createSlice({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
requestSent: (state, action) => {
|
requestSentEvent: (state, action) => {
|
||||||
const { itemUid, collectionUid, cancelTokenUid, requestSent } = action.payload;
|
const { itemUid, collectionUid, cancelTokenUid, requestSent } = action.payload;
|
||||||
const collection = findCollectionByUid(state.collections, collectionUid);
|
const collection = findCollectionByUid(state.collections, collectionUid);
|
||||||
|
|
||||||
@ -795,7 +795,7 @@ export const {
|
|||||||
deleteItem,
|
deleteItem,
|
||||||
renameItem,
|
renameItem,
|
||||||
cloneItem,
|
cloneItem,
|
||||||
requestSent,
|
requestSentEvent,
|
||||||
requestCancelled,
|
requestCancelled,
|
||||||
responseReceived,
|
responseReceived,
|
||||||
saveRequest,
|
saveRequest,
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
import get from 'lodash/get';
|
export const sendNetworkRequest = async (item, collectionUid) => {
|
||||||
import each from 'lodash/each';
|
|
||||||
import filter from 'lodash/filter';
|
|
||||||
import qs from 'qs';
|
|
||||||
|
|
||||||
export const sendNetworkRequest = async (item, options, onRequestSent) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (['http-request', 'graphql-request'].includes(item.type)) {
|
if (['http-request', 'graphql-request'].includes(item.type)) {
|
||||||
const timeStart = Date.now();
|
const timeStart = Date.now();
|
||||||
sendHttpRequest(item.draft ? item.draft.request : item.request, options, onRequestSent)
|
sendHttpRequest(item, collectionUid)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
const timeEnd = Date.now();
|
const timeEnd = Date.now();
|
||||||
resolve({
|
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) => {
|
return new Promise((resolve, reject) => {
|
||||||
const { ipcRenderer } = window;
|
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
|
ipcRenderer
|
||||||
.invoke('send-http-request', axiosRequest, options)
|
.invoke('send-http-request', item, collectionUid)
|
||||||
.then(resolve)
|
.then(resolve)
|
||||||
.catch(reject);
|
.catch(reject);
|
||||||
});
|
});
|
||||||
|
@ -3,12 +3,19 @@ const FormData = require('form-data');
|
|||||||
const { ipcMain } = require('electron');
|
const { ipcMain } = require('electron');
|
||||||
const { forOwn, extend } = require('lodash');
|
const { forOwn, extend } = require('lodash');
|
||||||
const { ScriptRuntime } = require('@usebruno/js');
|
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
|
// 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 {
|
try {
|
||||||
|
const _request = item.draft ? item.draft.request : item.request;
|
||||||
|
const request = prepareRequest(_request);
|
||||||
|
|
||||||
// make axios work in node using form data
|
// make axios work in node using form data
|
||||||
// reference: https://github.com/axios/axios/issues/1006#issuecomment-320165427
|
// reference: https://github.com/axios/axios/issues/1006#issuecomment-320165427
|
||||||
if(request.headers && request.headers['content-type'] === 'multipart/form-data') {
|
if(request.headers && request.headers['content-type'] === 'multipart/form-data') {
|
||||||
@ -20,11 +27,9 @@ const registerNetworkIpc = () => {
|
|||||||
request.data = form;
|
request.data = form;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(options && options.cancelTokenUid) {
|
const cancelToken = axios.CancelToken.source();
|
||||||
const cancelToken = axios.CancelToken.source();
|
request.cancelToken = cancelToken.token;
|
||||||
request.cancelToken = cancelToken.token;
|
saveCancelToken(cancelTokenUid, cancelToken);
|
||||||
saveCancelToken(options.cancelTokenUid, cancelToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(request.script && request.script.length) {
|
if(request.script && request.script.length) {
|
||||||
request.script = request.script += '\n onRequest(brunoRequest);';
|
request.script = request.script += '\n onRequest(brunoRequest);';
|
||||||
@ -32,11 +37,21 @@ const registerNetworkIpc = () => {
|
|||||||
scriptRuntime.run(request.script, request);
|
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);
|
const result = await axios(request);
|
||||||
|
|
||||||
if(options && options.cancelTokenUid) {
|
deleteCancelToken(cancelTokenUid);
|
||||||
deleteCancelToken(options.cancelTokenUid);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: result.status,
|
status: result.status,
|
||||||
@ -45,9 +60,7 @@ const registerNetworkIpc = () => {
|
|||||||
data: result.data
|
data: result.data
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if(options && options.cancelTokenUid) {
|
deleteCancelToken(cancelTokenUid);
|
||||||
deleteCancelToken(options.cancelTokenUid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(error.response) {
|
if(error.response) {
|
||||||
return {
|
return {
|
69
packages/bruno-electron/src/ipc/network/prepare-request.js
Normal file
69
packages/bruno-electron/src/ipc/network/prepare-request.js
Normal 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;
|
Loading…
x
Reference in New Issue
Block a user