Skip to content

HTTPS

[Stabile: 2 - Stabile]

Stabile: 2 Stabilità: 2 - Stabile

Codice sorgente: lib/https.js

HTTPS è il protocollo HTTP su TLS/SSL. In Node.js, questo è implementato come un modulo separato.

Determinare se il supporto per la crittografia non è disponibile

È possibile che Node.js venga compilato senza includere il supporto per il modulo node:crypto. In tali casi, il tentativo di importare da https o di chiamare require('node:https') comporterà la generazione di un errore.

Quando si utilizza CommonJS, l'errore generato può essere intercettato utilizzando try/catch:

js
let https
try {
  https = require('node:https')
} catch (err) {
  console.error('Il supporto HTTPS è disabilitato!')
}

Quando si utilizza la parola chiave lessicale ESM import, l'errore può essere intercettato solo se viene registrato un gestore per process.on('uncaughtException') prima di qualsiasi tentativo di caricare il modulo (utilizzando, ad esempio, un modulo preload).

Quando si utilizza ESM, se esiste la possibilità che il codice venga eseguito su una build di Node.js in cui il supporto per la crittografia non è abilitato, si consiglia di utilizzare la funzione import() invece della parola chiave lessicale import:

js
let https
try {
  https = await import('node:https')
} catch (err) {
  console.error('Il supporto HTTPS è disabilitato!')
}

Classe: https.Agent

[Cronologia]

VersioneModifiche
v5.3.0supporto 0 maxCachedSessions per disabilitare la memorizzazione nella cache delle sessioni TLS.
v2.5.0parametro maxCachedSessions aggiunto a options per il riutilizzo delle sessioni TLS.
v0.4.5Aggiunto in: v0.4.5

Un oggetto Agent per HTTPS simile a http.Agent. Vedere https.request() per ulteriori informazioni.

new Agent([options])

[Cronologia]

VersioneModifiche
v12.5.0non impostare automaticamente servername se l'host di destinazione è stato specificato utilizzando un indirizzo IP.
  • options <Object> Insieme di opzioni configurabili da impostare sull'agente. Può avere gli stessi campi di http.Agent(options), e
    • maxCachedSessions <number> numero massimo di sessioni TLS memorizzate nella cache. Utilizzare 0 per disabilitare la memorizzazione nella cache delle sessioni TLS. Predefinito: 100.
    • servername <string> il valore dell'estensione Server Name Indication da inviare al server. Utilizzare una stringa vuota '' per disabilitare l'invio dell'estensione. Predefinito: nome host del server di destinazione, a meno che il server di destinazione non venga specificato utilizzando un indirizzo IP, nel qual caso il valore predefinito è '' (nessuna estensione). Vedere Ripresa sessione per informazioni sul riutilizzo delle sessioni TLS.

Evento: 'keylog'

Aggiunto in: v13.2.0, v12.16.0

  • line <Buffer> Riga di testo ASCII, nel formato NSS SSLKEYLOGFILE.
  • tlsSocket <tls.TLSSocket> L'istanza di tls.TLSSocket sulla quale è stato generato.

L'evento keylog viene emesso quando il materiale di crittografia viene generato o ricevuto da una connessione gestita da questo agent (tipicamente prima che l'handshake sia completato, ma non necessariamente). Questo materiale di crittografia può essere memorizzato per il debug, poiché consente di decrittografare il traffico TLS catturato. Può essere emesso più volte per ogni socket.

Un tipico caso d'uso è aggiungere le righe ricevute a un file di testo comune, che viene successivamente utilizzato da software (come Wireshark) per decrittografare il traffico:

js
// ...
https.globalAgent.on('keylog', (line, tlsSocket) => {
  fs.appendFileSync('/tmp/ssl-keys.log', line, { mode: 0o600 })
})

Classe: https.Server

Aggiunto in: v0.3.4

Vedi http.Server per maggiori informazioni.

server.close([callback])

Aggiunto in: v0.1.90

Vedi server.close() nel modulo node:http.

server[Symbol.asyncDispose]()

Aggiunto in: v20.4.0

[Stabile: 1 - Sperimentale]

Stabile: 1 Stabilità: 1 - Sperimentale

Chiama server.close() e restituisce una promise che si risolve quando il server si è chiuso.

server.closeAllConnections()

Aggiunto in: v18.2.0

Vedi server.closeAllConnections() nel modulo node:http.

server.closeIdleConnections()

Aggiunto in: v18.2.0

Vedi server.closeIdleConnections() nel modulo node:http.

