Node.js TLS and HTTPS
TLS protects a connection only when the client verifies the expected peer under an appropriate trust policy. Turning verification off removes a central part of that contract.
How it works
The complete fixture generates an ephemeral one-day localhost certificate using a separately configured OpenSSL executable, starts an HTTPS server and trusts only that generated certificate in its own client. The client connects to loopback while checking the localhost name through servername. No key or certificate is published or reused. This proves a local handshake and name/trust configuration, not a public certificate chain, renewal system or production TLS deployment.
Run the code
Run this example locally with Node.js. The exact sources are reviewed on Node 22.15.1 and Node 24.22.1 unless a specialised lab states otherwise. Save the complete source as tls-https.mjs in a separate empty exercises folder and run node tls-https.mjs. There is no Node.js browser runner on Bhylu; the plain JavaScript playground does not provide these filesystem, server or process APIs. Set BHYLU_OPENSSL to a compatible local OpenSSL executable. The review uses XAMPP’s OpenSSL command only to generate a temporary localhost identity; it does not edit Apache or the system trust store.
Download the complete source. Ordinary Node scripts need no Apache, PHP or MySQL service. File examples own their temporary folders; network fixtures use loopback and available temporary ports.
Example
import { mkdtemp, rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
const folder = await mkdtemp(join(tmpdir(), 'bhylu-node-'));
import { readFile, writeFile } from 'node:fs/promises';
import { spawnSync } from 'node:child_process';
import https from 'node:https';
import tls from 'node:tls';
import { once } from 'node:events';
try {
if (!process.env.BHYLU_OPENSSL)
throw new Error('Set BHYLU_OPENSSL to your OpenSSL executable');
const keyFile = join(folder, 'key.pem'),
certFile = join(folder, 'cert.pem'),
configFile = join(folder, 'openssl.cnf');
await writeFile(configFile, '[req]\ndistinguished_name=dn\n[dn]\nCN=localhost\n', {
flag: 'wx',
});
const generated = spawnSync(
process.env.BHYLU_OPENSSL,
[
'req',
'-config',
configFile,
'-x509',
'-newkey',
'rsa:2048',
'-noenc',
'-keyout',
keyFile,
'-out',
certFile,
'-subj',
'/CN=localhost',
'-addext',
'subjectAltName=DNS:localhost',
'-days',
'1',
],
{ encoding: 'utf8', timeout: 15000, windowsHide: true },
);
if (generated.status !== 0) throw new Error('Local certificate generation failed');
const key = await readFile(keyFile),
cert = await readFile(certFile);
console.log(typeof tls.createSecureContext({ key, cert }) === 'object');
const server = https.createServer(
{ key, cert, minVersion: 'TLSv1.2' },
(request, response) => response.end('verified-local-tls'),
);
server.listen(0, '127.0.0.1');
await once(server, 'listening');
try {
const text = await new Promise((resolve, reject) => {
const request = https.get(
{
hostname: '127.0.0.1',
port: server.address().port,
servername: 'localhost',
ca: cert,
rejectUnauthorized: true,
},
(response) => {
let body = '';
response.setEncoding('utf8');
response.on('data', (chunk) => (body += chunk));
response.on('end', () => resolve(body));
response.on('error', reject);
},
);
request.on('error', reject);
});
console.log(text);
} finally {
server.closeAllConnections();
await new Promise((resolve) => server.close(resolve));
}
} finally {
await rm(folder, { recursive: true, force: true });
}
Expected result
true verified-local-tls
The client verifies its explicitly trusted local identity and receives the expected response. The temporary private key is deleted with the owned folder. The review does not disable global verification or modify any browser or operating-system trust store.
Use the Node.js API reference for the precise version contract.