@@ -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/
248264const https = require (' node:https' );
249265const fs = require (' node:fs' );
250266
251267const 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
256272https .createServer (options, (req , res ) => {
@@ -261,12 +277,27 @@ https.createServer(options, (req, res) => {
261277
262278Or
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
265296const https = require (' node:https' );
266297const fs = require (' node:fs' );
267298
268299const 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.
303348string, it is automatically parsed with [ ` new URL() ` ] [ ] . If it is a [ ` URL ` ] [ ]
304349object, 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
307369const https = require (' node:https' );
308370
309371https .get (' https://encrypted.google.com/' , (res ) => {
@@ -394,7 +456,33 @@ object, it will be automatically converted to an ordinary `options` object.
394456class. The ` ClientRequest ` instance is a writable stream. If one needs to
395457upload 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
398486const https = require (' node:https' );
399487
400488const 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};
433521options .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) => {
468556Example 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
472633const tls = require (' node:tls' );
473634const https = require (' node:https' );
474635const 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);
530691const 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
548707Subject 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=
557719All OK. Server matched our pinned cert or public key
558720statusCode: 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