server.headersTimeout

Aggiunto in: v11.3.0

Vedi server.headersTimeout nel modulo node:http.

server.listen()

Avvia il server HTTPS in ascolto di connessioni crittografate. Questo metodo è identico a server.listen() da net.Server.

server.maxHeadersCount

Vedi server.maxHeadersCount nel modulo node:http.

server.requestTimeout

[Cronologia]

VersioneModifiche
v18.0.0Il timeout predefinito della richiesta è cambiato da nessun timeout a 300 secondi (5 minuti).
v14.11.0Aggiunto in: v14.11.0

Vedi server.requestTimeout nel modulo node:http.

server.setTimeout([msecs][, callback])

Aggiunto in: v0.11.2

Vedi server.setTimeout() nel modulo node:http.

server.timeout

[Cronologia]

VersioneModifiche
v13.0.0Il timeout predefinito è cambiato da 120 secondi a 0 (nessun timeout).
v0.11.2Aggiunto in: v0.11.2
  • <number> Predefinito: 0 (nessun timeout)

Vedi server.timeout nel modulo node:http.

server.keepAliveTimeout

Aggiunto in: v8.0.0

Vedi server.keepAliveTimeout nel modulo node:http.

https.createServer([options][, requestListener])

Aggiunto in: v0.3.4

js
// curl -k https://localhost:8000/
import { createServer } from 'node:https'
import { readFileSync } from 'node:fs'

const options = {
  key: readFileSync('private-key.pem'),
  cert: readFileSync('certificate.pem'),
}

createServer(options, (req, res) => {
  res.writeHead(200)
  res.end('hello world\n')
}).listen(8000)
js
// curl -k https://localhost:8000/
const https = require('node:https')
const fs = require('node:fs')

const options = {
  key: fs.readFileSync('private-key.pem'),
  cert: fs.readFileSync('certificate.pem'),
}

https
  .createServer(options, (req, res) => {
    res.writeHead(200)
    res.end('hello world\n')
  })
  .listen(8000)

Oppure

js
import { createServer } from 'node:https'
import { readFileSync } from 'node:fs'

const options = {
  pfx: readFileSync('test_cert.pfx'),
  passphrase: 'sample',
}

createServer(options, (req, res) => {
  res.writeHead(200)
  res.end('hello world\n')
}).listen(8000)
js
const https = require('node:https')
const fs = require('node:fs')

const options = {
  pfx: fs.readFileSync('test_cert.pfx'),
  passphrase: 'sample',
}

https
  .createServer(options, (req, res) => {
    res.writeHead(200)
    res.end('hello world\n')
  })
  .listen(8000)

Per generare il certificato e la chiave per questo esempio, eseguire:

bash
openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \
  -keyout private-key.pem -out certificate.pem

Quindi, per generare il certificato pfx per questo esempio, eseguire:

bash
openssl pkcs12 -certpbe AES-256-CBC -export -out test_cert.pfx \
  -inkey private-key.pem -in certificate.pem -passout pass:sample

https.get(options[, callback])

https.get(url[, options][, callback])

[Cronologia]

VersioneCambiamenti
v10.9.0Il parametro url ora può essere passato insieme a un oggetto options separato.
v7.5.0Il parametro options può essere un oggetto URL WHATWG.
v0.3.6Aggiunto in: v0.3.6

Come http.get() ma per HTTPS.

options può essere un oggetto, una stringa o un oggetto URL. Se options è una stringa, viene analizzata automaticamente con new URL(). Se è un oggetto URL, verrà automaticamente convertito in un normale oggetto options.

js
import { get } from 'node:https'
import process from 'node:process'

get('https://encrypted.google.com/', res => {
  console.log('statusCode:', res.statusCode)
  console.log('headers:', res.headers)

  res.on('data', d => {
    process.stdout.write(d)
  })
}).on('error', e => {
  console.error(e)
})
js
const https = require('node:https')

https
  .get('https://encrypted.google.com/', res => {
    console.log('statusCode:', res.statusCode)
    console.log('headers:', res.headers)

    res.on('data', d => {
      process.stdout.write(d)
    })
  })
  .on('error', e => {
    console.error(e)
  })

https.globalAgent

[Cronologia]

VersioneModifiche
v19.0.0L'agent ora utilizza HTTP Keep-Alive e un timeout di 5 secondi per impostazione predefinita.
v0.5.9Aggiunto in: v0.5.9

Istanza globale di https.Agent per tutte le richieste client HTTPS. Si discosta da una configurazione predefinita di https.Agent per avere keepAlive abilitato e un timeout di 5 secondi.

