@@ -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 ) => {
@@ -396,7 +458,33 @@ object, it will be automatically converted to an ordinary `options` object.
396458class. The ` ClientRequest ` instance is a writable stream. If one needs to
397459upload a file with a POST request, then write to the ` ClientRequest ` object.
398460
399- ``` js
461+ ``` mjs
462+ import { request } from ' node:https' ;
463+ import process from ' node:process' ;
464+
465+ const options = {
466+ hostname: ' encrypted.google.com' ,
467+ port: 443 ,
468+ path: ' /' ,
469+ method: ' GET' ,
470+ };
471+
472+ const req = request (options, (res ) => {
473+ console .log (' statusCode:' , res .statusCode );
474+ console .log (' headers:' , res .headers );
475+
476+ res .on (' data' , (d ) => {
477+ process .stdout .write (d);
478+ });
479+ });
480+
481+ req .on (' error' , (e ) => {
482+ console .error (e);
483+ });
484+ req .end ();
485+ ```
486+
487+ ``` cjs
400488const https = require (' node:https' );
401489
402490const options = {
@@ -429,8 +517,8 @@ const options = {
429517 port: 443 ,
430518 path: ' /' ,
431519 method: ' GET' ,
432- key: fs .readFileSync (' test/fixtures/keys/agent2 -key.pem' ),
433- cert: fs .readFileSync (' test/fixtures/keys/agent2-cert .pem' ),
520+ key: fs .readFileSync (' private -key.pem' ),
521+ cert: fs .readFileSync (' certificate .pem' ),
434522};
435523options .agent = new https.Agent (options);
436524
@@ -447,8 +535,8 @@ const options = {
447535 port: 443 ,
448536 path: ' /' ,
449537 method: ' GET' ,
450- key: fs .readFileSync (' test/fixtures/keys/agent2 -key.pem' ),
451- cert: fs .readFileSync (' test/fixtures/keys/agent2-cert .pem' ),
538+ key: fs .readFileSync (' private -key.pem' ),
539+ cert: fs .readFileSync (' certificate .pem' ),
452540 agent: false ,
453541};
454542
@@ -470,7 +558,80 @@ const req = https.request(options, (res) => {
470558Example pinning on certificate fingerprint, or the public key (similar to
471559` pin-sha256 ` ):
472560
473- ``` js
561+ ``` mjs
562+ import { checkServerIdentity } from ' node:tls' ;
563+ import { Agent , request } from ' node:https' ;
564+ import { createHash } from ' node:crypto' ;
565+
566+ function sha256 (s ) {
567+ return createHash (' sha256' ).update (s).digest (' base64' );
568+ }
569+ const options = {
570+ hostname: ' github.com' ,
571+ port: 443 ,
572+ path: ' /' ,
573+ method: ' GET' ,
574+ checkServerIdentity : function (host , cert ) {
575+ // Make sure the certificate is issued to the host we are connected to
576+ const err = checkServerIdentity (host, cert);
577+ if (err) {
578+ return err;
579+ }
580+
581+ // Pin the public key, similar to HPKP pin-sha256 pinning
582+ const pubkey256 = ' SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8=' ;
583+ if (sha256 (cert .pubkey ) !== pubkey256) {
584+ const msg = ' Certificate verification error: ' +
585+ ` The public key of '${ cert .subject .CN } ' ` +
586+ ' does not match our pinned fingerprint' ;
587+ return new Error (msg);
588+ }
589+
590+ // Pin the exact certificate, rather than the pub key
591+ const cert256 = ' FD:6E:9B:0E:F3:98:BC:D9:04:C3:B2:EC:16:7A:7B:' +
592+ ' 0F:DA:72:01:C9:03:C5:3A:6A:6A:E5:D0:41:43:63:EF:65' ;
593+ if (cert .fingerprint256 !== cert256) {
594+ const msg = ' Certificate verification error: ' +
595+ ` The certificate of '${ cert .subject .CN } ' ` +
596+ ' does not match our pinned fingerprint' ;
597+ return new Error (msg);
598+ }
599+
600+ // This loop is informational only.
601+ // Print the certificate and public key fingerprints of all certs in the
602+ // chain. Its common to pin the public key of the issuer on the public
603+ // internet, while pinning the public key of the service in sensitive
604+ // environments.
605+ let lastprint256;
606+ do {
607+ console .log (' Subject Common Name:' , cert .subject .CN );
608+ console .log (' Certificate SHA256 fingerprint:' , cert .fingerprint256 );
609+
610+ const hash = createHash (' sha256' );
611+ console .log (' Public key ping-sha256:' , sha256 (cert .pubkey ));
612+
613+ lastprint256 = cert .fingerprint256 ;
614+ cert = cert .issuerCertificate ;
615+ } while (cert .fingerprint256 !== lastprint256);
616+
617+ },
618+ };
619+
620+ options .agent = new Agent (options);
621+ const req = request (options, (res ) => {
622+ console .log (' All OK. Server matched our pinned cert or public key' );
623+ console .log (' statusCode:' , res .statusCode );
624+
625+ res .on (' data' , (d ) => {});
626+ });
627+
628+ req .on (' error' , (e ) => {
629+ console .error (e .message );
630+ });
631+ req .end ();
632+ ```
633+
634+ ``` cjs
474635const tls = require (' node:tls' );
475636const https = require (' node:https' );
476637const crypto = require (' node:crypto' );
@@ -491,7 +652,7 @@ const options = {
491652 }
492653
493654 // Pin the public key, similar to HPKP pin-sha256 pinning
494- const pubkey256 = ' pL1+qb9HTMRZJmuC/bB/ZI9d302BYrrqiVuRyW+DGrU =' ;
655+ const pubkey256 = ' SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8 =' ;
495656 if (sha256 (cert .pubkey ) !== pubkey256) {
496657 const msg = ' Certificate verification error: ' +
497658 ` The public key of '${ cert .subject .CN } ' ` +
@@ -500,8 +661,8 @@ const options = {
500661 }
501662
502663 // Pin the exact certificate, rather than the pub key
503- const cert256 = ' 25:FE:39:32:D9:63:8C:8A:FC:A1:9A:29:87 :' +
504- ' D8:3E:4C:1D:98:DB:71:E4:1A:48:03:98:EA:22:6A:BD:8B:93:16 ' ;
664+ const cert256 = ' FD:6E:9B:0E:F3:98:BC:D9:04:C3:B2:EC:16:7A:7B :' +
665+ ' 0F:DA:72:01:C9:03:C5:3A:6A:6A:E5:D0:41:43:63:EF:65 ' ;
505666 if (cert .fingerprint256 !== cert256) {
506667 const msg = ' Certificate verification error: ' +
507668 ` The certificate of '${ cert .subject .CN } ' ` +
@@ -532,8 +693,6 @@ options.agent = new https.Agent(options);
532693const req = https .request (options, (res ) => {
533694 console .log (' All OK. Server matched our pinned cert or public key' );
534695 console .log (' statusCode:' , res .statusCode );
535- // Print the HPKP values
536- console .log (' headers:' , res .headers [' public-key-pins' ]);
537696
538697 res .on (' data' , (d ) => {});
539698});
@@ -548,17 +707,19 @@ Outputs for example:
548707
549708``` text
550709Subject Common Name: github.com
551- 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
552- Public key ping-sha256: pL1+qb9HTMRZJmuC/bB/ZI9d302BYrrqiVuRyW+DGrU=
553- Subject Common Name: DigiCert SHA2 Extended Validation Server CA
554- 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
555- Public key ping-sha256: RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho=
556- Subject Common Name: DigiCert High Assurance EV Root CA
557- 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
558- Public key ping-sha256: WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=
710+ 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
711+ Public key ping-sha256: SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8=
712+ Subject Common Name: Sectigo ECC Domain Validation Secure Server CA
713+ 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
714+ Public key ping-sha256: Eep0p/AsSa9lFUH6KT2UY+9s1Z8v7voAPkQ4fGknZ2g=
715+ Subject Common Name: USERTrust ECC Certification Authority
716+ 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
717+ Public key ping-sha256: UJM2FOhG9aTNY0Pg4hgqjNzZ/lQBiMGRxPD5Y2/e0bw=
718+ Subject Common Name: AAA Certificate Services
719+ 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
720+ Public key ping-sha256: vRU+17BDT2iGsXvOi76E7TQMcTLXAqj0+jGPdW7L1vM=
559721All OK. Server matched our pinned cert or public key
560722statusCode: 200
561- 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
562723```
563724
564725[ `Agent` ] : #class-httpsagent
0 commit comments