Skip to content

Commit fb34438

Browse files
authored
added formatted proxy URL (#834)
* added formatted proxy URL * version increment
1 parent 7486d51 commit fb34438

File tree

6 files changed

+104
-4
lines changed

6 files changed

+104
-4
lines changed

node/docs/proxy.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export interface ProxyConfiguration {
1414
proxyUsername?: string;
1515
proxyPassword?: string;
1616
proxyBypassHosts?: string[];
17+
proxyFormattedUrl: string;
1718
}
1819
```
1920

@@ -61,6 +62,24 @@ async function run() {
6162
run();
6263
```
6364

65+
For some external applications executed from the shell, you might need to set an environment variable that contains a formatted URL
66+
in the following format: protocol://user:password@hostname:port
67+
You can retrieve such configuration directly from task-lib:
68+
```typescript
69+
import tl = require('azure-pipelines-task-lib/task');
70+
71+
async function run() {
72+
let proxy = tl.getProxyConfiguration()
73+
74+
process.env['http_proxy'] = proxy.proxyFormattedUrl;
75+
process.env['https_proxy'] = proxy.proxyFormattedUrl;
76+
const gitPath: string = tl.which('git');
77+
const gitPull = tl.tool(gitPath);
78+
await gitPull.exec()
79+
}
80+
81+
run();
82+
```
6483
#### PowerShell Lib
6584

6685
Method for retrieve proxy settings in PowerShell lib

node/package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

node/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "azure-pipelines-task-lib",
3-
"version": "3.2.1",
3+
"version": "3.3.0",
44
"description": "Azure Pipelines Task SDK",
55
"main": "./task.js",
66
"typings": "./task.d.ts",

node/task.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1839,11 +1839,33 @@ export function findMatch(defaultRoot: string, patterns: string[] | string, find
18391839

18401840
export interface ProxyConfiguration {
18411841
proxyUrl: string;
1842+
/**
1843+
* Proxy URI formated as: protocol://username:password@hostname:port
1844+
*
1845+
* For tools that require setting proxy configuration in the single environment variable
1846+
*/
1847+
proxyFormattedUrl: string;
18421848
proxyUsername?: string;
18431849
proxyPassword?: string;
18441850
proxyBypassHosts?: string[];
18451851
}
18461852

1853+
/**
1854+
* Build Proxy URL in the following format: protocol://username:password@hostname:port
1855+
* @param proxyUrl Url address of the proxy server (eg: http://example.com)
1856+
* @param proxyUsername Proxy username (optional)
1857+
* @param proxyPassword Proxy password (optional)
1858+
* @returns string
1859+
*/
1860+
function getProxyFormattedUrl(proxyUrl: string, proxyUsername: string | undefined, proxyPassword: string | undefined): string {
1861+
const parsedUrl: URL = new URL(proxyUrl);
1862+
let proxyAddress: string = `${parsedUrl.protocol}//${parsedUrl.host}`;
1863+
if (proxyUsername) {
1864+
proxyAddress = `${parsedUrl.protocol}//${proxyUsername}:${proxyPassword}@${parsedUrl.host}`;
1865+
}
1866+
return proxyAddress;
1867+
}
1868+
18471869
/**
18481870
* Gets http proxy configuration used by Build/Release agent
18491871
*
@@ -1869,11 +1891,13 @@ export function getHttpProxyConfiguration(requestUrl?: string): ProxyConfigurati
18691891
return null;
18701892
}
18711893
else {
1894+
const proxyAddress = getProxyFormattedUrl(proxyUrl, proxyUsername, proxyPassword)
18721895
return {
18731896
proxyUrl: proxyUrl,
18741897
proxyUsername: proxyUsername,
18751898
proxyPassword: proxyPassword,
1876-
proxyBypassHosts: proxyBypassHosts
1899+
proxyBypassHosts: proxyBypassHosts,
1900+
proxyFormattedUrl: proxyAddress
18771901
};
18781902
}
18791903
}

node/test/gethttpproxytests.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import * as assert from 'assert';
2+
import * as tl from '../_build/task';
3+
4+
enum ProxyEnvironmentEnum {
5+
proxyUrl = 'AGENT_PROXYURL',
6+
proxyUsername = 'AGENT_PROXYUSERNAME',
7+
proxyPassword = 'AGENT_PROXYPASSWORD',
8+
proxyBypass = 'AGENT_PROXYBYPASSLIST'
9+
}
10+
11+
describe('GetHttpProxyConfiguration Tests', () => {
12+
const proxyHost: string = 'proxy.example.com';
13+
const proxyPort: number = 8888;
14+
const proxyUrl: string = `http://${proxyHost}:${proxyPort}`;
15+
const proxyUsername: string = 'proxyUser';
16+
const proxyPassword: string = 'proxyPassword';
17+
const proxyByPass: string[] = ['http://bypass.example.com'];
18+
const formatedUrlWithoutCrednetials = proxyUrl;
19+
const fortmatedUrlWithCredentials = `http://${proxyUsername}:${proxyPassword}@${proxyHost}:${proxyPort}`;
20+
21+
it('returns a valid proxy configuration if no credentials set', () => {
22+
process.env[ProxyEnvironmentEnum.proxyUrl] = proxyUrl;
23+
process.env[ProxyEnvironmentEnum.proxyBypass] = JSON.stringify(proxyByPass);
24+
const expected: tl.ProxyConfiguration = {
25+
proxyUrl: proxyUrl,
26+
proxyBypassHosts: proxyByPass,
27+
proxyUsername: undefined,
28+
proxyPassword: undefined,
29+
proxyFormattedUrl: formatedUrlWithoutCrednetials
30+
}
31+
const result = tl.getHttpProxyConfiguration();
32+
assert.deepStrictEqual(result, expected, 'it should have valid configuration');
33+
});
34+
35+
it('returns valid proxy configuration if credentials set', () => {
36+
process.env[ProxyEnvironmentEnum.proxyUrl] = proxyUrl;
37+
process.env[ProxyEnvironmentEnum.proxyUsername] = proxyUsername;
38+
process.env[ProxyEnvironmentEnum.proxyPassword] = proxyPassword;
39+
process.env[ProxyEnvironmentEnum.proxyBypass] = JSON.stringify(proxyByPass);
40+
const expected: tl.ProxyConfiguration = {
41+
proxyUrl: proxyUrl,
42+
proxyBypassHosts: proxyByPass,
43+
proxyFormattedUrl: fortmatedUrlWithCredentials,
44+
proxyPassword: proxyPassword,
45+
proxyUsername: proxyUsername
46+
}
47+
const result = tl.getHttpProxyConfiguration();
48+
assert.deepStrictEqual(result, expected, 'it should have credentials in formatted url');
49+
});
50+
51+
it('returns null if host should be bypassed', () => {
52+
process.env[ProxyEnvironmentEnum.proxyUrl] = proxyUrl;
53+
const result = tl.getHttpProxyConfiguration(proxyByPass[0]);
54+
assert.strictEqual(result, null, 'result should be null');
55+
});
56+
})

node/test/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"findmatchtests.ts",
2424
"mocktests.ts",
2525
"retrytests.ts",
26-
"isuncpathtests.ts"
26+
"isuncpathtests.ts",
27+
"gethttpproxytests.ts"
2728
]
2829
}

0 commit comments

Comments
 (0)