Skip to content

Commit c58f4ee

Browse files
committed
Improve error handling
1 parent 08bae21 commit c58f4ee

2 files changed

Lines changed: 70 additions & 30 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"displayName": "Network Proxy Test",
44
"license": "MIT",
55
"publisher": "chrmarti",
6-
"version": "0.0.20",
6+
"version": "0.0.21",
77
"repository": {
88
"type": "git",
99
"url": "https://github.com/chrmarti/vscode-network-proxy-test.git"

src/extension.ts

Lines changed: 69 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ async function testConnection(useHTTP2: boolean) {
4343

4444
const editor = await openEmptyEditor();
4545
await logHeaderInfo(editor);
46+
await logCertificatesSummary(editor);
4647
await logSettings(editor);
4748
await logEnvVariables(editor);
4849
await lookupHosts(editor, url);
@@ -53,7 +54,11 @@ async function showOSCertificates() {
5354
const editor = await openEmptyEditor();
5455
await logHeaderInfo(editor);
5556
const certs = await loadSystemCertificates();
56-
await logCertificates(editor, `Certificates loaded from the OS (${osCertificateLocation()}):`, certs!);
57+
if (Array.isArray(certs)) {
58+
await logCertificates(editor, `Certificates loaded from the OS (${osCertificateLocation()}):`, certs);
59+
} else {
60+
await appendText(editor, `Error loading OS certificates: ${collectErrorMessages(certs.error)}\n`);
61+
}
5762
}
5863

5964
function osCertificateLocation() {
@@ -79,13 +84,31 @@ async function compareSystemCertificates() {
7984
const editor = await openEmptyEditor();
8085
await logHeaderInfo(editor);
8186

82-
// Get certificates from both sources
83-
const tlsSystemCerts = certsInfo(tls.getCACertificates?.('system') || []);
84-
const loadedSystemCerts = certsInfo(await loadSystemCertificates(false) || []);
85-
8687
await appendText(editor, `Comparing system certificates loaded by:\n`);
87-
await appendText(editor, `- Node.js: ${tlsSystemCerts.lengths}\n`);
88-
await appendText(editor, `- @vscode/proxy-agent: ${loadedSystemCerts.lengths}\n\n`);
88+
89+
const tlsCerts = loadSystemCertificatesNode();
90+
let tlsSystemCerts;
91+
if (Array.isArray(tlsCerts)) {
92+
tlsSystemCerts = certsInfo(tlsCerts);
93+
await appendText(editor, `- Node.js: ${tlsSystemCerts.lengths}\n`);
94+
} else if (!tlsCerts) {
95+
await appendText(editor, `- Node.js: tls.getCACertificates() not available in this Node.js version (${process.version})\n`);
96+
} else {
97+
await appendText(editor, `- Node.js: Error loading OS certificates: ${collectErrorMessages(tlsCerts.error)}\n`);
98+
}
99+
100+
const loadedCerts = await loadSystemCertificates(false);
101+
let loadedSystemCerts;
102+
if (Array.isArray(loadedCerts)) {
103+
loadedSystemCerts = certsInfo(loadedCerts);
104+
await appendText(editor, `- @vscode/proxy-agent: ${loadedSystemCerts.lengths}\n\n`);
105+
} else {
106+
await appendText(editor, `- @vscode/proxy-agent: Error loading OS certificates: ${collectErrorMessages(loadedCerts.error)}\n`);
107+
}
108+
109+
if (!tlsSystemCerts || !loadedSystemCerts) {
110+
return;
111+
}
89112

90113
const tlsMap = tlsSystemCerts.unique;
91114
const loadedMap = loadedSystemCerts.unique;
@@ -126,10 +149,10 @@ async function compareSystemCertificates() {
126149
async function logCertificates(editor: vscode.TextEditor, title: string, certs: ReadonlyArray<string | { from: string[]; pem: string; cert: crypto.X509Certificate }>) {
127150
await appendText(editor, `${title}\n`);
128151
for (const cert of certs) {
129-
const current = typeof cert === 'string' ? tryParseCertificate(cert) : cert instanceof crypto.X509Certificate ? cert : cert.cert;
152+
const current = typeof cert === 'string' ? tryParseCertificate(cert) : cert.cert;
130153
if (!(current instanceof crypto.X509Certificate)) {
131-
await appendText(editor, `- Certificate parse error: ${(current as any)?.message || String(current)}\n`);
132-
await appendText(editor, ` Input:\n${cert}\n`);
154+
await appendText(editor, `- Certificate parse error: ${current.error?.message || String(current.error)}\n`);
155+
await appendText(editor, ` Input: ${(typeof cert === 'string' ? cert : cert.pem).trim()}\n`);
133156
continue;
134157
}
135158
// await appendText(editor, `- Raw:\n${typeof cert === 'string' ? cert : cert.pem}\n`);
@@ -174,9 +197,12 @@ async function logRuntimeInfo(editor: vscode.TextEditor) {
174197
await appendText(editor, `Remote: ${vscode.env.remoteName}\n`);
175198
}
176199
await appendText(editor, `\n`);
200+
}
201+
202+
async function logCertificatesSummary(editor: vscode.TextEditor) {
177203
await appendText(editor, `Built-in certificates: ${certsInfo(tls.rootCertificates).lengths}\n`);
178204
const osCerts = await loadSystemCertificates();
179-
await appendText(editor, `OS certificates: ${osCerts ? certsInfo(osCerts).lengths : 'Failed to load'}\n`);
205+
await appendText(editor, `OS certificates: ${Array.isArray(osCerts) ? certsInfo(osCerts).lengths : `Error: ${collectErrorMessages(osCerts.error)}`}\n`);
180206
await appendText(editor, `\n`);
181207
}
182208

@@ -232,14 +258,11 @@ async function probeProxy(editor: vscode.TextEditor, url: string) {
232258
if (proxyAgent?.loadSystemCertificates && probeProxyURL?.startsWith('https:')) {
233259
const tlsOrig: typeof tls | undefined = (tls as any).__vscodeOriginal;
234260
if (tlsOrig) {
235-
await appendText(editor, `- TLS: `);
236261
const osCertificates = await loadSystemCertificates();
237-
if (!osCertificates) {
238-
await appendText(editor, `(failed to load system certificates) `);
239-
}
262+
await appendText(editor, `- TLS${!Array.isArray(osCertificates) ? ` (errors loading certificates)` : ''}: `);
240263
const start = Date.now();
241264
try {
242-
const result = await Promise.race([tlsConnect(tlsOrig, probeProxyURL, [...tls.rootCertificates, ...(osCertificates || [])]), timeout(timeoutSeconds * 1000)]);
265+
const result = await Promise.race([tlsConnect(tlsOrig, probeProxyURL, [...tls.rootCertificates, ...(Array.isArray(osCertificates) ? osCertificates : [])]), timeout(timeoutSeconds * 1000)]);
243266
if (result !== 'timeout') {
244267
await appendText(editor, `${result} (${Date.now() - start} ms)\n`);
245268
} else {
@@ -286,8 +309,8 @@ async function probeUrlWithNodeModules(editor: vscode.TextEditor, url: string, r
286309
await appendText(editor, `- Proxy-Authenticate: ${res.headers['proxy-authenticate']}\n`);
287310
}
288311
if (cert) {
289-
const uniqCerts = await getAllCaCertificates();
290-
await appendText(editor, `Certificate chain:\n`);
312+
const { uniqCerts, errors } = await getAllCaCertificates();
313+
await appendText(editor, `Certificate chain${errors.length ? ` (errors loading OS certificates: ${errors.length})` : ''}:\n`);
291314
let hasExpired = false;
292315
let current = cert;
293316
const allLocalRoots: typeof uniqCerts = [];
@@ -425,14 +448,17 @@ function getNodeFetchWithH2(): typeof globalThis.fetch {
425448

426449
async function getAllCaCertificates() {
427450
const osCerts = await loadSystemCertificates();
451+
const errors: any[] = [];
428452
const certMap = new Map<string, { from: string[]; pem: string; cert: crypto.X509Certificate; }>();
429453
for (const pem of tls.rootCertificates) {
430454
const cert = tryParseCertificate(pem);
431455
if (cert instanceof crypto.X509Certificate) {
432456
certMap.set(cert.fingerprint512, { from: ['built-in'], pem, cert });
457+
} else {
458+
errors.push(cert.error);
433459
}
434460
}
435-
if (osCerts) {
461+
if (Array.isArray(osCerts)) {
436462
for (const pem of osCerts) {
437463
const cert = tryParseCertificate(pem);
438464
if (cert instanceof crypto.X509Certificate) {
@@ -444,17 +470,24 @@ async function getAllCaCertificates() {
444470
} else {
445471
certMap.set(cert.fingerprint512, { from: ['OS'], pem, cert });
446472
}
473+
} else {
474+
errors.push(cert.error);
447475
}
448476
}
477+
} else {
478+
errors.push(osCerts.error);
449479
}
450-
return [...certMap.values()];
480+
return {
481+
uniqCerts: [...certMap.values()],
482+
errors,
483+
};
451484
}
452485

453486
function tryParseCertificate(pem: string) {
454487
try {
455488
return new crypto.X509Certificate(pem);
456-
} catch (err) {
457-
return err;
489+
} catch (error) {
490+
return { error };
458491
}
459492
}
460493

@@ -568,16 +601,23 @@ function loadVSCodeModule<T>(moduleName: string): T | undefined {
568601
return undefined;
569602
}
570603

571-
async function loadSystemCertificates(loadSystemCertificatesFromNode = vscode.workspace.getConfiguration('http').get<boolean>('systemCertificatesNode')): Promise<string[] | undefined> {
604+
function loadSystemCertificatesNode(): string[] | { error: any } | undefined {
605+
try {
606+
return tls.getCACertificates?.('system');
607+
} catch (error) {
608+
return { error };
609+
}
610+
}
611+
612+
async function loadSystemCertificates(loadSystemCertificatesFromNode = vscode.workspace.getConfiguration('http').get<boolean>('systemCertificatesNode')): Promise<string[] | { error: any }> {
572613
try {
573614
const certificates = await proxyAgent?.loadSystemCertificates({
574615
loadSystemCertificatesFromNode: () => loadSystemCertificatesFromNode,
575616
log: console
576617
});
577-
return Array.isArray(certificates) ? certificates : undefined;
578-
} catch (err) {
579-
console.error(err);
580-
return undefined;
618+
return Array.isArray(certificates) ? certificates : { error: 'Was undefined' };
619+
} catch (error) {
620+
return { error };
581621
}
582622
}
583623

@@ -644,7 +684,7 @@ function publicKeyHash(current: crypto.X509Certificate | tls.DetailedPeerCertifi
644684
try {
645685
publicKey = current.publicKey.export({ type: 'spki', format: 'der' });
646686
} catch (err) {
647-
return err.message;
687+
return err.message as string || 'Error exporting public key';
648688
}
649689
} else if (current.pubkey) {
650690
publicKey = current.pubkey;
@@ -663,7 +703,7 @@ function certsInfo(certs: readonly string[]) {
663703
if (cert instanceof crypto.X509Certificate) {
664704
unique.set(cert.fingerprint512, cert);
665705
} else {
666-
errors.push(cert);
706+
errors.push(cert.error);
667707
}
668708
}
669709
const lengths = [`${certs.length} certs`];

0 commit comments

Comments
 (0)