https.request(options[, callback])

https.request(url[, options][, callback])

[Cronologia]

VersioneModifiche
v22.4.0, v20.16.0L'opzione clientCertEngine dipende dal supporto di motori personalizzati in OpenSSL, che è deprecato in OpenSSL 3.
v16.7.0, v14.18.0Quando si utilizza un oggetto URL, il nome utente e la password analizzati verranno ora decodificati correttamente dall'URI.
v14.1.0, v13.14.0L'opzione highWaterMark è ora accettata.
v10.9.0Il parametro url può ora essere passato insieme a un oggetto options separato.
v9.3.0Il parametro options può ora includere clientCertEngine.
v7.5.0Il parametro options può essere un oggetto URL WHATWG.
v0.3.6Aggiunto in: v0.3.6

Effettua una richiesta a un server web sicuro.

Sono accettate anche le seguenti options aggiuntive da tls.connect(): ca, cert, ciphers, clientCertEngine (deprecato), crl, dhparam, ecdhCurve, honorCipherOrder, key, passphrase, pfx, rejectUnauthorized, secureOptions, secureProtocol, servername, sessionIdContext, highWaterMark.

options può essere un oggetto, una stringa o un oggetto URL. Se options è una stringa, viene analizzata automaticamente con new URL(). Se è un oggetto URL, verrà automaticamente convertito in un normale oggetto options.

https.request() restituisce un'istanza della classe http.ClientRequest. L'istanza ClientRequest è uno stream scrivibile. Se è necessario caricare un file con una richiesta POST, scrivere nell'oggetto ClientRequest.

js
import { request } from 'node:https'
import process from 'node:process'

const options = {
  hostname: 'encrypted.google.com',
  port: 443,
  path: '/',
  method: 'GET',
}

const req = request(options, res => {
  console.log('statusCode:', res.statusCode)
  console.log('headers:', res.headers)

  res.on('data', d => {
    process.stdout.write(d)
  })
})

req.on('error', e => {
  console.error(e)
})
req.end()
js
const https = require('node:https')

const options = {
  hostname: 'encrypted.google.com',
  port: 443,
  path: '/',
  method: 'GET',
}

const req = https.request(options, res => {
  console.log('statusCode:', res.statusCode)
  console.log('headers:', res.headers)

  res.on('data', d => {
    process.stdout.write(d)
  })
})

req.on('error', e => {
  console.error(e)
})
req.end()

Esempio di utilizzo delle opzioni da tls.connect():

js
const options = {
  hostname: 'encrypted.google.com',
  port: 443,
  path: '/',
  method: 'GET',
  key: fs.readFileSync('private-key.pem'),
  cert: fs.readFileSync('certificate.pem'),
}
options.agent = new https.Agent(options)

const req = https.request(options, res => {
  // ...
})

In alternativa, si può rinunciare al connection pooling non utilizzando un Agent.

js
const options = {
  hostname: 'encrypted.google.com',
  port: 443,
  path: '/',
  method: 'GET',
  key: fs.readFileSync('private-key.pem'),
  cert: fs.readFileSync('certificate.pem'),
  agent: false,
}

const req = https.request(options, res => {
  // ...
})

Esempio di utilizzo di un oggetto URL come options:

js
const options = new URL('https://abc:')

const req = https.request(options, res => {
  // ...
})

Esempio di pinning sulla fingerprint del certificato o sulla chiave pubblica (simile a pin-sha256):

js
import { checkServerIdentity } from 'node:tls'
import { Agent, request } from 'node:https'
import { createHash } from 'node:crypto'

