Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/docs/user-guide/using-proxy-url.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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"
```
63 changes: 5 additions & 58 deletions src/request.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {} };
});

Expand All @@ -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: {} };
});

Expand All @@ -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 () => {
Expand Down
21 changes: 1 addition & 20 deletions src/request.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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();