feat: add support for HTTPS with --pem option in both Python and Node.js servers

This commit is contained in:
2026-05-22 00:08:50 +02:00
parent c0237886ee
commit fca0b84216
3 changed files with 60 additions and 11 deletions
+38 -8
View File
@@ -8,6 +8,8 @@
* - Displays incoming X-* headers when present
* - If User-Agent contains "curl" or "wget" (case-insensitive), the server
* responds with Content-Type: text/plain; otherwise Content-Type: text/html.
* - --pem specifies a PEM bundle file (cert chain + private key) to enable HTTPS.
* Without --pem the server listens on plain HTTP.
* - --look controls which HTML variant is returned for non-CLI agents:
* * basic - plain HTML with no external references
* * nice - includes Google Font "Noto Sans" (default)
@@ -18,6 +20,8 @@
*/
import http from "node:http";
import https from "node:https";
import fs from "node:fs";
import { URL } from "node:url";
const VALID_LOOKS = new Set(["basic", "nice", "bootstrap", "tailwind"]);
@@ -258,6 +262,7 @@ function parseArgs(argv) {
let bind = "0.0.0.0";
let port = 8080;
let look = "nice";
let pem = null;
for (let i = 0; i < argv.length; i += 1) {
const arg = argv[i];
@@ -284,6 +289,15 @@ function parseArgs(argv) {
continue;
}
if (arg === "--pem") {
i += 1;
if (i >= argv.length) {
throw new Error(`${arg} requires a value`);
}
pem = argv[i];
continue;
}
if (arg === "--look") {
i += 1;
if (i >= argv.length) {
@@ -300,11 +314,12 @@ function parseArgs(argv) {
if (arg === "-h" || arg === "--help") {
const help = [
"Usage:",
" node ok-server.mjs [-b|--bind ADDRESS] [-p|--port PORT] [--look basic|nice|bootstrap|tailwind]",
" node ok-server.mjs [-b|--bind ADDRESS] [-p|--port PORT] [--pem PEMFILE] [--look basic|nice|bootstrap|tailwind]",
"",
"Defaults:",
" --bind 0.0.0.0",
" --port 8080",
" --pem (none, plain HTTP)",
" --look nice",
].join("\n");
console.log(help);
@@ -314,12 +329,13 @@ function parseArgs(argv) {
throw new Error(`Unknown argument: ${arg}`);
}
return { bind, port, look };
return { bind, port, look, pem };
}
function run(bind, port, look) {
function run(bind, port, look, pem) {
let isShuttingDown = false;
const server = http.createServer((req, res) => {
function createRequestHandler(req, res) {
const method = req.method || "GET";
if (method !== "GET" && method !== "HEAD") {
@@ -342,7 +358,20 @@ function run(bind, port, look) {
}
res.end(body);
});
}
let server;
if (pem) {
let pemContent;
try {
pemContent = fs.readFileSync(pem);
} catch (err) {
throw new Error(`Cannot read PEM file '${pem}': ${err.message}`);
}
server = https.createServer({ cert: pemContent, key: pemContent }, createRequestHandler);
} else {
server = http.createServer(createRequestHandler);
}
server.on("request", (req) => {
const clientIp = getClientIp(req);
@@ -358,7 +387,8 @@ function run(bind, port, look) {
});
server.listen(port, bind, () => {
console.log(`Serving on ${bind}:${port} (default look=${look}) (Ctrl-C to stop)`);
const scheme = pem ? "https" : "http";
console.log(`Serving on ${scheme}://${bind}:${port} (default look=${look}) (Ctrl-C to stop)`);
});
function handleShutdownSignal() {
@@ -375,8 +405,8 @@ function run(bind, port, look) {
}
try {
const { bind, port, look } = parseArgs(process.argv.slice(2));
run(bind, port, look);
const { bind, port, look, pem } = parseArgs(process.argv.slice(2));
run(bind, port, look, pem);
} catch (err) {
process.stderr.write(`${err.message}\n`);
process.exit(2);