mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-28 07:04:10 +00:00
feat(preferences): add cache.httpHttpsAgents.enabled preference
This commit is contained in:
@@ -429,10 +429,12 @@ const runSingleRequest = async function (
|
||||
|
||||
// Prepare TLS options for agent caching
|
||||
const tlsOptions = {
|
||||
...httpsAgentRequestFields,
|
||||
keepAlive: true
|
||||
...httpsAgentRequestFields
|
||||
};
|
||||
|
||||
// HTTP agent options — separate from tlsOptions to avoid leaking TLS fields
|
||||
const httpAgentOptions = { keepAlive: true };
|
||||
|
||||
const parsedRequestUrl = new URL(request.url);
|
||||
const isHttpsRequest = parsedRequestUrl.protocol === 'https:';
|
||||
|
||||
@@ -459,13 +461,13 @@ const runSingleRequest = async function (
|
||||
if (isHttpsRequest) {
|
||||
request.httpsAgent = getOrCreateAgent(SocksProxyAgent, tlsOptions, proxyUri);
|
||||
} else {
|
||||
request.httpAgent = getOrCreateHttpAgent(SocksProxyAgent, { keepAlive: true }, proxyUri);
|
||||
request.httpAgent = getOrCreateHttpAgent(SocksProxyAgent, httpAgentOptions, proxyUri);
|
||||
}
|
||||
} else {
|
||||
if (isHttpsRequest) {
|
||||
request.httpsAgent = getOrCreateAgent(PatchedHttpsProxyAgent, tlsOptions, proxyUri);
|
||||
} else {
|
||||
request.httpAgent = getOrCreateHttpAgent(HttpProxyAgent, { keepAlive: true }, proxyUri);
|
||||
request.httpAgent = getOrCreateHttpAgent(HttpProxyAgent, httpAgentOptions, proxyUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -477,7 +479,7 @@ const runSingleRequest = async function (
|
||||
try {
|
||||
if (http_proxy?.length && !isHttpsRequest) {
|
||||
new URL(http_proxy);
|
||||
request.httpAgent = getOrCreateHttpAgent(HttpProxyAgent, { keepAlive: true }, http_proxy);
|
||||
request.httpAgent = getOrCreateHttpAgent(HttpProxyAgent, httpAgentOptions, http_proxy);
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error('Invalid system http_proxy');
|
||||
@@ -501,7 +503,7 @@ const runSingleRequest = async function (
|
||||
if (isHttpsRequest) {
|
||||
request.httpsAgent = getOrCreateAgent(https.Agent, tlsOptions, null);
|
||||
} else {
|
||||
request.httpAgent = getOrCreateHttpAgent(http.Agent, { keepAlive: true }, null);
|
||||
request.httpAgent = getOrCreateHttpAgent(http.Agent, httpAgentOptions, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -609,7 +611,7 @@ const runSingleRequest = async function (
|
||||
|
||||
let token;
|
||||
if (oauth2RequestUrl) {
|
||||
const tlsOptions = {
|
||||
const oauth2ConfigOptions = {
|
||||
noproxy: options.noproxy,
|
||||
shouldVerifyTls: !insecure,
|
||||
shouldUseCustomCaCertificate: !!options['cacert'],
|
||||
@@ -626,7 +628,7 @@ const runSingleRequest = async function (
|
||||
const { httpAgent: oauth2HttpAgent, httpsAgent: oauth2HttpsAgent } = await getHttpHttpsAgents({
|
||||
requestUrl: oauth2RequestUrl,
|
||||
collectionPath,
|
||||
options: tlsOptions,
|
||||
options: oauth2ConfigOptions,
|
||||
clientCertificates: interpolatedClientCertificates,
|
||||
collectionLevelProxy: interpolatedProxyConfig,
|
||||
systemProxyConfig
|
||||
|
||||
@@ -106,6 +106,11 @@ const defaultPreferences = {
|
||||
},
|
||||
display: {
|
||||
zoomPercentage: 100
|
||||
},
|
||||
cache: {
|
||||
httpHttpsAgents: {
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -164,7 +169,12 @@ const preferencesSchema = Yup.object().shape({
|
||||
}),
|
||||
display: Yup.object({
|
||||
zoomPercentage: Yup.number().min(50).max(150)
|
||||
})
|
||||
}),
|
||||
cache: Yup.object({
|
||||
httpHttpsAgents: Yup.object({
|
||||
enabled: Yup.boolean()
|
||||
})
|
||||
}).optional()
|
||||
});
|
||||
|
||||
class PreferencesStore {
|
||||
@@ -351,6 +361,9 @@ const preferencesUtil = {
|
||||
getZoomPercentage: () => {
|
||||
return get(getPreferences(), 'display.zoomPercentage', 100);
|
||||
},
|
||||
isHttpHttpsAgentCachingEnabled: () => {
|
||||
return get(getPreferences(), 'cache.httpHttpsAgents.enabled', true);
|
||||
},
|
||||
hasLaunchedBefore: () => {
|
||||
return get(getPreferences(), 'onboarding.hasLaunchedBefore', false);
|
||||
},
|
||||
|
||||
@@ -6,7 +6,7 @@ const { interpolateString } = require('../ipc/network/interpolate-string');
|
||||
const { SocksProxyAgent } = require('socks-proxy-agent');
|
||||
const { HttpProxyAgent } = require('http-proxy-agent');
|
||||
const { isEmpty, get, isUndefined, isNull } = require('lodash');
|
||||
const { getOrCreateAgent, getOrCreateHttpAgent, clearAgentCache, getAgentCacheSize } = require('@usebruno/requests');
|
||||
const { getOrCreateAgent, getOrCreateHttpAgent } = require('@usebruno/requests');
|
||||
|
||||
const DEFAULT_PORTS = {
|
||||
ftp: 21,
|
||||
@@ -200,9 +200,5 @@ function setupProxyAgents({
|
||||
module.exports = {
|
||||
shouldUseProxy,
|
||||
PatchedHttpsProxyAgent,
|
||||
setupProxyAgents,
|
||||
clearAgentCache,
|
||||
getAgentCacheSize,
|
||||
getOrCreateAgent,
|
||||
getOrCreateHttpAgent
|
||||
setupProxyAgents
|
||||
};
|
||||
|
||||
@@ -61,6 +61,14 @@ describe('Agent Cache', () => {
|
||||
expect(httpsAgent).not.toBe(httpAgent);
|
||||
expect(getAgentCacheSize()).toBe(2);
|
||||
});
|
||||
|
||||
it('creates separate agents for different keepAlive values', () => {
|
||||
const agent1 = getOrCreateAgent(https.Agent, { keepAlive: true });
|
||||
const agent2 = getOrCreateAgent(https.Agent, { keepAlive: false });
|
||||
|
||||
expect(agent1).not.toBe(agent2);
|
||||
expect(getAgentCacheSize()).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('timeline support', () => {
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import crypto from 'node:crypto';
|
||||
import http from 'node:http';
|
||||
import https from 'node:https';
|
||||
import type { Agent as HttpAgent } from 'node:http';
|
||||
import type { Agent as HttpsAgent } from 'node:https';
|
||||
import { createTimelineAgentClass, createTimelineHttpAgentClass, type TimelineEntry, type AgentOptions, type HttpAgentOptions, type AgentClass, type HttpAgentClass } from './timeline-agent';
|
||||
@@ -82,6 +80,7 @@ function getAgentCacheKey(agentClassId: number, options: AgentOptions, proxyUri:
|
||||
const keyData = {
|
||||
agentClassId,
|
||||
proxyUri,
|
||||
keepAlive: options.keepAlive,
|
||||
rejectUnauthorized: options.rejectUnauthorized,
|
||||
// Hash certificates and passphrase instead of including full content
|
||||
ca: hashCaValue(options.ca),
|
||||
@@ -233,7 +232,7 @@ function getOrCreateAgent(
|
||||
timeline,
|
||||
getAgentCacheKey,
|
||||
getTimelineAgentClass,
|
||||
'Reusing cached agent (SSL session reuse enabled)'
|
||||
'Reusing cached https agent'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -261,7 +260,7 @@ function getOrCreateHttpAgent(
|
||||
timeline,
|
||||
getHttpAgentCacheKey,
|
||||
getTimelineHttpAgentClass,
|
||||
'Reusing cached agent (connection reuse enabled)'
|
||||
'Reusing cached http agent'
|
||||
) as HttpAgent;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import * as fs from 'node:fs';
|
||||
import * as path from 'node:path';
|
||||
import http from 'node:http';
|
||||
import https from 'node:https';
|
||||
import type { Agent as HttpAgent } from 'node:http';
|
||||
import type { Agent as HttpsAgent } from 'node:https';
|
||||
@@ -11,6 +12,7 @@ import { isEmpty, get, isUndefined, isNull } from 'lodash';
|
||||
import { getCACertificates } from './ca-cert';
|
||||
import { transformProxyConfig } from './proxy-util';
|
||||
import { getOrCreateAgent, getOrCreateHttpAgent } from './agent-cache';
|
||||
import type { TimelineEntry } from './timeline-agent';
|
||||
|
||||
const DEFAULT_PORTS: Record<string, number> = {
|
||||
ftp: 21,
|
||||
@@ -114,12 +116,6 @@ type GetCertsAndProxyConfigResult = {
|
||||
certsConfig: CertsConfig;
|
||||
};
|
||||
|
||||
type TimelineEntry = {
|
||||
timestamp: Date;
|
||||
type: 'info' | 'tls' | 'error';
|
||||
message: string;
|
||||
};
|
||||
|
||||
type CreateAgentsParams = {
|
||||
requestUrl?: string;
|
||||
proxyMode: ProxyMode;
|
||||
@@ -368,9 +364,10 @@ function createAgents({
|
||||
let httpAgent: HttpAgent | undefined;
|
||||
let httpsAgent: HttpsAgent | HttpsProxyAgent<any> | SocksProxyAgent | undefined;
|
||||
|
||||
// Determine if this is an HTTPS request
|
||||
const isHttpsRequest = requestUrl ? requestUrl.startsWith('https:') : true;
|
||||
|
||||
if (proxyMode === 'on') {
|
||||
// Determine if this is an HTTPS request
|
||||
const isHttpsRequest = requestUrl ? requestUrl.startsWith('https:') : true;
|
||||
const shouldProxy = shouldUseProxy(requestUrl, get(proxyConfig, 'bypassProxy', ''));
|
||||
if (shouldProxy) {
|
||||
const proxyProtocol = get(proxyConfig, 'protocol');
|
||||
@@ -421,7 +418,7 @@ function createAgents({
|
||||
const shouldUseSystemProxy = shouldUseProxy(requestUrl, no_proxy || '');
|
||||
if (shouldUseSystemProxy) {
|
||||
try {
|
||||
if (http_proxy?.length) {
|
||||
if (http_proxy?.length && !isHttpsRequest) {
|
||||
new URL(http_proxy);
|
||||
httpAgent = getOrCreateHttpAgent(HttpProxyAgent, { keepAlive: true }, http_proxy, timeline || null);
|
||||
}
|
||||
@@ -429,20 +426,22 @@ function createAgents({
|
||||
throw new Error('Invalid system http_proxy');
|
||||
}
|
||||
try {
|
||||
if (https_proxy?.length) {
|
||||
if (https_proxy?.length && isHttpsRequest) {
|
||||
new URL(https_proxy);
|
||||
httpsAgent = getOrCreateAgent(PatchedHttpsProxyAgent, tlsOptions as any, https_proxy, timeline || null) as HttpsAgent;
|
||||
} else {
|
||||
httpsAgent = getOrCreateAgent(https.Agent, tlsOptions as any, null, timeline || null) as HttpsAgent;
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error('Invalid system https_proxy');
|
||||
}
|
||||
} else {
|
||||
httpsAgent = getOrCreateAgent(https.Agent, tlsOptions as any, null, timeline || null) as HttpsAgent;
|
||||
}
|
||||
} else {
|
||||
httpsAgent = getOrCreateAgent(https.Agent, tlsOptions as any, null, timeline || null) as HttpsAgent;
|
||||
}
|
||||
|
||||
if (!httpAgent && !httpsAgent) {
|
||||
if (isHttpsRequest) {
|
||||
httpsAgent = getOrCreateAgent(https.Agent, tlsOptions as any, null, timeline || null) as HttpsAgent;
|
||||
} else {
|
||||
httpAgent = getOrCreateHttpAgent(http.Agent, { keepAlive: true }, null, timeline || null);
|
||||
}
|
||||
}
|
||||
|
||||
return { httpAgent, httpsAgent };
|
||||
|
||||
Reference in New Issue
Block a user