Skip to content

Commit c23eb0b

Browse files
committed
fix: system proxy detection updates
1 parent bc82536 commit c23eb0b

File tree

24 files changed

+2101
-104
lines changed

24 files changed

+2101
-104
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { useEffect } from 'react';
2+
import { useDispatch, useSelector } from 'react-redux';
3+
import { getSystemProxyVariables } from 'providers/ReduxStore/slices/app';
4+
5+
const SystemProxy = () => {
6+
const dispatch = useDispatch();
7+
const systemProxyVariables = useSelector((state) => state.app.systemProxyVariables);
8+
const { source, http_proxy, https_proxy, no_proxy } = systemProxyVariables || {};
9+
10+
useEffect(() => {
11+
dispatch(getSystemProxyVariables());
12+
}, [dispatch]);
13+
14+
return (
15+
<>
16+
<div className="mb-3 text-muted system-proxy-settings space-y-4">
17+
<div className="flex items-start justify-start flex-col gap-2 mt-2">
18+
<div className="flex flex-row items-center gap-2">
19+
<div>
20+
<h2 className="text-xs text-gray-900 dark:text-gray-100">
21+
System Proxy
22+
</h2>
23+
<small className="text-gray-500 dark:text-gray-400">
24+
Below values are sourced from your system proxy settings.
25+
</small>
26+
</div>
27+
</div>
28+
</div>
29+
{source && (
30+
<div className="mb-2">
31+
<small className="font-medium flex flex-row gap-2">
32+
<div className="opacity-70 text-xs">
33+
Proxy source:
34+
</div>
35+
<div>
36+
{source === 'environment' ? 'Environment Variables'
37+
: source === 'windows-system' ? 'Windows System Settings'
38+
: source === 'macos-system' ? 'macOS System Settings'
39+
: source === 'linux-system' ? 'Linux System Settings' : source}
40+
</div>
41+
</small>
42+
</div>
43+
)}
44+
<small>
45+
These values cannot be directly updated in Bruno. Please refer to your OS documentation to update these.
46+
</small>
47+
<div className="flex flex-col justify-start items-start pt-2">
48+
<div className="mb-1 flex items-center">
49+
<label className="settings-label">
50+
http_proxy
51+
</label>
52+
<div className="opacity-80 text-indigo-600 dark:text-indigo-400">{http_proxy || '-'}</div>
53+
</div>
54+
<div className="mb-1 flex items-center">
55+
<label className="settings-label">
56+
https_proxy
57+
</label>
58+
<div className="opacity-80 text-indigo-600 dark:text-indigo-400">{https_proxy || '-'}</div>
59+
</div>
60+
<div className="mb-1 flex items-center">
61+
<label className="settings-label">
62+
no_proxy
63+
</label>
64+
<div className="opacity-80 text-indigo-600 dark:text-indigo-400">{no_proxy || '-'}</div>
65+
</div>
66+
</div>
67+
</div>
68+
</>
69+
);
70+
};
71+
72+
export default SystemProxy;

packages/bruno-app/src/components/Preferences/ProxySettings/index.js

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@ import StyledWrapper from './StyledWrapper';
88
import { useDispatch, useSelector } from 'react-redux';
99
import { IconEye, IconEyeOff } from '@tabler/icons';
1010
import { useState } from 'react';
11+
import SystemProxy from './SystemProxy/index';
1112

