Multi Server Upgrade

A WebSocket/upgrade-capable primary server alongside a plain additional server. The first http.createServer is the primary: it can handle the Node `'upgrade'` event (here a trivial raw-protocol echo). An additional server on its own port is plain HTTP/1.1 — an app that speaks WebSockets on its main port while exposing a plain health/metrics port.

The additional server also demonstrates Stage 2's close/listen relisten: it is closed and re-listened on a fresh port before the demo shuts down. A self-closing sequence keeps the example runnable to completion.

import http from 'http';
import type { AddressInfo } from 'net';

const app = http.createServer((req: http.IncomingMessage, res: http.ServerResponse) => {
  res.writeHead(200, { "Content-Type": "text/plain" });
  res.end("app: " + req.url);
});
app.on('upgrade', (req, socket, head) => {
  socket.write('HTTP/1.1 101 Switching Protocols\r\nUpgrade: echo\r\nConnection: Upgrade\r\n\r\n');
  socket.on('data', (chunk) => { socket.write('echo:' + chunk.toString()); });
});

const health = http.createServer((req: http.IncomingMessage, res: http.ServerResponse) => {
  res.writeHead(200, { "Content-Type": "application/json" });
  res.end('{"status":"ok"}');
});

app.listen(0, () => {
  health.listen(0, () => {
    console.log("app (ws-capable) on port", (app.address() as AddressInfo).port > 0);
    console.log("health on port", (health.address() as AddressInfo).port > 0);
    // Stage 2 relisten: close the additional server and bring it back up on a
    // fresh OS-assigned port.
    health.close();
    health.listen(0, () => {
      console.log("health relistened on port", (health.address() as AddressInfo).port > 0);
      app.close();
      health.close();
    });
  });
});

console.log("ws-capable primary + plain additional server listening");
View source on GitHubexamples/http/multi_server_upgrade.ts