Skip to content

Commit 26d547a

Browse files
authored
Merge pull request #139 from salesforcecli/phale/W-8857752
fix: add proxy support for got
2 parents ac7120c + 5bee1b5 commit 26d547a

File tree

8 files changed

+383
-106
lines changed

8 files changed

+383
-106
lines changed

.mocharc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
"watch-extensions": "ts",
44
"recursive": true,
55
"reporter": "spec",
6-
"timeout": 10000
6+
"timeout": 20000
77
}

package.json

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"@salesforce/core": "^2.15.2",
1414
"@salesforce/kit": "^1.3.3",
1515
"@salesforce/ts-types": "^1.4.3",
16+
"agent-base": "^6.0.2",
1617
"aws-sdk": "^2.782.0",
1718
"chalk": "^4.1.0",
1819
"cli-ux": "^5.5.1",
@@ -22,6 +23,8 @@
2223
"fast-glob": "^3.2.5",
2324
"glob": "^7.1.6",
2425
"got": "^11.8.0",
26+
"proxy-agent": "^4.0.1",
27+
"proxy-from-env": "^1.1.0",
2528
"shelljs": "^0.8.4",
2629
"standard-version": "^9.0.0",
2730
"tslib": "^2"
@@ -30,11 +33,11 @@
3033
"@oclif/dev-cli": "^1",
3134
"@oclif/plugin-command-snapshot": "^2.0.0",
3235
"@salesforce/cli-plugins-testkit": "^0.0.25",
33-
"@salesforce/dev-config": "^2.1.0",
34-
"@salesforce/dev-scripts": "0.9.1",
36+
"@salesforce/dev-config": "^2.1.2",
37+
"@salesforce/dev-scripts": "^0.9.11",
3538
"@salesforce/plugin-command-reference": "^1.3.0",
3639
"@salesforce/prettier-config": "^0.0.2",
37-
"@salesforce/ts-sinon": "1.3.5",
40+
"@salesforce/ts-sinon": "1.3.12",
3841
"@types/conventional-changelog-preset-loader": "^2.3.1",
3942
"@types/conventional-commits-parser": "^3.0.1",
4043
"@types/shelljs": "^0.8.8",
@@ -45,9 +48,9 @@
4548
"cz-conventional-changelog": "^3.2.0",
4649
"eslint": "^6.8.0",
4750
"eslint-config-prettier": "^6.11.0",
48-
"eslint-config-salesforce": "^0.1.0",
49-
"eslint-config-salesforce-license": "^0.1.0",
50-
"eslint-config-salesforce-typescript": "^0.2.0",
51+
"eslint-config-salesforce": "^0.1.6",
52+
"eslint-config-salesforce-license": "^0.1.6",
53+
"eslint-config-salesforce-typescript": "^0.2.7",
5154
"eslint-plugin-header": "^3.0.0",
5255
"eslint-plugin-import": "^2.20.2",
5356
"eslint-plugin-jsdoc": "^27.0.3",

