From c5c343c543db520e53e02f4da24919c1f96eea69 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Fri, 30 Aug 2024 15:22:06 +0530 Subject: [PATCH] feat: update proxy implementation in preferences (#2977) --- .../CollectionSettings/ProxySettings/index.js | 400 +++++++++--------- .../ProxySettings/StyledWrapper.js | 6 + .../Preferences/ProxySettings/index.js | 37 +- .../bruno-cli/src/utils/axios-instance.js | 4 +- .../bruno-electron/src/ipc/network/index.js | 31 +- .../bruno-electron/src/store/preferences.js | 22 +- 6 files changed, 250 insertions(+), 250 deletions(-) diff --git a/packages/bruno-app/src/components/CollectionSettings/ProxySettings/index.js b/packages/bruno-app/src/components/CollectionSettings/ProxySettings/index.js index 54be8669a..105a92642 100644 --- a/packages/bruno-app/src/components/CollectionSettings/ProxySettings/index.js +++ b/packages/bruno-app/src/components/CollectionSettings/ProxySettings/index.js @@ -6,28 +6,14 @@ import * as Yup from 'yup'; import toast from 'react-hot-toast'; import { IconEye, IconEyeOff } from '@tabler/icons'; import { useState } from 'react'; -import { useMemo } from 'react'; -import { cloneDeep } from 'lodash'; - -const ProxySettings = ({ proxyConfig: _proxyConfig, onUpdate }) => { - const proxyConfig = useMemo(() => { - const proxyConfigCopy = cloneDeep(_proxyConfig); - // backward compatibility check - if (proxyConfigCopy?.enabled == 'true') proxyConfigCopy.enabled = true; - if (proxyConfigCopy?.enabled == 'false') proxyConfigCopy.enabled = false; - - proxyConfigCopy.enabled = ['string', 'boolean'].includes(typeof proxyConfigCopy?.enabled) - ? proxyConfigCopy?.enabled - : 'global'; - return proxyConfigCopy; - }, [_proxyConfig]); +const ProxySettings = ({ proxyConfig, onUpdate }) => { const proxySchema = Yup.object({ - enabled: Yup.mixed().oneOf([false, true, 'global']), + enabled: Yup.string().oneOf(['global', 'true', 'false']), protocol: Yup.string().oneOf(['http', 'https', 'socks4', 'socks5']), hostname: Yup.string() .when('enabled', { - is: true, + is: 'true', then: (hostname) => hostname.required('Specify the hostname for your proxy.'), otherwise: (hostname) => hostname.nullable() }) @@ -40,7 +26,7 @@ const ProxySettings = ({ proxyConfig: _proxyConfig, onUpdate }) => { .transform((_, val) => (val ? Number(val) : null)), auth: Yup.object() .when('enabled', { - is: true, + is: 'true', then: Yup.object({ enabled: Yup.boolean(), username: Yup.string() @@ -63,7 +49,7 @@ const ProxySettings = ({ proxyConfig: _proxyConfig, onUpdate }) => { const formik = useFormik({ initialValues: { - enabled: proxyConfig.enabled, + enabled: proxyConfig.enabled || 'global', protocol: proxyConfig.protocol || 'http', hostname: proxyConfig.hostname || '', port: proxyConfig.port || '', @@ -79,6 +65,13 @@ const ProxySettings = ({ proxyConfig: _proxyConfig, onUpdate }) => { proxySchema .validate(values, { abortEarly: true }) .then((validatedProxy) => { + // serialize 'enabled' to boolean + if (validatedProxy.enabled === 'true') { + validatedProxy.enabled = true; + } else if (validatedProxy.enabled === 'false') { + validatedProxy.enabled = false; + } + onUpdate(validatedProxy); }) .catch((error) => { @@ -91,7 +84,7 @@ const ProxySettings = ({ proxyConfig: _proxyConfig, onUpdate }) => { useEffect(() => { formik.setValues({ - enabled: proxyConfig.enabled, + enabled: proxyConfig.enabled === true ? 'true' : proxyConfig.enabled === false ? 'false' : 'global', protocol: proxyConfig.protocol || 'http', hostname: proxyConfig.hostname || '', port: proxyConfig.port || '', @@ -125,229 +118,214 @@ const ProxySettings = ({ proxyConfig: _proxyConfig, onUpdate }) => { />
-
- {formik.values.enabled === 'global' ? ( -
Global proxy can be configured in the app preferences.
- ) : null} - {formik.values.enabled === true ? ( - <> -
- -
- - - - -
-
-
- +
+ +
+ + + + +
+
+
+ + + {formik.touched.hostname && formik.errors.hostname ? ( +
{formik.errors.hostname}
+ ) : null} +
+
+ + + {formik.touched.port && formik.errors.port ? ( +
{formik.errors.port}
+ ) : null} +
+
+ + +
+
+
+ + + {formik.touched.auth?.username && formik.errors.auth?.username ? ( +
{formik.errors.auth.username}
+ ) : null} +
+
+ +
+ - {formik.touched.hostname && formik.errors.hostname ? ( -
{formik.errors.hostname}
- ) : null} -
-
- - - {formik.touched.port && formik.errors.port ? ( -
{formik.errors.port}
- ) : null} -
-
- - +
-
-
- - - {formik.touched.auth?.username && formik.errors.auth?.username ? ( -
{formik.errors.auth.username}
- ) : null} -
-
- -
- - -
- {formik.touched.auth?.password && formik.errors.auth?.password ? ( -
{formik.errors.auth.password}
- ) : null} -
-
-
- - - {formik.touched.bypassProxy && formik.errors.bypassProxy ? ( -
{formik.errors.bypassProxy}
- ) : null} -
- - ) : null} + {formik.touched.auth?.password && formik.errors.auth?.password ? ( +
{formik.errors.auth.password}
+ ) : null} +
+
+
+ + + {formik.touched.bypassProxy && formik.errors.bypassProxy ? ( +
{formik.errors.bypassProxy}
+ ) : null} +
{formik?.values?.mode === 'system' ? ( -
-
-
+
+ + Below values are sourced from your system environment variables and cannot be directly updated in Bruno.
+ Please refer to your OS documentation to change these values. +
+
+
{http_proxy || '-'}
-
+
{https_proxy || '-'}
-
+
diff --git a/packages/bruno-cli/src/utils/axios-instance.js b/packages/bruno-cli/src/utils/axios-instance.js index dd38174be..225156484 100644 --- a/packages/bruno-cli/src/utils/axios-instance.js +++ b/packages/bruno-cli/src/utils/axios-instance.js @@ -8,9 +8,7 @@ const axios = require('axios'); */ function makeAxiosInstance() { /** @type {axios.AxiosInstance} */ - const instance = axios.create({ - proxy: false - }); + const instance = axios.create(); instance.interceptors.request.use((config) => { config.headers['request-start-time'] = Date.now(); diff --git a/packages/bruno-electron/src/ipc/network/index.js b/packages/bruno-electron/src/ipc/network/index.js index 1f17e64ea..185fbc59f 100644 --- a/packages/bruno-electron/src/ipc/network/index.js +++ b/packages/bruno-electron/src/ipc/network/index.js @@ -165,17 +165,32 @@ const configureRequest = async ( } } - // proxy configuration - let proxyConfig = get(brunoConfig, 'proxy', {}); - let proxyMode = get(proxyConfig, 'enabled', 'global'); - if (proxyMode === 'global') { + /** + * Proxy configuration + * + * Preferences proxyMode has three possible values: on, off, system + * Collection proxyMode has three possible values: true, false, global + * + * When collection proxyMode is true, it overrides the app-level proxy settings + * When collection proxyMode is false, it ignores the app-level proxy settings + * When collection proxyMode is global, it uses the app-level proxy settings + * + * Below logic calculates the proxyMode and proxyConfig to be used for the request + */ + let proxyMode = 'off'; + let proxyConfig = {}; + + const collectionProxyConfig = get(brunoConfig, 'proxy', {}); + const collectionProxyEnabled = get(collectionProxyConfig, 'enabled', 'global'); + if (collectionProxyEnabled === true) { + proxyConfig = collectionProxyConfig; + proxyMode = 'on'; + } else if (collectionProxyEnabled === 'global') { proxyConfig = preferencesUtil.getGlobalProxyConfig(); - proxyMode = get(proxyConfig, 'mode', false); + proxyMode = get(proxyConfig, 'mode', 'off'); } - // proxyMode is true, if the collection-level proxy is enabled. - // proxyMode is 'on', if the app-level proxy mode is turned on. - if (proxyMode === true || proxyMode === 'on') { + if (proxyMode === 'on') { const shouldProxy = shouldUseProxy(request.url, get(proxyConfig, 'bypassProxy', '')); if (shouldProxy) { const proxyProtocol = interpolateString(get(proxyConfig, 'protocol'), interpolationOptions); diff --git a/packages/bruno-electron/src/store/preferences.js b/packages/bruno-electron/src/store/preferences.js index 58a3d10f6..33d7a02f8 100644 --- a/packages/bruno-electron/src/store/preferences.js +++ b/packages/bruno-electron/src/store/preferences.js @@ -1,6 +1,6 @@ const Yup = require('yup'); const Store = require('electron-store'); -const { get } = require('lodash'); +const { get, merge } = require('lodash'); /** * The preferences are stored in the electron store 'preferences.json'. @@ -81,10 +81,22 @@ class PreferencesStore { } getPreferences() { - return { - ...defaultPreferences, - ...this.store.get('preferences') - }; + let preferences = this.store.get('preferences', {}); + + // This to support the old preferences format + // In the old format, we had a proxy.enabled flag + // In the new format, this maps to proxy.mode = 'on' + if (preferences?.proxy?.enabled) { + preferences.proxy.mode = 'on'; + } + + // Delete the proxy.enabled property if it exists, regardless of its value + // This is a part of migration to the new preferences format + if (preferences?.proxy && 'enabled' in preferences.proxy) { + delete preferences.proxy.enabled; + } + + return merge({}, defaultPreferences, preferences); } savePreferences(newPreferences) {