From f1f203e3596e983707fd6143236a08d8ac0c7b19 Mon Sep 17 00:00:00 2001 From: Zekai Zhao Date: Thu, 2 Apr 2026 11:00:28 +0800 Subject: [PATCH] Adds NO_PROXY support for proxy configuration. Closes #7165 --- docs/docs/user-guide/using-proxy-url.mdx | 10 ++++ src/request.spec.ts | 63 ++---------------------- src/request.ts | 21 +------- 3 files changed, 16 insertions(+), 78 deletions(-) diff --git a/docs/docs/user-guide/using-proxy-url.mdx b/docs/docs/user-guide/using-proxy-url.mdx index b0204ecf705..ca26b4c0599 100644 --- a/docs/docs/user-guide/using-proxy-url.mdx +++ b/docs/docs/user-guide/using-proxy-url.mdx @@ -15,3 +15,13 @@ When using a proxy, it's important to understand the different parts of a proxy - **username and password**: if the proxy server requires authentication, you will need to provide a username and password - **host**: the hostname or IP address of the proxy server - **port number**: the port number on which the proxy server is listening. Defaults to 443 for the `HTTPS` protocol, otherwise it defaults to 80 when not provided + +## Bypassing the proxy for specific hosts + +If you need certain requests to bypass the proxy, you can use the `NO_PROXY` (or `no_proxy`) environment variable. This is a comma-separated list of hostnames or domain patterns that should not be routed through the proxy. + +For example, to bypass the proxy for Microsoft authentication endpoints: + +```sh +export NO_PROXY="login.microsoftonline.com,*.microsoft.com,*.azure.net" +``` diff --git a/src/request.spec.ts b/src/request.spec.ts index 649b39cabd3..849313112af 100644 --- a/src/request.spec.ts +++ b/src/request.spec.ts @@ -292,16 +292,11 @@ describe('Request', () => { }); }); - it('returns response of a successful GET request, with a proxy url', async () => { - let proxyConfigured = false; + it('does not set explicit proxy config on requests, letting Axios handle proxy natively', async () => { sinon.stub(process, 'env').value({ 'HTTPS_PROXY': 'http://proxy.contoso.com:8080' }); sinon.stub(_request as any, 'req').callsFake((options) => { _options = options as CliRequestOptions; - proxyConfigured = !!_options.proxy && - _options.proxy.host === 'proxy.contoso.com' && - _options.proxy.port === 8080 && - _options.proxy.protocol === 'http'; return { data: {} }; }); @@ -310,19 +305,14 @@ describe('Request', () => { url: 'https://contoso.sharepoint.com/' }); - assert(proxyConfigured); + assert.strictEqual(_options.proxy, undefined); }); - it('returns response of a successful GET request, with a proxy url and defaults port to 80', async () => { - let proxyConfigured = false; - sinon.stub(process, 'env').value({ 'HTTPS_PROXY': 'http://proxy.contoso.com' }); + it('does not set explicit proxy config when NO_PROXY is set', async () => { + sinon.stub(process, 'env').value({ 'HTTPS_PROXY': 'http://proxy.contoso.com:8080', 'NO_PROXY': 'contoso.sharepoint.com' }); sinon.stub(_request as any, 'req').callsFake((options) => { _options = options as CliRequestOptions; - proxyConfigured = !!_options.proxy && - _options.proxy.host === 'proxy.contoso.com' && - _options.proxy.port === 80 && - _options.proxy.protocol === 'http'; return { data: {} }; }); @@ -331,50 +321,7 @@ describe('Request', () => { url: 'https://contoso.sharepoint.com/' }); - assert(proxyConfigured); - }); - - it('returns response of a successful GET request, with a proxy url and defaults port to 443', async () => { - let proxyConfigured = false; - sinon.stub(process, 'env').value({ 'HTTPS_PROXY': 'https://proxy.contoso.com' }); - - sinon.stub(_request as any, 'req').callsFake((options) => { - _options = options as CliRequestOptions; - proxyConfigured = !!_options.proxy && - _options.proxy.host === 'proxy.contoso.com' && - _options.proxy.port === 443 && - _options.proxy.protocol === 'http'; - return { data: {} }; - }); - - await _request - .get({ - url: 'https://contoso.sharepoint.com/' - }); - assert(proxyConfigured); - }); - - it('returns response of a successful GET request, with a proxy url with username and password', async () => { - let proxyConfigured = false; - sinon.stub(process, 'env').value({ 'HTTPS_PROXY': 'http://username:password@proxy.contoso.com:8080' }); - - sinon.stub(_request as any, 'req').callsFake((options) => { - _options = options as CliRequestOptions; - proxyConfigured = !!_options.proxy && - _options.proxy.host === 'proxy.contoso.com' && - _options.proxy.port === 8080 && - _options.proxy.protocol === 'http' && - _options.proxy.auth?.username === 'username' && - _options.proxy.auth?.password === 'password'; - return { data: {} }; - }); - - await _request - .get({ - url: 'https://contoso.sharepoint.com/' - }); - - assert(proxyConfigured); + assert.strictEqual(_options.proxy, undefined); }); it('correctly handles failed GET request', async () => { diff --git a/src/request.ts b/src/request.ts index 4c5b55ea785..69eaf4e6d59 100644 --- a/src/request.ts +++ b/src/request.ts @@ -1,4 +1,4 @@ -import Axios, { AxiosError, AxiosInstance, AxiosProxyConfig, AxiosRequestConfig, AxiosResponse } from 'axios'; +import Axios, { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'; import { Stream } from 'stream'; import auth, { Auth, CloudType } from './Auth.js'; import { Logger } from './cli/Logger.js'; @@ -186,12 +186,6 @@ class Request { } } - const proxyUrl = process.env.HTTP_PROXY || process.env.HTTPS_PROXY; - - if (proxyUrl) { - options.proxy = this.createProxyConfigFromUrl(proxyUrl); - } - const res = await this.req(options); const end = process.hrtime.bigint(); @@ -235,19 +229,6 @@ class Request { options.url = options.url!.substring(0, 8) + options.url!.substring(8).replace('//', '/'); } - - private createProxyConfigFromUrl(url: string): AxiosProxyConfig { - const parsedUrl = new URL(url); - const port = parsedUrl.port || (url.toLowerCase().startsWith('https') ? 443 : 80); - let authObject = null; - if (parsedUrl.username && parsedUrl.password) { - authObject = { - username: parsedUrl.username, - password: parsedUrl.password - }; - } - return { host: parsedUrl.hostname, port: Number(port), protocol: 'http', ...(authObject && { auth: authObject }) }; - } } export default new Request();