1213
const ProxySettings = ({ close }) => {
1314
const preferences = useSelector((state) => state.app.preferences);
14-
const systemProxyEnvVariables = useSelector((state) => state.app.systemProxyEnvVariables);
15-
const { http_proxy, https_proxy, no_proxy } = systemProxyEnvVariables || {};
1615
const dispatch = useDispatch();
17-
console.log(preferences);
1816

1917
const proxySchema = Yup.object({
2018
mode: Yup.string().oneOf(['off', 'on', 'system']),
@@ -162,30 +160,7 @@ const ProxySettings = ({ close }) => {
162160
</div>
163161
{formik?.values?.mode === 'system' ? (
164162
<div className="mb-3 pt-1 text-muted system-proxy-settings">
165-
<small>
166-
Below values are sourced from your system environment variables and cannot be directly updated in Bruno.<br/>
167-
Please refer to your OS documentation to change these values.
168-
</small>
169-
<div className="flex flex-col justify-start items-start pt-2">
170-
<div className="mb-1 flex items-center">
171-
<label className="settings-label" htmlFor="http_proxy">
172-
http_proxy
173-
</label>
174-
<div className="opacity-80">{http_proxy || '-'}</div>
175-
</div>
176-
<div className="mb-1 flex items-center">
177-
<label className="settings-label" htmlFor="https_proxy">
178-
https_proxy
179-
</label>
180-
<div className="opacity-80">{https_proxy || '-'}</div>
181-
</div>
182-
<div className="mb-1 flex items-center">
183-
<label className="settings-label" htmlFor="no_proxy">
184-
no_proxy
185-
</label>
186-
<div className="opacity-80">{no_proxy || '-'}</div>
187-
</div>
188-
</div>
163+
<SystemProxy />
189164
</div>
190165
) : null}
191166
{formik?.values?.mode === 'on' ? (

packages/bruno-app/src/components/ResponsePane/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ const ResponsePane = ({ item, collection }) => {
159159
<div className={getTabClassname('response')} role="tab" onClick={() => selectTab('response')}>
160160
Response
161161
</div>
162-
<div className={getTabClassname('headers')} role="tab" onClick={() => selectTab('headers')}>
162+
<div className={getTabClassname('headers')} role="tab" onClick={() => selectTab('headers')} data-testid="response-headers-tab">
163163
Headers
164164
{responseHeadersCount > 0 && <sup className="ml-1 font-medium">{responseHeadersCount}</sup>}
165165
</div>

packages/bruno-app/src/providers/App/useIpcEvents.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ import { useEffect } from 'react';
22
import {
33
showPreferences,
44
updateCookies,
5-
updatePreferences,
6-
updateSystemProxyEnvVariables
5+
updatePreferences
76
} from 'providers/ReduxStore/slices/app';
87
import {
98
brunoConfigUpdateEvent,
@@ -164,10 +163,6 @@ const useIpcEvents = () => {
164163
dispatch(updatePreferences(val));
165164
});
166165

167-
const removeSystemProxyEnvUpdatesListener = ipcRenderer.on('main:load-system-proxy-env', (val) => {
168-
dispatch(updateSystemProxyEnvVariables(val));
169-
});
170-
171166
const removeCookieUpdateListener = ipcRenderer.on('main:cookies-update', (val) => {
172167
dispatch(updateCookies(val));
173168
});
@@ -218,7 +213,6 @@ const useIpcEvents = () => {
218213
removeShowPreferencesListener();
219214
removePreferencesUpdatesListener();
220215
removeCookieUpdateListener();
221-
removeSystemProxyEnvUpdatesListener();
222216
removeGlobalEnvironmentsUpdatesListener();
223217
removeSnapshotHydrationListener();
224218
removeCollectionOauth2CredentialsUpdatesListener();

packages/bruno-app/src/providers/ReduxStore/slices/app.js

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ const initialState = {
4141
},
4242
cookies: [],
4343
taskQueue: [],
44-
systemProxyEnvVariables: {},
4544
clipboard: {
4645
hasCopiedItems: false // Whether clipboard has Bruno data (for UI)
47-
}
46+
},
47+
systemProxyVariables: {}
4848
};
4949

5050
export const appSlice = createSlice({
@@ -90,8 +90,8 @@ export const appSlice = createSlice({
9090
removeAllTasksFromQueue: (state) => {
9191
state.taskQueue = [];
9292
},
93-
updateSystemProxyEnvVariables: (state, action) => {
94-
state.systemProxyEnvVariables = action.payload;
93+
updateSystemProxyVariables: (state, action) => {
94+
state.systemProxyVariables = action.payload;
9595
},
9696
updateGenerateCode: (state, action) => {
9797
state.generateCode = {
@@ -123,7 +123,7 @@ export const {
123123
insertTaskIntoQueue,
124124
removeTaskFromQueue,
125125
removeAllTasksFromQueue,
126-
updateSystemProxyEnvVariables,
126+
updateSystemProxyVariables,
127127
updateGenerateCode,
128128
toggleSidebarCollapse,
129129
setClipboard
@@ -198,4 +198,15 @@ export const copyRequest = (item) => (dispatch, getState) => {
198198
return Promise.resolve();
199199
};
200200

201+
export const getSystemProxyVariables = () => (dispatch, getState) => {
202+
return new Promise((resolve, reject) => {
203+
const { ipcRenderer } = window;
204+
ipcRenderer.invoke('renderer:get-system-proxy-variables')
205+
.then((variables) => {
206+
dispatch(updateSystemProxyVariables(variables));
207+
})
208+
.then(resolve).catch(reject);
209+
});
210+
};
211+
201212
export default appSlice.reducer;

packages/bruno-cli/src/runner/run-single-request.js

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const qs = require('qs');
22
const chalk = require('chalk');
3+
const parseUrl = require('url').parse;
34
const decomment = require('decomment');
45
const fs = require('fs');
56
const { forOwn, isUndefined, isNull, each, extend, get, compact } = require('lodash');
@@ -15,7 +16,8 @@ const { HttpProxyAgent } = require('http-proxy-agent');
1516
const { SocksProxyAgent } = require('socks-proxy-agent');
1617
const { makeAxiosInstance } = require('../utils/axios-instance');
1718
const { addAwsV4Interceptor, resolveAwsV4Credentials } = require('./awsv4auth-helper');
18-
const { shouldUseProxy, PatchedHttpsProxyAgent, getSystemProxyEnvVariables } = require('../utils/proxy-util');
19+
const { shouldUseProxy, PatchedHttpsProxyAgent } = require('../utils/proxy-util');
20+
const { getSystemProxy } = require('@usebruno/requests');
1921
const path = require('path');
2022
const { parseDataFromResponse } = require('../utils/common');
2123
const { getCookieStringForUrl, saveCookies } = require('../utils/cookies');
@@ -301,7 +303,8 @@ const runSingleRequest = async function (
301303
proxyMode = 'on';
302304
} else if (collectionProxyEnabled === 'global') {
303305
// If collection proxy is set to 'global', use system proxy
304-
const { http_proxy, https_proxy } = getSystemProxyEnvVariables();
306+
const systemProxy = await getSystemProxy();
307+
const { http_proxy, https_proxy } = systemProxy;
305308
if (http_proxy?.length || https_proxy?.length) {
306309
proxyMode = 'system';
307310
}
@@ -346,33 +349,40 @@ const runSingleRequest = async function (
346349
});
347350
}
348351
} else if (proxyMode === 'system') {
349-
const { http_proxy, https_proxy, no_proxy } = getSystemProxyEnvVariables();
350-
const shouldUseSystemProxy = shouldUseProxy(request.url, no_proxy || '');
351-
if (shouldUseSystemProxy) {
352-
try {
353-
if (http_proxy?.length) {
354-
new URL(http_proxy);
355-
request.httpAgent = new HttpProxyAgent(http_proxy);
352+
try {
353+
const systemProxy = await getSystemProxy();
354+
const { http_proxy, https_proxy, no_proxy } = systemProxy;
355+
const shouldUseSystemProxy = shouldUseProxy(request.url, no_proxy || '');
356+
const parsedUrl = parseUrl(request.url);
357+
const isHttpsRequest = parsedUrl.protocol === 'https:';
358+
if (shouldUseSystemProxy) {
359+
try {
360+
if (http_proxy?.length && !isHttpsRequest) {
361+
new URL(http_proxy);
362+
request.httpAgent = new HttpProxyAgent(http_proxy);
363+
}
364+
} catch (error) {
365+
throw new Error('Invalid system http_proxy');
356366
}
357-
} catch (error) {
358-
throw new Error('Invalid system http_proxy');
359-
}
360-
try {
361-
if (https_proxy?.length) {
362-
new URL(https_proxy);
363-
request.httpsAgent = new PatchedHttpsProxyAgent(
364-
https_proxy,
365-
Object.keys(httpsAgentRequestFields).length > 0 ? { ...httpsAgentRequestFields } : undefined
366-
);
367-
} else {
368-
request.httpsAgent = new https.Agent({
369-
...httpsAgentRequestFields
367+
try {
368+
if (https_proxy?.length && isHttpsRequest) {
369+
new URL(https_proxy);
370+
request.httpsAgent = new PatchedHttpsProxyAgent(https_proxy,
371+
Object.keys(httpsAgentRequestFields).length > 0 ? { ...httpsAgentRequestFields } : undefined);
372+
} else {
373+
request.httpsAgent = new https.Agent({
374+
...httpsAgentRequestFields
370375
});
371376
}
372-
} catch (error) {
373-
throw new Error('Invalid system https_proxy');
377+
} catch (error) {
378+
throw new Error('Invalid system https_proxy');
379+
}
380+
} else {
381+
request.httpsAgent = new https.Agent({
382+
...httpsAgentRequestFields
383+
});
374384
}
375-
} else {
385+
} catch (error) {
376386
request.httpsAgent = new https.Agent({
377387
...httpsAgentRequestFields
378388
});

packages/bruno-cli/src/utils/proxy-util.js

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -79,18 +79,7 @@ class PatchedHttpsProxyAgent extends HttpsProxyAgent {
7979
}
8080
}
8181

82-
83-
const getSystemProxyEnvVariables = () => {
84-
const { http_proxy, HTTP_PROXY, https_proxy, HTTPS_PROXY, no_proxy, NO_PROXY } = process.env;
85-
return {
86-
http_proxy: http_proxy || HTTP_PROXY,
87-
https_proxy: https_proxy || HTTPS_PROXY,
88-
no_proxy: no_proxy || NO_PROXY
89-
};
90-
}
91-
9282
module.exports = {
9383
shouldUseProxy,
94-
PatchedHttpsProxyAgent,
95-
getSystemProxyEnvVariables
84+
PatchedHttpsProxyAgent
9685
};

packages/bruno-electron/src/ipc/network/cert-utils.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const fs = require('node:fs');
22
const path = require('path');
33
const { get } = require('lodash');
4-
const { getCACertificates } = require('@usebruno/requests');
4+
const { getCACertificates, getSystemProxy } = require('@usebruno/requests');
55
const { preferencesUtil } = require('../../store/preferences');
66
const { getBrunoConfig } = require('../../store/bruno-config');
77
const { interpolateString } = require('./interpolate-string');
@@ -113,6 +113,10 @@ const getCertsAndProxyConfig = async ({
113113
} else if (collectionProxyEnabled === 'global') {
114114
proxyConfig = preferencesUtil.getGlobalProxyConfig();
115115
proxyMode = get(proxyConfig, 'mode', 'off');
116+
if (proxyMode == 'system') {
117+
const systemProxyConfig = await getSystemProxy();
118+
proxyConfig = systemProxyConfig;
119+
}
116120
}
117121

118122
return { proxyMode, proxyConfig, httpsAgentRequestFields, interpolationOptions };

packages/bruno-electron/src/ipc/preferences.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,14 @@ const { getPreferences, savePreferences, preferencesUtil } = require('../store/p
33
const { isDirectory } = require('../utils/filesystem');
44
const { openCollection } = require('../app/collections');
55
const { globalEnvironmentsStore } = require('../store/global-environments');
6-
``;
6+
const { getSystemProxy } = require('@usebruno/requests');
7+
78
const registerPreferencesIpc = (mainWindow, watcher, lastOpenedCollections) => {
89
ipcMain.handle('renderer:ready', async (event) => {
910
// load preferences
1011
const preferences = getPreferences();
1112
mainWindow.webContents.send('main:load-preferences', preferences);
1213

13-
// load system proxy vars
14-
const systemProxyVars = preferencesUtil.getSystemProxyEnvVariables();
15-
const { http_proxy, https_proxy, no_proxy } = systemProxyVars || {};
16-
mainWindow.webContents.send('main:load-system-proxy-env', { http_proxy, https_proxy, no_proxy });
17-
1814
try {
1915
// load global environments
2016
const globalEnvironments = globalEnvironmentsStore.getGlobalEnvironments();
@@ -52,6 +48,11 @@ const registerPreferencesIpc = (mainWindow, watcher, lastOpenedCollections) => {
5248
return Promise.reject(error);
5349
}
5450
});
51+
52+
ipcMain.handle('renderer:get-system-proxy-variables', async () => {
53+
const systemProxyConfig = await getSystemProxy();
54+
return systemProxyConfig;
55+
});
5556
};
5657

5758
module.exports = registerPreferencesIpc;

0 commit comments

Comments
 (0)