mirror of
https://github.com/usebruno/bruno.git
synced 2026-07-08 14:35:03 +00:00
fix: system proxy resolver updates (#6273)
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
const fs = require('node:fs');
|
||||
const path = require('path');
|
||||
const { get } = require('lodash');
|
||||
const { getCACertificates } = require('@usebruno/requests');
|
||||
const { getCACertificates, getSystemProxy } = require('@usebruno/requests');
|
||||
const { preferencesUtil } = require('../../store/preferences');
|
||||
const { getBrunoConfig } = require('../../store/bruno-config');
|
||||
const { interpolateString } = require('./interpolate-string');
|
||||
@@ -144,6 +144,8 @@ const getCertsAndProxyConfig = async ({
|
||||
} else if (!globalDisabled && globalInherit) {
|
||||
// Use system proxy
|
||||
proxyMode = 'system';
|
||||
const systemProxyConfig = await getSystemProxy();
|
||||
proxyConfig = systemProxyConfig;
|
||||
}
|
||||
// else: global proxy is disabled, proxyMode stays 'off'
|
||||
}
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
const { ipcMain, nativeTheme } = require('electron');
|
||||
const { getPreferences, savePreferences, preferencesUtil } = require('../store/preferences');
|
||||
const { getPreferences, savePreferences } = require('../store/preferences');
|
||||
const { globalEnvironmentsStore } = require('../store/global-environments');
|
||||
const { getSystemProxy } = require('@usebruno/requests');
|
||||
|
||||
const registerPreferencesIpc = (mainWindow, watcher) => {
|
||||
const registerPreferencesIpc = (mainWindow) => {
|
||||
ipcMain.handle('renderer:ready', async (event) => {
|
||||
// load preferences
|
||||
const preferences = getPreferences();
|
||||
mainWindow.webContents.send('main:load-preferences', preferences);
|
||||
|
||||
// load system proxy vars
|
||||
const systemProxyVars = preferencesUtil.getSystemProxyEnvVariables();
|
||||
const { http_proxy, https_proxy, no_proxy } = systemProxyVars || {};
|
||||
mainWindow.webContents.send('main:load-system-proxy-env', { http_proxy, https_proxy, no_proxy });
|
||||
|
||||
try {
|
||||
// load global environments
|
||||
const globalEnvironments = globalEnvironmentsStore.getGlobalEnvironments();
|
||||
@@ -42,6 +38,11 @@ const registerPreferencesIpc = (mainWindow, watcher) => {
|
||||
ipcMain.on('renderer:theme-change', (event, theme) => {
|
||||
nativeTheme.themeSource = theme;
|
||||
});
|
||||
|
||||
ipcMain.handle('renderer:get-system-proxy-variables', async () => {
|
||||
const systemProxyConfig = await getSystemProxy();
|
||||
return systemProxyConfig;
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = registerPreferencesIpc;
|
||||
|
||||
@@ -124,9 +124,27 @@ class PreferencesStore {
|
||||
getPreferences() {
|
||||
let preferences = this.store.get('preferences', {});
|
||||
|
||||
// Migrate proxy configuration from old formats to new format
|
||||
const proxyMigrated = get(preferences, '_migrations.proxyConfigFormat', false);
|
||||
if (!proxyMigrated && preferences?.proxy) {
|
||||
// Handle existing users without proxy settings
|
||||
// They should get disabled proxy by default, not inherit from system
|
||||
// New users (empty preferences) will get defaultPreferences.proxy via merge
|
||||
if (Object.keys(preferences).length > 0 && !preferences.proxy) {
|
||||
preferences.proxy = {
|
||||
inherit: false,
|
||||
disabled: true,
|
||||
config: {
|
||||
protocol: 'http',
|
||||
hostname: '',
|
||||
port: null,
|
||||
auth: {
|
||||
username: '',
|
||||
password: ''
|
||||
},
|
||||
bypassProxy: ''
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (preferences?.proxy) {
|
||||
const proxy = preferences.proxy || {};
|
||||
|
||||
// Check if this is an old format that needs migration
|
||||
@@ -181,15 +199,6 @@ class PreferencesStore {
|
||||
}
|
||||
|
||||
preferences.proxy = newProxy;
|
||||
|
||||
// Mark migration as complete // ?
|
||||
// if (!preferences._migrations) {
|
||||
// preferences._migrations = {};
|
||||
// }
|
||||
// preferences._migrations.proxyConfigFormat = true;
|
||||
|
||||
// Save the migrated preferences back to the store
|
||||
// this.store.set('preferences', preferences);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +269,7 @@ const preferencesUtil = {
|
||||
return get(getPreferences(), 'request.timeout', 0);
|
||||
},
|
||||
getGlobalProxyConfig: () => {
|
||||
return get(getPreferences(), 'proxy', {});
|
||||
return get(getPreferences(), 'proxy', defaultPreferences.proxy);
|
||||
},
|
||||
shouldStoreCookies: () => {
|
||||
return get(getPreferences(), 'request.storeCookies', true);
|
||||
@@ -274,14 +283,6 @@ const preferencesUtil = {
|
||||
getResponsePaneOrientation: () => {
|
||||
return get(getPreferences(), 'layout.responsePaneOrientation', 'horizontal');
|
||||
},
|
||||
getSystemProxyEnvVariables: () => {
|
||||
const { http_proxy, HTTP_PROXY, https_proxy, HTTPS_PROXY, no_proxy, NO_PROXY } = process.env;
|
||||
return {
|
||||
http_proxy: http_proxy || HTTP_PROXY,
|
||||
https_proxy: https_proxy || HTTPS_PROXY,
|
||||
no_proxy: no_proxy || NO_PROXY
|
||||
};
|
||||
},
|
||||
isBetaFeatureEnabled: (featureName) => {
|
||||
return get(getPreferences(), `beta.${featureName}`, false);
|
||||
},
|
||||
|
||||
@@ -4,7 +4,6 @@ const { HttpsProxyAgent } = require('https-proxy-agent');
|
||||
const { interpolateString } = require('../ipc/network/interpolate-string');
|
||||
const { SocksProxyAgent } = require('socks-proxy-agent');
|
||||
const { HttpProxyAgent } = require('http-proxy-agent');
|
||||
const { preferencesUtil } = require('../store/preferences');
|
||||
const { isEmpty, get, isUndefined, isNull } = require('lodash');
|
||||
|
||||
const DEFAULT_PORTS = {
|
||||
@@ -84,6 +83,29 @@ class PatchedHttpsProxyAgent extends HttpsProxyAgent {
|
||||
}
|
||||
}
|
||||
|
||||
function createTimelineHttpAgentClass(BaseAgentClass) {
|
||||
return class extends BaseAgentClass {
|
||||
constructor(options, timeline) {
|
||||
// For proxy agents, the first argument is the proxy URI and the second is options
|
||||
const { proxy: proxyUri, httpProxyAgentOptions } = options || {};
|
||||
|
||||
if (!proxyUri) {
|
||||
throw new Error('TimelineHttpProxyAgent requires options.proxy to be set');
|
||||
}
|
||||
|
||||
super(proxyUri, httpProxyAgentOptions);
|
||||
|
||||
this.timeline = Array.isArray(timeline) ? timeline : [];
|
||||
// Log the proxy details
|
||||
this.timeline.push({
|
||||
timestamp: new Date(),
|
||||
type: 'info',
|
||||
message: `Using proxy: ${proxyUri}`
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function createTimelineAgentClass(BaseAgentClass) {
|
||||
return class extends BaseAgentClass {
|
||||
constructor(options, timeline) {
|
||||
@@ -312,6 +334,10 @@ function setupProxyAgents({
|
||||
rejectUnauthorized: httpsAgentRequestFields.rejectUnauthorized !== undefined ? httpsAgentRequestFields.rejectUnauthorized : true
|
||||
};
|
||||
|
||||
const httpProxyAgentOptions = {
|
||||
keepAlive: true
|
||||
};
|
||||
|
||||
if (proxyMode === 'on') {
|
||||
const shouldProxy = shouldUseProxy(requestConfig.url, get(proxyConfig, 'bypassProxy', ''));
|
||||
if (shouldProxy) {
|
||||
@@ -337,8 +363,9 @@ function setupProxyAgents({
|
||||
requestConfig.httpAgent = new TimelineSocksProxyAgent({ proxy: proxyUri }, timeline);
|
||||
requestConfig.httpsAgent = new TimelineSocksProxyAgent({ proxy: proxyUri, ...tlsOptions }, timeline);
|
||||
} else {
|
||||
const TimelineHttpProxyAgent = createTimelineHttpAgentClass(HttpProxyAgent);
|
||||
const TimelineHttpsProxyAgent = createTimelineAgentClass(PatchedHttpsProxyAgent);
|
||||
requestConfig.httpAgent = new HttpProxyAgent(proxyUri); // For http, no need for timeline
|
||||
requestConfig.httpAgent = new TimelineHttpProxyAgent({ proxy: proxyUri, httpProxyAgentOptions }, timeline);
|
||||
requestConfig.httpsAgent = new TimelineHttpsProxyAgent(
|
||||
{ proxy: proxyUri, ...tlsOptions },
|
||||
timeline
|
||||
@@ -350,19 +377,22 @@ function setupProxyAgents({
|
||||
requestConfig.httpsAgent = new TimelineHttpsAgent(tlsOptions, timeline);
|
||||
}
|
||||
} else if (proxyMode === 'system') {
|
||||
const { http_proxy, https_proxy, no_proxy } = preferencesUtil.getSystemProxyEnvVariables();
|
||||
const { http_proxy, https_proxy, no_proxy } = proxyConfig || {};
|
||||
const shouldUseSystemProxy = shouldUseProxy(requestConfig.url, no_proxy || '');
|
||||
const parsedUrl = parseUrl(requestConfig.url);
|
||||
const isHttpsRequest = parsedUrl.protocol === 'https:';
|
||||
if (shouldUseSystemProxy) {
|
||||
try {
|
||||
if (http_proxy?.length) {
|
||||
if (http_proxy?.length && !isHttpsRequest) {
|
||||
new URL(http_proxy);
|
||||
requestConfig.httpAgent = new HttpProxyAgent(http_proxy);
|
||||
const TimelineHttpProxyAgent = createTimelineHttpAgentClass(HttpProxyAgent);
|
||||
requestConfig.httpAgent = new TimelineHttpProxyAgent({ proxy: http_proxy, httpProxyAgentOptions }, timeline);
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error('Invalid system http_proxy');
|
||||
throw new Error(`Invalid system http_proxy "${http_proxy}": ${error.message}`);
|
||||
}
|
||||
try {
|
||||
if (https_proxy?.length) {
|
||||
if (https_proxy?.length && isHttpsRequest) {
|
||||
new URL(https_proxy);
|
||||
const TimelineHttpsProxyAgent = createTimelineAgentClass(PatchedHttpsProxyAgent);
|
||||
requestConfig.httpsAgent = new TimelineHttpsProxyAgent(
|
||||
@@ -374,7 +404,7 @@ function setupProxyAgents({
|
||||
requestConfig.httpsAgent = new TimelineHttpsAgent(tlsOptions, timeline);
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error('Invalid system https_proxy');
|
||||
throw new Error(`Invalid system https_proxy "${https_proxy}": ${error.message}`);
|
||||
}
|
||||
} else {
|
||||
const TimelineHttpsAgent = createTimelineAgentClass(https.Agent);
|
||||
|
||||
Reference in New Issue
Block a user