import type {Server, IncomingMessage, ServerResponse} from 'node:http'; import type {Duplex} from 'node:stream'; interface Mount { target: Server | null; acquire(target: Server): () => void; } const mounts = new WeakMap>(); // Keep one dormant dispatcher per host/path: later Socket.IO services may wrap // this listener, so removing it on stop would corrupt their request chain. export function mount_http(host: Server, path: string, target: Server): () => void { let entries = mounts.get(host); if (!entries) { entries = new Map(); mounts.set(host, entries); } const existing = entries.get(path); if (existing) return existing.acquire(target); const original = host.listeners('request'); const prefix = `${path}/`; const matches = (request: IncomingMessage) => (request.url ?? '').split('?')[0].startsWith(prefix); const mount: Mount = { target: null, acquire(next) { if (this.target) throw new Error(`Relay path already mounted: ${path}`); this.target = next; return () => { if (this.target === next) this.target = null; }; }, }; const request_listener = (request: IncomingMessage, response: ServerResponse) => { if (matches(request)) { if (mount.target) mount.target.emit('request', request, response); else { response.statusCode = 503; response.end('Relay unavailable'); } } else { for (const listener of original) listener.call(host, request, response); } }; const upgrade_listener = (request: IncomingMessage, socket: Duplex, head: Buffer) => { if (!matches(request)) return; if (mount.target) mount.target.emit('upgrade', request, socket, head); else socket.destroy(); }; for (const listener of original) host.removeListener('request', listener); host.on('request', request_listener); host.on('upgrade', upgrade_listener); entries.set(path, mount); host.on('close', () => { mount.target = null; }); return mount.acquire(target); }