Skip to content

Commit

Permalink
Update the proxyPolicy and constants (Azure#7069)
Browse files Browse the repository at this point in the history
* update to latest version of azure-sdk-for-js

* udpate core-http.api.md

* update proxyPolicy.ts

* update proxyPolicy.ts according to comments
  • Loading branch information
zzhxiaofeng authored and deyaaeldeen committed Sep 25, 2020
1 parent 3fcd5ce commit 887ec56
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 29 deletions.
2 changes: 2 additions & 0 deletions sdk/core/core-http/review/core-http.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ export const Constants: {
HTTPS: string;
HTTP_PROXY: string;
HTTPS_PROXY: string;
NO_PROXY: string;
ALL_PROXY: string;
HttpConstants: {
HttpVerbs: {
PUT: string;
Expand Down
58 changes: 48 additions & 10 deletions sdk/core/core-http/src/policies/proxyPolicy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,61 @@ import { ProxySettings } from "../serviceClient";
import { WebResourceLike } from "../webResource";
import { Constants } from "../util/constants";
import { URLBuilder } from "../url";
import { getEnvironmentValue } from "../util/utils";

let noProxyList: string[] = [];
let isNoProxyInitalized = false;
let byPassedList = new Map();

function loadEnvironmentProxyValue(): string | undefined {
if (!process) {
return undefined;
}

if (process.env[Constants.HTTPS_PROXY]) {
return process.env[Constants.HTTPS_PROXY];
} else if (process.env[Constants.HTTPS_PROXY.toLowerCase()]) {
return process.env[Constants.HTTPS_PROXY.toLowerCase()];
} else if (process.env[Constants.HTTP_PROXY]) {
return process.env[Constants.HTTP_PROXY];
} else if (process.env[Constants.HTTP_PROXY.toLowerCase()]) {
return process.env[Constants.HTTP_PROXY.toLowerCase()];
const httpsProxy = getEnvironmentValue(Constants.HTTPS_PROXY);
const allProxy = getEnvironmentValue(Constants.ALL_PROXY);
const httpProxy = getEnvironmentValue(Constants.HTTP_PROXY);

return httpsProxy || allProxy || httpProxy;
}

// Check whether the given `uri` matches the noProxyList. If it matches, any request sent to that same `uri` won't set the proxy settings.
function isBypassed(uri: string) {
if (byPassedList.has(uri)) {
return byPassedList.get(uri);
}
loadNoProxy();
let isBypassed = false;
let host = URLBuilder.parse(uri).getHost()!;
for (const proxyString of noProxyList) {
if (proxyString[0] === ".") {
if (uri.endsWith(proxyString)) {
isBypassed = true;
} else {
if (host === proxyString.slice(1) && host.length === proxyString.length - 1) {
isBypassed = true;
}
}
} else {
if (host === proxyString) {
isBypassed = true;
}
}
}
byPassedList.set(uri, isBypassed);
return isBypassed;
}

return undefined;
function loadNoProxy() {
if (isNoProxyInitalized) {
return;
}
const noProxy = getEnvironmentValue(Constants.NO_PROXY);
if (noProxy) {
let list = noProxy.split(",");
noProxyList = list.map((item) => item.trim()).filter((item) => item.length);
}
isNoProxyInitalized = true;
}

export function getDefaultProxySettings(proxyUrl?: string): ProxySettings | undefined {
Expand Down Expand Up @@ -97,7 +135,7 @@ export class ProxyPolicy extends BaseRequestPolicy {
}

public sendRequest(request: WebResourceLike): Promise<HttpOperationResponse> {
if (!request.proxySettings) {
if (!request.proxySettings && !isBypassed(request.url)) {
request.proxySettings = this.proxySettings;
}
return this._nextPolicy.sendRequest(request);
Expand Down
16 changes: 16 additions & 0 deletions sdk/core/core-http/src/util/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@ export const Constants = {
*/
HTTPS_PROXY: "HTTPS_PROXY",

/**
* Specifies NO Proxy.
*
* @const
* @type {string}
*/
NO_PROXY: "NO_PROXY",

/**
* Specifies ALL Proxy.
*
* @const
* @type {string}
*/
ALL_PROXY: "ALL_PROXY",

HttpConstants: {
/**
* Http Verbs
Expand Down
9 changes: 9 additions & 0 deletions sdk/core/core-http/src/util/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,3 +254,12 @@ export function replaceAll(
export function isPrimitiveType(value: any): boolean {
return (typeof value !== "object" && typeof value !== "function") || value === null;
}

export function getEnvironmentValue(name: string): string | undefined {
if (process.env[name]) {
return process.env[name];
} else if (process.env[name.toLowerCase()]) {
return process.env[name.toLowerCase()];
}
return undefined;
}
81 changes: 62 additions & 19 deletions sdk/core/core-http/test/policies/proxyPolicyTests.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ describe("ProxyPolicy (node)", function() {
};

const emptyPolicyOptions = new RequestPolicyOptions();
process.env[Constants.NO_PROXY] = ".foo.com, test.com";

describe("for Node.js", function() {
it("factory passes correct proxy settings", function(done) {
Expand Down Expand Up @@ -63,6 +64,35 @@ describe("ProxyPolicy (node)", function() {

request.proxySettings!.should.be.deep.equal(requestSpecificProxySettings);
});

it("should not assign proxy settings to the web request when noProxyList contain request url", async () => {
let request = new WebResource();
let policy = new ProxyPolicy(emptyRequestPolicy, emptyPolicyOptions, proxySettings);
request.url = "http://foo.com";
await policy.sendRequest(request);
should().not.exist(request.proxySettings);

request.url = "https://www.foo.com";
await policy.sendRequest(request);
should().not.exist(request.proxySettings);

request.url = "http://test.foo.com";
await policy.sendRequest(request);
should().not.exist(request.proxySettings);

request.url = "http://abcfoo.com";
await policy.sendRequest(request);
request.proxySettings!.should.be.deep.equal(proxySettings);

request.proxySettings = undefined;
request.url = "http://test.com";
await policy.sendRequest(request);
should().not.exist(request.proxySettings);

request.url = "http://www.test.com";
await policy.sendRequest(request);
request.proxySettings!.should.be.deep.equal(proxySettings);
});
});
});

Expand Down Expand Up @@ -146,6 +176,10 @@ describe("getDefaultProxySettings", () => {
delete process.env[Constants.HTTPS_PROXY];
delete process.env[Constants.HTTP_PROXY.toLowerCase()];
delete process.env[Constants.HTTPS_PROXY.toLowerCase()];
delete process.env[Constants.ALL_PROXY];
delete process.env[Constants.ALL_PROXY.toLowerCase()];
delete process.env[Constants.NO_PROXY];
delete process.env[Constants.NO_PROXY.toLowerCase()];
});

it("should return undefined when no proxy passed and environment variable is not set", () => {
Expand All @@ -162,6 +196,24 @@ describe("getDefaultProxySettings", () => {
proxySettings.port.should.equal(defaultPort);
});

describe("should load setting from ALL_PROXY(all_proxy) environmental variable when no proxy passed and one of HTTPS proxy and HTTP proxy is not set ", () => {
[
{ name: "lower case", func: (envVar: string) => envVar.toLowerCase() },
{ name: "upper case", func: (envVar: string) => envVar.toUpperCase() }
].forEach((testCase) => {
it(`with ${testCase.name}`, () => {
const allProxy = "https://proxy.azure.com";
const httpProxy = "http://proxy.microsoft.com";
process.env[testCase.func(Constants.HTTP_PROXY)] = httpProxy;
process.env[testCase.func(Constants.ALL_PROXY)] = allProxy;

const proxySettings: ProxySettings = getDefaultProxySettings()!;
proxySettings.host.should.equal(allProxy);
proxySettings.port.should.equal(defaultPort);
});
});
});

describe("should prefer HTTPS proxy over HTTP proxy", () => {
[
{ name: "lower case", func: (envVar: string) => envVar.toLowerCase() },
Expand All @@ -178,28 +230,19 @@ describe("getDefaultProxySettings", () => {
proxySettings.port.should.equal(defaultPort);
});
});

it("should prefer HTTPS proxy over HTTP proxy", () => {
const httpProxy = "http://proxy.microsoft.com";
const httpsProxy = "https://proxy.azure.com";
process.env[Constants.HTTP_PROXY] = httpProxy;
process.env[Constants.HTTPS_PROXY] = httpsProxy;

const proxySettings: ProxySettings = getDefaultProxySettings()!;
proxySettings.host.should.equal(httpsProxy);
proxySettings.port.should.equal(defaultPort);
});
});

["HTTP_PROXY", "HTTPS_PROXY", "http_proxy", "https_proxy"].forEach((envVariableName) => {
it(`should should load setting from "${envVariableName}" environmental variable`, () => {
process.env[envVariableName] = proxyUrl;
const proxySettings: ProxySettings = getDefaultProxySettings()!;
["HTTP_PROXY", "HTTPS_PROXY", "ALL_PROXY", "http_proxy", "https_proxy", "all_proxy"].forEach(
(envVariableName) => {
it(`should load setting from "${envVariableName}" environmental variable`, () => {
process.env[envVariableName] = proxyUrl;
const proxySettings: ProxySettings = getDefaultProxySettings()!;

proxySettings.host.should.equal(proxyUrl);
proxySettings.port.should.equal(defaultPort);
});
});
proxySettings.host.should.equal(proxyUrl);
proxySettings.port.should.equal(defaultPort);
});
}
);
});
});
});

0 comments on commit 887ec56

Please sign in to comment.