Skip to content

Commit cdc6713

Browse files
mfdebiantargos
authored andcommitted
doc: add esm examples to node:https
PR-URL: #54399 Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Trivikram Kamat <[email protected]>
1 parent 4f421b3 commit cdc6713

File tree

1 file changed

+187
-26
lines changed

1 file changed

+187
-26
lines changed

doc/api/https.md

+187-26
Original file line numberDiff line numberDiff line change
@@ -243,14 +243,30 @@ added: v0.3.4
243243
* `requestListener` {Function} A listener to be added to the `'request'` event.
244244
* Returns: {https.Server}
245245

246-
```js
246+
```mjs
247+
// curl -k https://localhost:8000/
248+
import { createServer } from 'node:https';
249+
import { readFileSync } from 'node:fs';
250+
251+
const options = {
252+
key: readFileSync('private-key.pem'),
253+
cert: readFileSync('certificate.pem'),
254+
};
255+
256+
createServer(options, (req, res) => {
257+
res.writeHead(200);
258+
res.end('hello world\n');
259+
}).listen(8000);
260+
```
261+
262+
```cjs
247263
// curl -k https://localhost:8000/
248264
const https = require('node:https');
249265
const fs = require('node:fs');
250266

251267
const options = {
252-
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
253-
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem'),
268+
key: fs.readFileSync('private-key.pem'),
269+
cert: fs.readFileSync('certificate.pem'),
254270
};
255271

