From a55ed9bd50da2e458b47dc2aa8ddfd62efa9e7a2 Mon Sep 17 00:00:00 2001 From: lohxt1 Date: Thu, 12 Dec 2024 14:09:06 +0530 Subject: [PATCH] feat: cli -- system level proxy fix --- .../src/runner/run-single-request.js | 108 +++++++++++++----- .../bruno-cli/src/utils/axios-instance.js | 1 + packages/bruno-cli/src/utils/proxy-util.js | 13 ++- 3 files changed, 90 insertions(+), 32 deletions(-) diff --git a/packages/bruno-cli/src/runner/run-single-request.js b/packages/bruno-cli/src/runner/run-single-request.js index 35cafb590..87ba7d2ff 100644 --- a/packages/bruno-cli/src/runner/run-single-request.js +++ b/packages/bruno-cli/src/runner/run-single-request.js @@ -17,7 +17,7 @@ const { HttpProxyAgent } = require('http-proxy-agent'); const { SocksProxyAgent } = require('socks-proxy-agent'); const { makeAxiosInstance } = require('../utils/axios-instance'); const { addAwsV4Interceptor, resolveAwsV4Credentials } = require('./awsv4auth-helper'); -const { shouldUseProxy, PatchedHttpsProxyAgent } = require('../utils/proxy-util'); +const { shouldUseProxy, PatchedHttpsProxyAgent, getSystemProxyEnvVariables } = require('../utils/proxy-util'); const path = require('path'); const { createFormData } = require('../utils/common'); const { getCookieStringForUrl, saveCookies, shouldUseCookies } = require('../utils/cookies'); @@ -42,7 +42,7 @@ const runSingleRequest = async function ( try { let request; let nextRequestName; - let item = { + let item = { pathname: path.join(collectionPath, filename), ...bruJson } @@ -140,39 +140,85 @@ const runSingleRequest = async function ( } } - // set proxy if enabled - const proxyEnabled = get(brunoConfig, 'proxy.enabled', false); - const shouldProxy = shouldUseProxy(request.url, get(brunoConfig, 'proxy.bypassProxy', '')); - if (proxyEnabled && shouldProxy) { - const proxyProtocol = interpolateString(get(brunoConfig, 'proxy.protocol'), interpolationOptions); - const proxyHostname = interpolateString(get(brunoConfig, 'proxy.hostname'), interpolationOptions); - const proxyPort = interpolateString(get(brunoConfig, 'proxy.port'), interpolationOptions); - const proxyAuthEnabled = get(brunoConfig, 'proxy.auth.enabled', false); - const socksEnabled = proxyProtocol.includes('socks'); + let proxyMode = 'off'; + let proxyConfig = {}; - let uriPort = isUndefined(proxyPort) || isNull(proxyPort) ? '' : `:${proxyPort}`; - let proxyUri; - if (proxyAuthEnabled) { - const proxyAuthUsername = interpolateString(get(brunoConfig, 'proxy.auth.username'), interpolationOptions); - const proxyAuthPassword = interpolateString(get(brunoConfig, 'proxy.auth.password'), interpolationOptions); - - proxyUri = `${proxyProtocol}://${proxyAuthUsername}:${proxyAuthPassword}@${proxyHostname}${uriPort}`; - } else { - proxyUri = `${proxyProtocol}://${proxyHostname}${uriPort}`; + const collectionProxyConfig = get(brunoConfig, 'proxy', {}); + const collectionProxyEnabled = get(collectionProxyConfig, 'enabled', false); + if (collectionProxyEnabled === true) { + proxyConfig = collectionProxyConfig; + proxyMode = 'on'; + } else { + // if the collection level proxy is not set, pick the system level proxy by default, to maintain backward compatibility + const { http_proxy, https_proxy } = getSystemProxyEnvVariables(); + if (http_proxy?.length || https_proxy?.length) { + proxyMode = 'system'; } + } - if (socksEnabled) { - request.httpsAgent = new SocksProxyAgent( - proxyUri, - Object.keys(httpsAgentRequestFields).length > 0 ? { ...httpsAgentRequestFields } : undefined - ); - request.httpAgent = new SocksProxyAgent(proxyUri); + if (proxyMode === 'on') { + const shouldProxy = shouldUseProxy(request.url, get(proxyConfig, 'bypassProxy', '')); + if (shouldProxy) { + const proxyProtocol = interpolateString(get(proxyConfig, 'protocol'), interpolationOptions); + const proxyHostname = interpolateString(get(proxyConfig, 'hostname'), interpolationOptions); + const proxyPort = interpolateString(get(proxyConfig, 'port'), interpolationOptions); + const proxyAuthEnabled = get(proxyConfig, 'auth.enabled', false); + const socksEnabled = proxyProtocol.includes('socks'); + let uriPort = isUndefined(proxyPort) || isNull(proxyPort) ? '' : `:${proxyPort}`; + let proxyUri; + if (proxyAuthEnabled) { + const proxyAuthUsername = interpolateString(get(proxyConfig, 'auth.username'), interpolationOptions); + const proxyAuthPassword = interpolateString(get(proxyConfig, 'auth.password'), interpolationOptions); + + proxyUri = `${proxyProtocol}://${proxyAuthUsername}:${proxyAuthPassword}@${proxyHostname}${uriPort}`; + } else { + proxyUri = `${proxyProtocol}://${proxyHostname}${uriPort}`; + } + if (socksEnabled) { + request.httpsAgent = new SocksProxyAgent( + proxyUri, + Object.keys(httpsAgentRequestFields).length > 0 ? { ...httpsAgentRequestFields } : undefined + ); + request.httpAgent = new SocksProxyAgent(proxyUri); + } else { + request.httpsAgent = new PatchedHttpsProxyAgent( + proxyUri, + Object.keys(httpsAgentRequestFields).length > 0 ? { ...httpsAgentRequestFields } : undefined + ); + request.httpAgent = new HttpProxyAgent(proxyUri); + } } else { - request.httpsAgent = new PatchedHttpsProxyAgent( - proxyUri, - Object.keys(httpsAgentRequestFields).length > 0 ? { ...httpsAgentRequestFields } : undefined - ); - request.httpAgent = new HttpProxyAgent(proxyUri); + request.httpsAgent = new https.Agent({ + ...httpsAgentRequestFields + }); + } + } else if (proxyMode === 'system') { + const { http_proxy, https_proxy, no_proxy } = getSystemProxyEnvVariables(); + const shouldUseSystemProxy = shouldUseProxy(request.url, no_proxy || ''); + if (shouldUseSystemProxy) { + try { + if (http_proxy?.length) { + new URL(http_proxy); + request.httpAgent = new HttpProxyAgent(http_proxy); + } + } catch (error) { + throw new Error('Invalid system http_proxy'); + } + try { + if (https_proxy?.length) { + new URL(https_proxy); + request.httpsAgent = new PatchedHttpsProxyAgent( + https_proxy, + Object.keys(httpsAgentRequestFields).length > 0 ? { ...httpsAgentRequestFields } : undefined + ); + } + } catch (error) { + throw new Error('Invalid system https_proxy'); + } + } else { + request.httpsAgent = new https.Agent({ + ...httpsAgentRequestFields + }); } } else if (Object.keys(httpsAgentRequestFields).length > 0) { request.httpsAgent = new https.Agent({ diff --git a/packages/bruno-cli/src/utils/axios-instance.js b/packages/bruno-cli/src/utils/axios-instance.js index 8f61066c5..834cda2a8 100644 --- a/packages/bruno-cli/src/utils/axios-instance.js +++ b/packages/bruno-cli/src/utils/axios-instance.js @@ -10,6 +10,7 @@ const { CLI_VERSION } = require('../constants'); function makeAxiosInstance() { /** @type {axios.AxiosInstance} */ const instance = axios.create({ + proxy: false, headers: { "User-Agent": `bruno-runtime/${CLI_VERSION}` } diff --git a/packages/bruno-cli/src/utils/proxy-util.js b/packages/bruno-cli/src/utils/proxy-util.js index 729e03356..2a93d517e 100644 --- a/packages/bruno-cli/src/utils/proxy-util.js +++ b/packages/bruno-cli/src/utils/proxy-util.js @@ -79,7 +79,18 @@ class PatchedHttpsProxyAgent extends HttpsProxyAgent { } } + +const 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 + }; +} + module.exports = { shouldUseProxy, - PatchedHttpsProxyAgent + PatchedHttpsProxyAgent, + getSystemProxyEnvVariables };