function sha256(s) {
  return createHash('sha256').update(s).digest('base64')
}
const options = {
  hostname: 'github.com',
  port: 443,
  path: '/',
  method: 'GET',
  checkServerIdentity: function (host, cert) {
    // Assicurarsi che il certificato sia emesso per l'host a cui siamo connessi
    const err = checkServerIdentity(host, cert)
    if (err) {
      return err
    }

    // Pin la chiave pubblica, simile al pinning HPKP pin-sha256
    const pubkey256 = 'SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8='
    if (sha256(cert.pubkey) !== pubkey256) {
      const msg =
        'Errore di verifica del certificato: ' +
        `La chiave pubblica di '${cert.subject.CN}' ` +
        'non corrisponde alla nostra fingerprint appuntata'
      return new Error(msg)
    }

    // Pin il certificato esatto, piuttosto che la chiave pubblica
    const cert256 =
      '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'
    if (cert.fingerprint256 !== cert256) {
      const msg =
        'Errore di verifica del certificato: ' +
        `Il certificato di '${cert.subject.CN}' ` +
        'non corrisponde alla nostra fingerprint appuntata'
      return new Error(msg)
    }

    // Questo ciclo è solo informativo.
    // Stampa il certificato e le fingerprint della chiave pubblica di tutti i certificati nella
    // catena. È comune appuntare la chiave pubblica dell'emittente su internet pubblico, mentre si appunta la chiave pubblica del servizio in ambienti sensibili.
    let lastprint256
    do {
      console.log('Subject Common Name:', cert.subject.CN)
      console.log('  Certificate SHA256 fingerprint:', cert.fingerprint256)

      const hash = createHash('sha256')
      console.log('  Public key ping-sha256:', sha256(cert.pubkey))

      lastprint256 = cert.fingerprint256
      cert = cert.issuerCertificate
    } while (cert.fingerprint256 !== lastprint256)
  },
}

options.agent = new Agent(options)
const req = request(options, res => {
  console.log('Tutto OK. Il server corrisponde al nostro certificato o chiave pubblica appuntati')
  console.log('statusCode:', res.statusCode)

  res.on('data', d => {})
})

req.on('error', e => {
  console.error(e.message)
})
req.end()
js
const tls = require('node:tls')
const https = require('node:https')
const crypto = require('node:crypto')

function sha256(s) {
  return crypto.createHash('sha256').update(s).digest('base64')
}
const options = {
  hostname: 'github.com',
  port: 443,
  path: '/',
  method: 'GET',
  checkServerIdentity: function (host, cert) {
    // Assicurarsi che il certificato sia emesso per l'host a cui siamo connessi
    const err = tls.checkServerIdentity(host, cert)
    if (err) {
      return err
    }

    // Pin la chiave pubblica, simile al pinning HPKP pin-sha256
    const pubkey256 = 'SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8='
    if (sha256(cert.pubkey) !== pubkey256) {
      const msg =
        'Errore di verifica del certificato: ' +
        `La chiave pubblica di '${cert.subject.CN}' ` +
        'non corrisponde alla nostra fingerprint appuntata'
      return new Error(msg)
    }

    // Pin il certificato esatto, piuttosto che la chiave pubblica
    const cert256 =
      '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'
    if (cert.fingerprint256 !== cert256) {
      const msg =
        'Errore di verifica del certificato: ' +
        `Il certificato di '${cert.subject.CN}' ` +
        'non corrisponde alla nostra fingerprint appuntata'
      return new Error(msg)
    }

    // Questo ciclo è solo informativo.
    // Stampa il certificato e le fingerprint della chiave pubblica di tutti i certificati nella
    // catena. È comune appuntare la chiave pubblica dell'emittente su internet pubblico, mentre si appunta la chiave pubblica del servizio in ambienti sensibili.
    do {
      console.log('Subject Common Name:', cert.subject.CN)
      console.log('  Certificate SHA256 fingerprint:', cert.fingerprint256)

      hash = crypto.createHash('sha256')
      console.log('  Public key ping-sha256:', sha256(cert.pubkey))

      lastprint256 = cert.fingerprint256
      cert = cert.issuerCertificate
    } while (cert.fingerprint256 !== lastprint256)
  },
}

options.agent = new https.Agent(options)
const req = https.request(options, res => {
  console.log('Tutto OK. Il server corrisponde al nostro certificato o chiave pubblica appuntati')
  console.log('statusCode:', res.statusCode)

  res.on('data', d => {})
})

req.on('error', e => {
  console.error(e.message)
})
req.end()

Output ad esempio:

text
Subject Common Name: github.com
  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
  Public key ping-sha256: SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8=
Subject Common Name: Sectigo ECC Domain Validation Secure Server CA
  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
  Public key ping-sha256: Eep0p/AsSa9lFUH6KT2UY+9s1Z8v7voAPkQ4fGknZ2g=
Subject Common Name: USERTrust ECC Certification Authority
  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
  Public key ping-sha256: UJM2FOhG9aTNY0Pg4hgqjNzZ/lQBiMGRxPD5Y2/e0bw=
Subject Common Name: AAA Certificate Services
  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
  Public key ping-sha256: vRU+17BDT2iGsXvOi76E7TQMcTLXAqj0+jGPdW7L1vM=
Tutto OK. Il server corrisponde al nostro certificato o chiave pubblica appuntati
statusCode: 200