1# HTTPS 2 3<!--introduced_in=v0.10.0--> 4 5> Stability: 2 - Stable 6 7<!-- source_link=lib/https.js --> 8 9HTTPS is the HTTP protocol over TLS/SSL. In Node.js this is implemented as a 10separate module. 11 12## Determining if crypto support is unavailable 13 14It is possible for Node.js to be built without including support for the 15`node:crypto` module. In such cases, attempting to `import` from `https` or 16calling `require('node:https')` will result in an error being thrown. 17 18When using CommonJS, the error thrown can be caught using try/catch: 19 20<!-- eslint-skip --> 21 22```cjs 23let https; 24try { 25 https = require('node:https'); 26} catch (err) { 27 console.error('https support is disabled!'); 28} 29``` 30 31When using the lexical ESM `import` keyword, the error can only be 32caught if a handler for `process.on('uncaughtException')` is registered 33_before_ any attempt to load the module is made (using, for instance, 34a preload module). 35 36When using ESM, if there is a chance that the code may be run on a build 37of Node.js where crypto support is not enabled, consider using the 38[`import()`][] function instead of the lexical `import` keyword: 39 40```mjs 41let https; 42try { 43 https = await import('node:https'); 44} catch (err) { 45 console.error('https support is disabled!'); 46} 47``` 48 49## Class: `https.Agent` 50 51<!-- YAML 52added: v0.4.5 53changes: 54 - version: v5.3.0 55 pr-url: https://github.com/nodejs/node/pull/4252 56 description: support `0` `maxCachedSessions` to disable TLS session caching. 57 - version: v2.5.0 58 pr-url: https://github.com/nodejs/node/pull/2228 59 description: parameter `maxCachedSessions` added to `options` for TLS 60 sessions reuse. 61--> 62 63An [`Agent`][] object for HTTPS similar to [`http.Agent`][]. See 64[`https.request()`][] for more information. 65 66### `new Agent([options])` 67 68<!-- YAML 69changes: 70 - version: v12.5.0 71 pr-url: https://github.com/nodejs/node/pull/28209 72 description: do not automatically set servername if the target host was 73 specified using an IP address. 74--> 75 76* `options` {Object} Set of configurable options to set on the agent. 77 Can have the same fields as for [`http.Agent(options)`][], and 78 * `maxCachedSessions` {number} maximum number of TLS cached sessions. 79 Use `0` to disable TLS session caching. **Default:** `100`. 80 * `servername` {string} the value of 81 [Server Name Indication extension][sni wiki] to be sent to the server. Use 82 empty string `''` to disable sending the extension. 83 **Default:** host name of the target server, unless the target server 84 is specified using an IP address, in which case the default is `''` (no 85 extension). 86 87 See [`Session Resumption`][] for information about TLS session reuse. 88 89#### Event: `'keylog'` 90 91<!-- YAML 92added: 93 - v13.2.0 94 - v12.16.0 95--> 96 97* `line` {Buffer} Line of ASCII text, in NSS `SSLKEYLOGFILE` format. 98* `tlsSocket` {tls.TLSSocket} The `tls.TLSSocket` instance on which it was 99 generated. 100 101The `keylog` event is emitted when key material is generated or received by a 102connection managed by this agent (typically before handshake has completed, but 103not necessarily). This keying material can be stored for debugging, as it 104allows captured TLS traffic to be decrypted. It may be emitted multiple times 105for each socket. 106 107A typical use case is to append received lines to a common text file, which is 108later used by software (such as Wireshark) to decrypt the traffic: 109 110```js 111// ... 112https.globalAgent.on('keylog', (line, tlsSocket) => { 113 fs.appendFileSync('/tmp/ssl-keys.log', line, { mode: 0o600 }); 114}); 115``` 116 117## Class: `https.Server` 118 119<!-- YAML 120added: v0.3.4 121--> 122 123* Extends: {tls.Server} 124 125See [`http.Server`][] for more information. 126 127### `server.close([callback])` 128 129<!-- YAML 130added: v0.1.90 131--> 132 133* `callback` {Function} 134* Returns: {https.Server} 135 136See [`server.close()`][] in the `node:http` module. 137 138### `server.closeAllConnections()` 139 140<!-- YAML 141added: v18.2.0 142--> 143 144See [`server.closeAllConnections()`][] in the `node:http` module. 145 146### `server.closeIdleConnections()` 147 148<!-- YAML 149added: v18.2.0 150--> 151 152See [`server.closeIdleConnections()`][] in the `node:http` module. 153 154### `server.headersTimeout` 155 156<!-- YAML 157added: v11.3.0 158--> 159 160* {number} **Default:** `60000` 161 162See [`server.headersTimeout`][] in the `node:http` module. 163 164### `server.listen()` 165 166Starts the HTTPS server listening for encrypted connections. 167This method is identical to [`server.listen()`][] from [`net.Server`][]. 168 169### `server.maxHeadersCount` 170 171* {number} **Default:** `2000` 172 173See [`server.maxHeadersCount`][] in the `node:http` module. 174 175### `server.requestTimeout` 176 177<!-- YAML 178added: v14.11.0 179changes: 180 - version: v18.0.0 181 pr-url: https://github.com/nodejs/node/pull/41263 182 description: The default request timeout changed 183 from no timeout to 300s (5 minutes). 184--> 185 186* {number} **Default:** `300000` 187 188See [`server.requestTimeout`][] in the `node:http` module. 189 190### `server.setTimeout([msecs][, callback])` 191 192<!-- YAML 193added: v0.11.2 194--> 195 196* `msecs` {number} **Default:** `120000` (2 minutes) 197* `callback` {Function} 198* Returns: {https.Server} 199 200See [`server.setTimeout()`][] in the `node:http` module. 201 202### `server.timeout` 203 204<!-- YAML 205added: v0.11.2 206changes: 207 - version: v13.0.0 208 pr-url: https://github.com/nodejs/node/pull/27558 209 description: The default timeout changed from 120s to 0 (no timeout). 210--> 211 212* {number} **Default:** 0 (no timeout) 213 214See [`server.timeout`][] in the `node:http` module. 215 216### `server.keepAliveTimeout` 217 218<!-- YAML 219added: v8.0.0 220--> 221 222* {number} **Default:** `5000` (5 seconds) 223 224See [`server.keepAliveTimeout`][] in the `node:http` module. 225 226## `https.createServer([options][, requestListener])` 227 228<!-- YAML 229added: v0.3.4 230--> 231 232* `options` {Object} Accepts `options` from [`tls.createServer()`][], 233 [`tls.createSecureContext()`][] and [`http.createServer()`][]. 234* `requestListener` {Function} A listener to be added to the `'request'` event. 235* Returns: {https.Server} 236 237```js 238// curl -k https://localhost:8000/ 239const https = require('node:https'); 240const fs = require('node:fs'); 241 242const options = { 243 key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'), 244 cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem'), 245}; 246 247https.createServer(options, (req, res) => { 248 res.writeHead(200); 249 res.end('hello world\n'); 250}).listen(8000); 251``` 252 253Or 254 255```js 256const https = require('node:https'); 257const fs = require('node:fs'); 258 259const options = { 260 pfx: fs.readFileSync('test/fixtures/test_cert.pfx'), 261 passphrase: 'sample', 262}; 263 264https.createServer(options, (req, res) => { 265 res.writeHead(200); 266 res.end('hello world\n'); 267}).listen(8000); 268``` 269 270## `https.get(options[, callback])` 271 272## `https.get(url[, options][, callback])` 273 274<!-- YAML 275added: v0.3.6 276changes: 277 - version: v10.9.0 278 pr-url: https://github.com/nodejs/node/pull/21616 279 description: The `url` parameter can now be passed along with a separate 280 `options` object. 281 - version: v7.5.0 282 pr-url: https://github.com/nodejs/node/pull/10638 283 description: The `options` parameter can be a WHATWG `URL` object. 284--> 285 286* `url` {string | URL} 287* `options` {Object | string | URL} Accepts the same `options` as 288 [`https.request()`][], with the method set to GET by default. 289* `callback` {Function} 290 291Like [`http.get()`][] but for HTTPS. 292 293`options` can be an object, a string, or a [`URL`][] object. If `options` is a 294string, it is automatically parsed with [`new URL()`][]. If it is a [`URL`][] 295object, it will be automatically converted to an ordinary `options` object. 296 297```js 298const https = require('node:https'); 299 300https.get('https://encrypted.google.com/', (res) => { 301 console.log('statusCode:', res.statusCode); 302 console.log('headers:', res.headers); 303 304 res.on('data', (d) => { 305 process.stdout.write(d); 306 }); 307 308}).on('error', (e) => { 309 console.error(e); 310}); 311``` 312 313## `https.globalAgent` 314 315<!-- YAML 316added: v0.5.9 317--> 318 319Global instance of [`https.Agent`][] for all HTTPS client requests. 320 321## `https.request(options[, callback])` 322 323## `https.request(url[, options][, callback])` 324 325<!-- YAML 326added: v0.3.6 327changes: 328 - version: 329 - v16.7.0 330 - v14.18.0 331 pr-url: https://github.com/nodejs/node/pull/39310 332 description: When using a `URL` object parsed username 333 and password will now be properly URI decoded. 334 - version: 335 - v14.1.0 336 - v13.14.0 337 pr-url: https://github.com/nodejs/node/pull/32786 338 description: The `highWaterMark` option is accepted now. 339 - version: v10.9.0 340 pr-url: https://github.com/nodejs/node/pull/21616 341 description: The `url` parameter can now be passed along with a separate 342 `options` object. 343 - version: v9.3.0 344 pr-url: https://github.com/nodejs/node/pull/14903 345 description: The `options` parameter can now include `clientCertEngine`. 346 - version: v7.5.0 347 pr-url: https://github.com/nodejs/node/pull/10638 348 description: The `options` parameter can be a WHATWG `URL` object. 349--> 350 351* `url` {string | URL} 352* `options` {Object | string | URL} Accepts all `options` from 353 [`http.request()`][], with some differences in default values: 354 * `protocol` **Default:** `'https:'` 355 * `port` **Default:** `443` 356 * `agent` **Default:** `https.globalAgent` 357* `callback` {Function} 358* Returns: {http.ClientRequest} 359 360Makes a request to a secure web server. 361 362The following additional `options` from [`tls.connect()`][] are also accepted: 363`ca`, `cert`, `ciphers`, `clientCertEngine`, `crl`, `dhparam`, `ecdhCurve`, 364`honorCipherOrder`, `key`, `passphrase`, `pfx`, `rejectUnauthorized`, 365`secureOptions`, `secureProtocol`, `servername`, `sessionIdContext`, 366`highWaterMark`. 367 368`options` can be an object, a string, or a [`URL`][] object. If `options` is a 369string, it is automatically parsed with [`new URL()`][]. If it is a [`URL`][] 370object, it will be automatically converted to an ordinary `options` object. 371 372`https.request()` returns an instance of the [`http.ClientRequest`][] 373class. The `ClientRequest` instance is a writable stream. If one needs to 374upload a file with a POST request, then write to the `ClientRequest` object. 375 376```js 377const https = require('node:https'); 378 379const options = { 380 hostname: 'encrypted.google.com', 381 port: 443, 382 path: '/', 383 method: 'GET', 384}; 385 386const req = https.request(options, (res) => { 387 console.log('statusCode:', res.statusCode); 388 console.log('headers:', res.headers); 389 390 res.on('data', (d) => { 391 process.stdout.write(d); 392 }); 393}); 394 395req.on('error', (e) => { 396 console.error(e); 397}); 398req.end(); 399``` 400 401Example using options from [`tls.connect()`][]: 402 403```js 404const options = { 405 hostname: 'encrypted.google.com', 406 port: 443, 407 path: '/', 408 method: 'GET', 409 key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'), 410 cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem'), 411}; 412options.agent = new https.Agent(options); 413 414const req = https.request(options, (res) => { 415 // ... 416}); 417``` 418 419Alternatively, opt out of connection pooling by not using an [`Agent`][]. 420 421```js 422const options = { 423 hostname: 'encrypted.google.com', 424 port: 443, 425 path: '/', 426 method: 'GET', 427 key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'), 428 cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem'), 429 agent: false, 430}; 431 432const req = https.request(options, (res) => { 433 // ... 434}); 435``` 436 437Example using a [`URL`][] as `options`: 438 439```js 440const options = new URL('https://abc:xyz@example.com'); 441 442const req = https.request(options, (res) => { 443 // ... 444}); 445``` 446 447Example pinning on certificate fingerprint, or the public key (similar to 448`pin-sha256`): 449 450```js 451const tls = require('node:tls'); 452const https = require('node:https'); 453const crypto = require('node:crypto'); 454 455function sha256(s) { 456 return crypto.createHash('sha256').update(s).digest('base64'); 457} 458const options = { 459 hostname: 'github.com', 460 port: 443, 461 path: '/', 462 method: 'GET', 463 checkServerIdentity: function(host, cert) { 464 // Make sure the certificate is issued to the host we are connected to 465 const err = tls.checkServerIdentity(host, cert); 466 if (err) { 467 return err; 468 } 469 470 // Pin the public key, similar to HPKP pin-sha256 pinning 471 const pubkey256 = 'pL1+qb9HTMRZJmuC/bB/ZI9d302BYrrqiVuRyW+DGrU='; 472 if (sha256(cert.pubkey) !== pubkey256) { 473 const msg = 'Certificate verification error: ' + 474 `The public key of '${cert.subject.CN}' ` + 475 'does not match our pinned fingerprint'; 476 return new Error(msg); 477 } 478 479 // Pin the exact certificate, rather than the pub key 480 const cert256 = '25:FE:39:32:D9:63:8C:8A:FC:A1:9A:29:87:' + 481 'D8:3E:4C:1D:98:DB:71:E4:1A:48:03:98:EA:22:6A:BD:8B:93:16'; 482 if (cert.fingerprint256 !== cert256) { 483 const msg = 'Certificate verification error: ' + 484 `The certificate of '${cert.subject.CN}' ` + 485 'does not match our pinned fingerprint'; 486 return new Error(msg); 487 } 488 489 // This loop is informational only. 490 // Print the certificate and public key fingerprints of all certs in the 491 // chain. Its common to pin the public key of the issuer on the public 492 // internet, while pinning the public key of the service in sensitive 493 // environments. 494 do { 495 console.log('Subject Common Name:', cert.subject.CN); 496 console.log(' Certificate SHA256 fingerprint:', cert.fingerprint256); 497 498 hash = crypto.createHash('sha256'); 499 console.log(' Public key ping-sha256:', sha256(cert.pubkey)); 500 501 lastprint256 = cert.fingerprint256; 502 cert = cert.issuerCertificate; 503 } while (cert.fingerprint256 !== lastprint256); 504 505 }, 506}; 507 508options.agent = new https.Agent(options); 509const req = https.request(options, (res) => { 510 console.log('All OK. Server matched our pinned cert or public key'); 511 console.log('statusCode:', res.statusCode); 512 // Print the HPKP values 513 console.log('headers:', res.headers['public-key-pins']); 514 515 res.on('data', (d) => {}); 516}); 517 518req.on('error', (e) => { 519 console.error(e.message); 520}); 521req.end(); 522``` 523 524Outputs for example: 525 526```text 527Subject Common Name: github.com 528 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 529 Public key ping-sha256: pL1+qb9HTMRZJmuC/bB/ZI9d302BYrrqiVuRyW+DGrU= 530Subject Common Name: DigiCert SHA2 Extended Validation Server CA 531 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 532 Public key ping-sha256: RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho= 533Subject Common Name: DigiCert High Assurance EV Root CA 534 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 535 Public key ping-sha256: WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18= 536All OK. Server matched our pinned cert or public key 537statusCode: 200 538headers: 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 539``` 540 541[`Agent`]: #class-httpsagent 542[`Session Resumption`]: tls.md#session-resumption 543[`URL`]: url.md#the-whatwg-url-api 544[`http.Agent(options)`]: http.md#new-agentoptions 545[`http.Agent`]: http.md#class-httpagent 546[`http.ClientRequest`]: http.md#class-httpclientrequest 547[`http.Server`]: http.md#class-httpserver 548[`http.createServer()`]: http.md#httpcreateserveroptions-requestlistener 549[`http.get()`]: http.md#httpgetoptions-callback 550[`http.request()`]: http.md#httprequestoptions-callback 551[`https.Agent`]: #class-httpsagent 552[`https.request()`]: #httpsrequestoptions-callback 553[`import()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import 554[`net.Server`]: net.md#class-netserver 555[`new URL()`]: url.md#new-urlinput-base 556[`server.close()`]: http.md#serverclosecallback 557[`server.closeAllConnections()`]: http.md#servercloseallconnections 558[`server.closeIdleConnections()`]: http.md#servercloseidleconnections 559[`server.headersTimeout`]: http.md#serverheaderstimeout 560[`server.keepAliveTimeout`]: http.md#serverkeepalivetimeout 561[`server.listen()`]: net.md#serverlisten 562[`server.maxHeadersCount`]: http.md#servermaxheaderscount 563[`server.requestTimeout`]: http.md#serverrequesttimeout 564[`server.setTimeout()`]: http.md#serversettimeoutmsecs-callback 565[`server.timeout`]: http.md#servertimeout 566[`tls.connect()`]: tls.md#tlsconnectoptions-callback 567[`tls.createSecureContext()`]: tls.md#tlscreatesecurecontextoptions 568[`tls.createServer()`]: tls.md#tlscreateserveroptions-secureconnectionlistener 569[sni wiki]: https://en.wikipedia.org/wiki/Server_Name_Indication 570