src/codeSigning/packAndSign.ts

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,18 @@ import { exec } from 'child_process';
1212
import { EOL } from 'os';
1313
import { basename, join as pathJoin } from 'path';
1414
import { sep as pathSep } from 'path';
15+
// import { URL } from 'url';
1516
import { Readable } from 'stream';
1617
import { copyFile, createReadStream } from 'fs';
17-
import * as https from 'https';
18+
import { Agent } from 'https';
19+
import got, { Agents, RequestError } from 'got';
1820
import { UX } from '@salesforce/command';
1921
import { fs, Logger } from '@salesforce/core';
2022
import { NamedError } from '@salesforce/kit';
23+
import * as ProxyAgent from 'proxy-agent';
24+
import { getProxyForUrl } from 'proxy-from-env';
25+
26+
// import { AgentOptions } from 'agent-base';
2127
import {
2228
CodeSignInfo,
2329
CodeVerifierInfo,
@@ -166,35 +172,36 @@ export const api = {
166172
* @param publicKeyUrl - url for the public key
167173
*/
168174
verify(tarGzStream: Readable, sigFilenameStream: Readable, publicKeyUrl: string): Promise<boolean> {
169-
return new Promise<boolean>((resolve, reject) => {
175+
return new Promise<boolean>((resolve) => {
170176
const verifyInfo = new CodeVerifierInfo();
171177
verifyInfo.dataToVerify = tarGzStream;
172178
verifyInfo.signatureStream = sigFilenameStream;
173179

174-
const req = https.get(publicKeyUrl, { agent: false });
175-
176-
req.on('response', (response) => {
177-
if (response && response.statusCode === 200) {
178-
verifyInfo.publicKeyStream = response;
179-
return resolve(verify(verifyInfo));
180-
} else {
181-
const statusCode: number = response.statusCode;
182-
return reject(
183-
new NamedError(
184-
'RetrievePublicKeyFailed',
185-
`Couldn't retrieve public key at url: ${publicKeyUrl} error code: ${statusCode}`
186-
)
187-
);
188-
}
189-
});
190-
191-
req.on('error', (err: Error) => {
192-
if (err && err['code'] === 'DEPTH_ZERO_SELF_SIGNED_CERT') {
193-
reject(new SignSignedCertError());
194-
} else {
195-
reject(err);
196-
}
197-
});
180+
return resolve(
181+
(async (): Promise<boolean> => {
182+
try {
183+
const agent = api.getAgentForUri(publicKeyUrl);
184+
const response = await got.get(publicKeyUrl, { agent });
185+
if (response && response.statusCode === 200) {
186+
verifyInfo.publicKeyStream = Readable.from([response.body]);
187+
return await verify(verifyInfo);
188+
} else {
189+
const statusCode: number = response.statusCode;
190+
throw new NamedError(
191+
'RetrievePublicKeyFailed',
192+
`Couldn't retrieve public key at url: ${publicKeyUrl} error code: ${statusCode}`
193+
);
194+
}
195+
} catch (err) {
196+
const error = err as RequestError;
197+
if (error && error.code === 'DEPTH_ZERO_SELF_SIGNED_CERT') {
198+
throw new SignSignedCertError();
199+
} else {
200+
throw err;
201+
}
202+
}
203+
})()
204+
);
198205
});
199206
},
200207

@@ -454,4 +461,11 @@ export const api = {
454461
}
455462
}
456463
},
464+
465+
getAgentForUri(url: string): false | Agents {
466+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
467+
const proxyUrl: string = getProxyForUrl(url) as string;
468+
const agent = ProxyAgent(proxyUrl) as Agent;
469+
return { https: agent, http: agent };
470+
},
457471
};

src/commands/circleci/envvar/update.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { isArray, isString, Dictionary, AnyJson, getArray } from '@salesforce/ts
1313
import { env } from '@salesforce/kit';
1414
import got, { Response } from 'got';
1515
import { green, red, bold, cyan, yellow } from 'chalk';
16+
import { api } from '../../../codeSigning/packAndSign';
1617

1718
Messages.importMessagesDirectory(__dirname);
1819
const messages = Messages.loadMessages('@salesforce/plugin-release-management', 'circleci');
@@ -99,7 +100,9 @@ export default class CircelCIEnvvarUpdate extends SfdxCommand {
99100
let response: Response<string>;
100101

101102
try {
102-
response = await got.get<string>(`${URL_BASE}/${slug}/envvar`, { headers: this.headers });
103+
const url = `${URL_BASE}/${slug}/envvar`;
104+
const agent = api.getAgentForUri(url);
105+
response = await got.get<string>(url, { headers: this.headers, agent });
103106
} catch (err) {
104107
const error = err as SfdxError;
105108
return `${error.message}. Skipping...`;
@@ -148,8 +151,11 @@ export default class CircelCIEnvvarUpdate extends SfdxCommand {
148151
if (!this.flags.dryrun) {
149152
try {
150153
// First remove the old envvar
151-
await got.delete(`${envvarUrl}/${name}`, { headers: this.headers });
154+
const url = `${envvarUrl}/${name}`;
155+
let agent = api.getAgentForUri(url);
156+
await got.delete(url, { headers: this.headers, agent });
152157

158+
agent = api.getAgentForUri(`${envvarUrl}`);
153159
await got.post(`${envvarUrl}`, {
154160
headers: this.headers,
155161
json: { name, value },

src/repositories.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
import got from 'got';
9+
import { api } from './codeSigning/packAndSign';
910

1011
const KNOWN_REPOSITORIES_URL = 'https://raw.githubusercontent.com/salesforcecli/status/main/repositories.json';
1112
const PACKAGE_REGISTRY_BASE_URL = 'https://www.npmjs.com/package';
@@ -33,7 +34,8 @@ export type RepositoryInfo = {
3334
* Get a list of known tooling repositories that include Salesforce CLI plugins, libraries, and orbs.
3435
*/
3536
export const retrieveKnownRepositories = async (): Promise<RepositoryInfo[]> => {
36-
const response = await got.get(KNOWN_REPOSITORIES_URL);
37+
const agent = api.getAgentForUri(KNOWN_REPOSITORIES_URL);
38+
const response = await got.get(KNOWN_REPOSITORIES_URL, { agent });
3739
const repositories = JSON.parse(response.body) as SourceRepositoryDefinition[];
3840

3941
return repositories.map((repository) => {

test/codeSigning/packAndSign.test.ts

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,47 +10,35 @@
1010
/* eslint-disable camelcase */
1111

1212
import child_process = require('child_process');
13-
import * as events from 'events';
1413
import { EOL } from 'os';
1514
import { join } from 'path';
1615
import { Readable } from 'stream';
1716
import * as fs from 'fs';
18-
import * as https from 'https';
1917
import { core, UX } from '@salesforce/command';
2018
import { fs as fscore } from '@salesforce/core';
2119
import { expect } from 'chai';
2220
import { testSetup } from '@salesforce/core/lib/testSetup';
2321
import { stubMethod } from '@salesforce/ts-sinon';
22+
import got from 'got';
2423
import { SigningResponse } from '../../src/codeSigning/packAndSign';
2524
import { CERTIFICATE, PRIVATE_KEY, TEST_DATA } from './testCert';
2625

2726
const $$ = testSetup();
2827

2928
const _getCertResponse = (path: string, e?: Error, statusCode?: number) => {
30-
const response = new Readable({
31-
read() {
32-
this.push(CERTIFICATE);
33-
this.push(null);
34-
},
35-
});
29+
const response = {};
30+
(response as any).body = CERTIFICATE;
3631

3732
if (statusCode) {
3833
(response as any).statusCode = statusCode;
3934
} else {
4035
(response as any).statusCode = 200;
4136
}
4237

43-
const requestEmitter = new events.EventEmitter();
44-
45-
process.nextTick(() => {
46-
if (e) {
47-
requestEmitter.emit('error', e);
48-
} else {
49-
requestEmitter.emit('response', response);
50-
}
51-
});
52-
53-
return requestEmitter;
38+
if (e) {
39+
throw e;
40+
}
41+
return response;
5442
};
5543

5644
let packAndSignApi: any;
@@ -61,6 +49,10 @@ describe('doPackAndSign', () => {
6149
before(() => {
6250
let signature: string;
6351

52+
stubMethod($$.SANDBOX, got, 'get').callsFake(async (path: string) => {
53+
return _getCertResponse(path);
54+
});
55+
6456
$$.SANDBOX.stub(console, 'log');
6557
$$.SANDBOX.stub(console, 'info');
6658

@@ -105,10 +97,6 @@ describe('doPackAndSign', () => {
10597
cb(null, `foo.tgz${EOL}`);
10698
});
10799

108-
stubMethod($$.SANDBOX, https, 'get').callsFake((path: any) => {
109-
return _getCertResponse(path);
110-
});
111-
112100
packAndSignApi = require('../../src/codeSigning/packAndSign').api;
113101
});
114102

@@ -223,7 +211,7 @@ describe('packAndSign Tests', () => {
223211
describe('verify', () => {
224212
it('verify flow - false', () => {
225213
let url: string;
226-
stubMethod($$.SANDBOX, https, 'get').callsFake((_url: string) => {
214+
stubMethod($$.SANDBOX, got, 'get').callsFake(async (_url: string) => {
227215
url = _url;
228216
return _getCertResponse(_url);
229217
});
@@ -246,14 +234,14 @@ describe('packAndSign Tests', () => {
246234
packAndSignApi = require('../../src/codeSigning/packAndSign').api;
247235
}
248236

249-
return packAndSignApi.verify(tarGz, signature, 'baz').then((authentic: boolean) => {
237+
return packAndSignApi.verify(tarGz, signature, 'https://baz').then((authentic: boolean) => {
250238
expect(authentic).to.be.equal(false);
251-
expect(url).to.be.equal('baz');
239+
expect(url).to.be.equal('https://baz');
252240
});
253241
});
254242

255243
it('verify flow - self signed', () => {
256-
stubMethod($$.SANDBOX, https, 'get').callsFake((_url: string) => {
244+
stubMethod($$.SANDBOX, got, 'get').callsFake(async (_url: string) => {
257245
const e: any = new Error();
258246
e.code = 'DEPTH_ZERO_SELF_SIGNED_CERT';
259247
return _getCertResponse(_url, e);
@@ -278,7 +266,7 @@ describe('packAndSign Tests', () => {
278266
}
279267

280268
return packAndSignApi
281-
.verify(tarGz, signature, 'baz')
269+
.verify(tarGz, signature, 'https://baz.com')
282270
.then(() => {
283271
throw new Error('This should never happen');
284272
})
@@ -288,7 +276,7 @@ describe('packAndSign Tests', () => {
288276
});
289277

290278
it('verify flow - http 500', () => {
291-
stubMethod($$.SANDBOX, https, 'get').callsFake((_url: string) => {
279+
stubMethod($$.SANDBOX, got, 'get').callsFake((_url: string) => {
292280
return _getCertResponse(_url, undefined, 500);
293281
});
294282

@@ -311,7 +299,7 @@ describe('packAndSign Tests', () => {
311299
}
312300

313301
return packAndSignApi
314-
.verify(tarGz, signature, 'baz')
302+
.verify(tarGz, signature, 'https://baz')
315303
.then(() => {
316304
throw new Error('This should never happen');
317305
})
@@ -341,4 +329,12 @@ describe('packAndSign Tests', () => {
341329
expect(packAndSignApi.validateNpmIgnorePatterns('*.tgz*.sigpackage.json.bak')).to.be.equal(undefined);
342330
});
343331
});
332+
333+
// minimal test since the function getAgentForUrl delegates to proxy-agent module
334+
describe('getAgentForUri', () => {
335+
it('should always return an agent', () => {
336+
const agents = packAndSignApi.getAgentForUri('https://somewhere.com');
337+
expect(agents).to.be.ok;
338+
});
339+
});
344340
});

tsconfig.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
"extends": "@salesforce/dev-config/tsconfig",
33
"compilerOptions": {
44
"outDir": "lib",
5-
"rootDir": "src"
5+
"rootDir": "src",
6+
"allowSyntheticDefaultImports": true
67
},
7-
"include": [
8-
"./src/**/*.ts"
9-
]
8+
"include": ["./src/**/*.ts"]
109
}

0 commit comments

Comments
 (0)