256272
https.createServer(options, (req, res) => {
@@ -261,12 +277,27 @@ https.createServer(options, (req, res) => {
261277

262278
Or
263279

264-
```js
280+
```mjs
281+
import { createServer } from 'node:https';
282+
import { readFileSync } from 'node:fs';
283+
284+
const options = {
285+
pfx: readFileSync('test_cert.pfx'),
286+
passphrase: 'sample',
287+
};
288+
289+
createServer(options, (req, res) => {
290+
res.writeHead(200);
291+
res.end('hello world\n');
292+
}).listen(8000);
293+
```
294+
295+
```cjs
265296
const https = require('node:https');
266297
const fs = require('node:fs');
267298

268299
const options = {
269-
pfx: fs.readFileSync('test/fixtures/test_cert.pfx'),
300+
pfx: fs.readFileSync('test_cert.pfx'),
270301
passphrase: 'sample',
271302
};
272303

@@ -276,6 +307,20 @@ https.createServer(options, (req, res) => {
276307
}).listen(8000);
277308
```
278309

310+
To generate the certificate and key for this example, run:
311+
312+
```bash
313+
openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \
314+
-keyout private-key.pem -out certificate.pem
315+
```
316+
317+
Then, to generate the `pfx` certificate for this example, run:
318+
319+
```bash
320+
openssl pkcs12 -certpbe AES-256-CBC -export -out test_cert.pfx \
321+
-inkey private-key.pem -in certificate.pem -passout pass:sample
322+
```
323+
279324
## `https.get(options[, callback])`
280325

281326
## `https.get(url[, options][, callback])`
@@ -303,7 +348,24 @@ Like [`http.get()`][] but for HTTPS.
303348
string, it is automatically parsed with [`new URL()`][]. If it is a [`URL`][]
304349
object, it will be automatically converted to an ordinary `options` object.
305350

306-
```js
351+
```mjs
352+
import { get } from 'node:https';
353+
import process from 'node:process';
354+
355+
get('https://encrypted.google.com/', (res) => {
356+
console.log('statusCode:', res.statusCode);
357+
console.log('headers:', res.headers);
358+
359+
res.on('data', (d) => {
360+
process.stdout.write(d);
361+
});
362+
363+
}).on('error', (e) => {
364+
console.error(e);
365+
});
366+
```
367+
368+
```cjs
307369
const https = require('node:https');
308370

309371
https.get('https://encrypted.google.com/', (res) => {
@@ -394,7 +456,33 @@ object, it will be automatically converted to an ordinary `options` object.
394456
class. The `ClientRequest` instance is a writable stream. If one needs to
395457
upload a file with a POST request, then write to the `ClientRequest` object.
396458

397-
```js
459+
```mjs
460+
import { request } from 'node:https';
461+
import process from 'node:process';
462+
463+
const options = {
464+
hostname: 'encrypted.google.com',
465+
port: 443,
466+
path: '/',
467+
method: 'GET',
468+
};
469+
470+
const req = request(options, (res) => {
471+
console.log('statusCode:', res.statusCode);
472+
console.log('headers:', res.headers);
473+
474+
res.on('data', (d) => {
475+
process.stdout.write(d);
476+
});
477+
});
478+
479+
req.on('error', (e) => {
480+
console.error(e);
481+
});
482+
req.end();
483+
```
484+
485+
```cjs
398486
const https = require('node:https');
399487

400488
const options = {
@@ -427,8 +515,8 @@ const options = {
427515
port: 443,
428516
path: '/',
429517
method: 'GET',
430-
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
431-
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem'),
518+
key: fs.readFileSync('private-key.pem'),
519+
cert: fs.readFileSync('certificate.pem'),
432520
};
433521
options.agent = new https.Agent(options);
434522

@@ -445,8 +533,8 @@ const options = {
445533
port: 443,
446534
path: '/',
447535
method: 'GET',
448-
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
449-
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem'),
536+
key: fs.readFileSync('private-key.pem'),
537+
cert: fs.readFileSync('certificate.pem'),
450538
agent: false,
451539
};
452540

@@ -468,7 +556,80 @@ const req = https.request(options, (res) => {
468556
Example pinning on certificate fingerprint, or the public key (similar to
469557
`pin-sha256`):
470558

471-
```js
559+
```mjs
560+
import { checkServerIdentity } from 'node:tls';
561+
import { Agent, request } from 'node:https';
562+
import { createHash } from 'node:crypto';
563+
564+
function sha256(s) {
565+
return createHash('sha256').update(s).digest('base64');
566+
}
567+
const options = {
568+
hostname: 'github.com',
569+
port: 443,
570+
path: '/',
571+
method: 'GET',
572+
checkServerIdentity: function(host, cert) {
573+
// Make sure the certificate is issued to the host we are connected to
574+
const err = checkServerIdentity(host, cert);
575+
if (err) {
576+
return err;
577+
}
578+
579+
// Pin the public key, similar to HPKP pin-sha256 pinning
580+
const pubkey256 = 'SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8=';
581+
if (sha256(cert.pubkey) !== pubkey256) {
582+
const msg = 'Certificate verification error: ' +
583+
`The public key of '${cert.subject.CN}' ` +
584+
'does not match our pinned fingerprint';
585+
return new Error(msg);
586+
}
587+
588+
// Pin the exact certificate, rather than the pub key
589+
const cert256 = 'FD:6E:9B:0E:F3:98:BC:D9:04:C3:B2:EC:16:7A:7B:' +
590+
'0F:DA:72:01:C9:03:C5:3A:6A:6A:E5:D0:41:43:63:EF:65';
591+
if (cert.fingerprint256 !== cert256) {
592+
const msg = 'Certificate verification error: ' +
593+
`The certificate of '${cert.subject.CN}' ` +
594+
'does not match our pinned fingerprint';
595+
return new Error(msg);
596+
}
597+
598+
// This loop is informational only.
599+
// Print the certificate and public key fingerprints of all certs in the
600+
// chain. Its common to pin the public key of the issuer on the public
601+
// internet, while pinning the public key of the service in sensitive
602+
// environments.
603+
let lastprint256;
604+
do {
605+
console.log('Subject Common Name:', cert.subject.CN);
606+
console.log(' Certificate SHA256 fingerprint:', cert.fingerprint256);
607+
608+
const hash = createHash('sha256');
609+
console.log(' Public key ping-sha256:', sha256(cert.pubkey));
610+
611+
lastprint256 = cert.fingerprint256;
612+
cert = cert.issuerCertificate;
613+
} while (cert.fingerprint256 !== lastprint256);
614+
615+
},
616+
};
617+
618+
options.agent = new Agent(options);
619+
const req = request(options, (res) => {
620+
console.log('All OK. Server matched our pinned cert or public key');
621+
console.log('statusCode:', res.statusCode);
622+
623+
res.on('data', (d) => {});
624+
});
625+
626+
req.on('error', (e) => {
627+
console.error(e.message);
628+
});
629+
req.end();
630+
```
631+
632+
```cjs
472633
const tls = require('node:tls');
473634
const https = require('node:https');
474635
const crypto = require('node:crypto');
@@ -489,7 +650,7 @@ const options = {
489650
}
490651

491652
// Pin the public key, similar to HPKP pin-sha256 pinning
492-
const pubkey256 = 'pL1+qb9HTMRZJmuC/bB/ZI9d302BYrrqiVuRyW+DGrU=';
653+
const pubkey256 = 'SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8=';
493654
if (sha256(cert.pubkey) !== pubkey256) {
494655
const msg = 'Certificate verification error: ' +
495656
`The public key of '${cert.subject.CN}' ` +
@@ -498,8 +659,8 @@ const options = {
498659
}
499660

500661
// Pin the exact certificate, rather than the pub key
501-
const cert256 = '25:FE:39:32:D9:63:8C:8A:FC:A1:9A:29:87:' +
502-
'D8:3E:4C:1D:98:DB:71:E4:1A:48:03:98:EA:22:6A:BD:8B:93:16';
662+
const cert256 = 'FD:6E:9B:0E:F3:98:BC:D9:04:C3:B2:EC:16:7A:7B:' +
663+
'0F:DA:72:01:C9:03:C5:3A:6A:6A:E5:D0:41:43:63:EF:65';
503664
if (cert.fingerprint256 !== cert256) {
504665
const msg = 'Certificate verification error: ' +
505666
`The certificate of '${cert.subject.CN}' ` +
@@ -530,8 +691,6 @@ options.agent = new https.Agent(options);
530691
const req = https.request(options, (res) => {
531692
console.log('All OK. Server matched our pinned cert or public key');
532693
console.log('statusCode:', res.statusCode);
533-
// Print the HPKP values
534-
console.log('headers:', res.headers['public-key-pins']);
535694

536695
res.on('data', (d) => {});
537696
});
@@ -546,17 +705,19 @@ Outputs for example:
546705

547706
```text
548707
Subject Common Name: github.com
549-
Certificate SHA256 fingerprint: 25:FE:39:32:D9:63:8C:8A:FC:A1:9A:29:87:D8:3E:4C:1D:98:DB:71:E4:1A:48:03:98:EA:22:6A:BD:8B:93:16
550-
Public key ping-sha256: pL1+qb9HTMRZJmuC/bB/ZI9d302BYrrqiVuRyW+DGrU=
551-
Subject Common Name: DigiCert SHA2 Extended Validation Server CA
552-
Certificate SHA256 fingerprint: 40:3E:06:2A:26:53:05:91:13:28:5B:AF:80:A0:D4:AE:42:2C:84:8C:9F:78:FA:D0:1F:C9:4B:C5:B8:7F:EF:1A
553-
Public key ping-sha256: RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho=
554-
Subject Common Name: DigiCert High Assurance EV Root CA
555-
Certificate SHA256 fingerprint: 74:31:E5:F4:C3:C1:CE:46:90:77:4F:0B:61:E0:54:40:88:3B:A9:A0:1E:D0:0B:A6:AB:D7:80:6E:D3:B1:18:CF
556-
Public key ping-sha256: WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=
708+
Certificate SHA256 fingerprint: FD:6E:9B:0E:F3:98:BC:D9:04:C3:B2:EC:16:7A:7B:0F:DA:72:01:C9:03:C5:3A:6A:6A:E5:D0:41:43:63:EF:65
709+
Public key ping-sha256: SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8=
710+
Subject Common Name: Sectigo ECC Domain Validation Secure Server CA
711+
Certificate SHA256 fingerprint: 61:E9:73:75:E9:F6:DA:98:2F:F5:C1:9E:2F:94:E6:6C:4E:35:B6:83:7C:E3:B9:14:D2:24:5C:7F:5F:65:82:5F
712+
Public key ping-sha256: Eep0p/AsSa9lFUH6KT2UY+9s1Z8v7voAPkQ4fGknZ2g=
713+
Subject Common Name: USERTrust ECC Certification Authority
714+
Certificate SHA256 fingerprint: A6:CF:64:DB:B4:C8:D5:FD:19:CE:48:89:60:68:DB:03:B5:33:A8:D1:33:6C:62:56:A8:7D:00:CB:B3:DE:F3:EA
715+
Public key ping-sha256: UJM2FOhG9aTNY0Pg4hgqjNzZ/lQBiMGRxPD5Y2/e0bw=
716+
Subject Common Name: AAA Certificate Services
717+
Certificate SHA256 fingerprint: D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4
718+
Public key ping-sha256: vRU+17BDT2iGsXvOi76E7TQMcTLXAqj0+jGPdW7L1vM=
557719
All OK. Server matched our pinned cert or public key
558720
statusCode: 200
559-
headers: max-age=0; pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; pin-sha256="RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho="; pin-sha256="k2v657xBsOVe1PQRwOsHsw3bsGT2VzIqz5K+59sNQws="; pin-sha256="K87oWBWM9UZfyddvDfoxL+8lpNyoUB2ptGtn0fv6G2Q="; pin-sha256="IQBnNBEiFuhj+8x6X8XLgh01V9Ic5/V3IRQLNFFc7v4="; pin-sha256="iie1VXtL7HzAMF+/PVPR9xzT80kQxdZeJ+zduCB3uj0="; pin-sha256="LvRiGEjRqfzurezaWuj8Wie2gyHMrW5Q06LspMnox7A="; includeSubDomains
560721
```
561722

562723
[`Agent`]: #class-httpsagent

0 commit comments

Comments
 (0)