diff --git a/packages/bruno-electron/src/ipc/network/index.js b/packages/bruno-electron/src/ipc/network/index.js index f843729d96..2de59c3c58 100644 --- a/packages/bruno-electron/src/ipc/network/index.js +++ b/packages/bruno-electron/src/ipc/network/index.js @@ -13,7 +13,6 @@ const { ipcMain } = require('electron'); const { isUndefined, isNull, each, get, compact, cloneDeep } = require('lodash'); const { VarsRuntime, AssertRuntime, ScriptRuntime, TestRuntime } = require('@usebruno/js'); const prepareRequest = require('./prepare-request'); -const prepareCollectionRequest = require('./prepare-collection-request'); const prepareGqlIntrospectionRequest = require('./prepare-gql-introspection-request'); const { cancelTokens, saveCancelToken, deleteCancelToken } = require('../../utils/cancel-token'); const { uuid } = require('../../utils/common'); @@ -207,29 +206,33 @@ const configureRequest = async ( switch (request?.oauth2?.grantType) { case 'authorization_code': { interpolateVars(requestCopy, envVars, collectionVariables, processEnvVars); - const { credentials } = await oauth2AuthorizeWithAuthorizationCode(requestCopy, collectionUid); + const { credentials, response } = await oauth2AuthorizeWithAuthorizationCode(requestCopy, collectionUid); request.credentials = credentials; + request.authRequestResponse = response; request.headers['Authorization'] = `Bearer ${credentials.access_token}`; break; } case 'client_credentials': { interpolateVars(requestCopy, envVars, collectionVariables, processEnvVars); - const { credentials } = await oauth2AuthorizeWithClientCredentials(requestCopy, collectionUid); + const { credentials, response } = await oauth2AuthorizeWithClientCredentials(requestCopy, collectionUid); request.credentials = credentials; + request.authRequestResponse = response; request.headers['Authorization'] = `Bearer ${credentials.access_token}`; break; } case 'password': { interpolateVars(requestCopy, envVars, collectionVariables, processEnvVars); - const { credentials } = await oauth2AuthorizeWithPasswordCredentials(requestCopy, collectionUid); + const { credentials, response } = await oauth2AuthorizeWithPasswordCredentials(requestCopy, collectionUid); request.credentials = credentials; + request.authRequestResponse = response; request.headers['Authorization'] = `Bearer ${credentials.access_token}`; break; } case 'implicit': { interpolateVars(requestCopy, envVars, collectionVariables, processEnvVars); - const { credentials } = await oauth2AuthorizeWithImplicitFlow(requestCopy, collectionUid); + const { credentials, response } = await oauth2AuthorizeWithImplicitFlow(requestCopy, collectionUid); request.credentials = credentials; + request.authRequestResponse = response; request.headers['Authorization'] = `Bearer ${credentials.access_token}`; break; } @@ -637,7 +640,11 @@ const registerNetworkIpc = (mainWindow) => { const collectionRoot = get(collection, 'root', {}); const _request = collectionRoot?.request; - const request = prepareCollectionRequest(_request, collectionRoot, collectionPath); + const request = prepareRequest(_request, collectionRoot, collectionPath); + + // Script from this collection-level pseudo-request should be erased as it duplicates the collection script + delete request.script; + const envVars = getEnvVars(environment); const processEnvVars = getProcessEnvVars(collectionUid); const brunoConfig = getBrunoConfig(collectionUid); @@ -656,7 +663,7 @@ const registerNetworkIpc = (mainWindow) => { ); interpolateVars(request, envVars, collection.collectionVariables, processEnvVars); - const axiosInstance = await configureRequest( + await configureRequest( collection.uid, request, envVars, @@ -665,19 +672,13 @@ const registerNetworkIpc = (mainWindow) => { collectionPath ); - try { - response = await axiosInstance(request); - } catch (error) { - if (error?.response) { - response = error.response; - } else { - return Promise.reject(error); - } + const response = request.authRequestResponse; + // When credentials are loaded from cache, authRequestResponse has no data + if (response.data) { + const { data } = parseDataFromResponse(response); + response.data = data; } - const { data } = parseDataFromResponse(response); - response.data = data; - await runPostResponse( request, response, @@ -695,7 +696,8 @@ const registerNetworkIpc = (mainWindow) => { status: response.status, statusText: response.statusText, headers: response.headers, - data: response.data + data: response.data, + credentials: request.credentials }; } catch (error) { return Promise.reject(error); diff --git a/packages/bruno-electron/src/ipc/network/oauth2-helper.js b/packages/bruno-electron/src/ipc/network/oauth2-helper.js index f13d7bc711..6ccf3256e8 100644 --- a/packages/bruno-electron/src/ipc/network/oauth2-helper.js +++ b/packages/bruno-electron/src/ipc/network/oauth2-helper.js @@ -35,7 +35,7 @@ const oauth2AuthorizeWithAuthorizationCode = async (request, collectionUid) => { const { cachedCredentials } = getPersistedOauth2Credentials(collectionUid); if (cachedCredentials?.access_token) { console.log('Reusing Stored access token'); - return { credentials: cachedCredentials }; + return { credentials: cachedCredentials, response: {} }; } let codeVerifier = generateCodeVerifier(); @@ -66,7 +66,7 @@ const oauth2AuthorizeWithAuthorizationCode = async (request, collectionUid) => { const response = await axiosInstance(request); const credentials = JSON.parse(response.data); persistOauth2Credentials(credentials, collectionUid); - return { credentials }; + return { credentials, response }; }; const getOAuth2AuthorizationCode = (request, codeChallenge, collectionUid) => { @@ -105,7 +105,7 @@ const oauth2AuthorizeWithClientCredentials = async (request, collectionUid) => { const { cachedCredentials } = getPersistedOauth2Credentials(collectionUid); if (cachedCredentials?.access_token) { console.log('Reusing Stored access token'); - return { credentials: cachedCredentials }; + return { credentials: cachedCredentials, response: {} }; } let requestCopy = cloneDeep(request); @@ -126,7 +126,7 @@ const oauth2AuthorizeWithClientCredentials = async (request, collectionUid) => { let response = await axiosInstance(request); let credentials = JSON.parse(response.data); persistOauth2Credentials(credentials, collectionUid); - return { credentials }; + return { credentials, response }; }; // PASSWORD CREDENTIALS @@ -135,7 +135,7 @@ const oauth2AuthorizeWithPasswordCredentials = async (request, collectionUid) => const { cachedCredentials } = getPersistedOauth2Credentials(collectionUid); if (cachedCredentials?.access_token) { console.log('Reusing Stored access token'); - return { credentials: cachedCredentials }; + return { credentials: cachedCredentials, response: {} }; } const oAuth = get(request, 'oauth2', {}); @@ -157,7 +157,7 @@ const oauth2AuthorizeWithPasswordCredentials = async (request, collectionUid) => let response = await axiosInstance(request); let credentials = JSON.parse(response.data); persistOauth2Credentials(credentials, collectionUid); - return { credentials }; + return { credentials, response }; }; // IMPLICIT @@ -166,7 +166,7 @@ const oauth2AuthorizeWithImplicitFlow = async (request, collectionUid) => { const { cachedCredentials } = getPersistedOauth2Credentials(collectionUid); if (cachedCredentials?.access_token) { console.log('Reusing Stored access token'); - return { credentials: cachedCredentials }; + return { credentials: cachedCredentials, response: {} }; } return new Promise(async (resolve, reject) => { @@ -186,7 +186,7 @@ const oauth2AuthorizeWithImplicitFlow = async (request, collectionUid) => { authorizeUrl: authorizationUrlWithQueryParams, session: oauth2Store.getSessionIdOfCollection(collectionUid) }); - resolve({ credentials }); + resolve({ credentials, response: {} }); persistOauth2Credentials(credentials, collectionUid); } catch (err) { reject(err); diff --git a/packages/bruno-electron/src/ipc/network/prepare-collection-request.js b/packages/bruno-electron/src/ipc/network/prepare-collection-request.js deleted file mode 100644 index 5fd6305948..0000000000 --- a/packages/bruno-electron/src/ipc/network/prepare-collection-request.js +++ /dev/null @@ -1,49 +0,0 @@ -const { get, each } = require('lodash'); -const { setAuthHeaders } = require('./prepare-request'); - -const prepareCollectionRequest = (request, collectionRoot) => { - const headers = {}; - let contentTypeDefined = false; - let url = request.url; - - // collection headers - each(get(collectionRoot, 'request.headers', []), (h) => { - if (h.enabled) { - headers[h.name] = h.value; - if (h.name.toLowerCase() === 'content-type') { - contentTypeDefined = true; - } - } - }); - - each(request.headers, (h) => { - if (h.enabled) { - headers[h.name] = h.value; - if (h.name.toLowerCase() === 'content-type') { - contentTypeDefined = true; - } - } - }); - - let axiosRequest = { - mode: request?.body?.mode, - method: request.method, - url, - headers, - responseType: 'arraybuffer' - }; - - axiosRequest = setAuthHeaders(axiosRequest, request, collectionRoot); - - if (request.script) { - axiosRequest.script = request.script; - } - - axiosRequest.vars = request.vars; - - axiosRequest.method = 'POST'; - - return axiosRequest; -}; - -module.exports = prepareCollectionRequest; diff --git a/packages/bruno-electron/src/ipc/network/prepare-request.js b/packages/bruno-electron/src/ipc/network/prepare-request.js index 3d6ae5f8d0..e7aec273bd 100644 --- a/packages/bruno-electron/src/ipc/network/prepare-request.js +++ b/packages/bruno-electron/src/ipc/network/prepare-request.js @@ -166,7 +166,7 @@ const prepareRequest = (request, collectionRoot, collectionPath) => { }); let axiosRequest = { - mode: request.body.mode, + mode: request?.body?.mode, method: request.method, url, headers, @@ -175,7 +175,7 @@ const prepareRequest = (request, collectionRoot, collectionPath) => { axiosRequest = setAuthHeaders(axiosRequest, request, collectionRoot); - if (request.body.mode === 'json') { + if (request.body?.mode === 'json') { if (!contentTypeDefined) { axiosRequest.headers['content-type'] = 'application/json'; } @@ -186,28 +186,28 @@ const prepareRequest = (request, collectionRoot, collectionPath) => { } } - if (request.body.mode === 'text') { + if (request.body?.mode === 'text') { if (!contentTypeDefined) { axiosRequest.headers['content-type'] = 'text/plain'; } axiosRequest.data = request.body.text; } - if (request.body.mode === 'xml') { + if (request.body?.mode === 'xml') { if (!contentTypeDefined) { axiosRequest.headers['content-type'] = 'text/xml'; } axiosRequest.data = request.body.xml; } - if (request.body.mode === 'sparql') { + if (request.body?.mode === 'sparql') { if (!contentTypeDefined) { axiosRequest.headers['content-type'] = 'application/sparql-query'; } axiosRequest.data = request.body.sparql; } - if (request.body.mode === 'formUrlEncoded') { + 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); @@ -215,14 +215,14 @@ const prepareRequest = (request, collectionRoot, collectionPath) => { axiosRequest.data = params; } - if (request.body.mode === 'multipartForm') { + if (request.body?.mode === 'multipartForm') { const enabledParams = filter(request.body.multipartForm, (p) => p.enabled); const form = parseFormData(enabledParams, collectionPath); extend(axiosRequest.headers, form.getHeaders()); axiosRequest.data = form; } - if (request.body.mode === 'graphql') { + if (request.body?.mode === 'graphql') { const graphqlQuery = { query: get(request, 'body.graphql.query'), // https://github.com/usebruno/bruno/issues/884 - we must only parse the variables after the variable interpolation