T-HUB/apps/api/src/connections/http-test-transport.ts
glass beadian aa5e262f3a Tactical Media Broadcast Hub — initial release
Self-hosted multi-platform broadcast newsroom for activist collectives:
publishing pipeline with group approval and DST-proof scheduling, TweetDeck-style
column wall with hostile-content-safe rendering, live control room with Auto
Director, bridged chat governance with polls and quorum, distributed sandboxed
transcode workers, encrypted content-addressed archive, monthly analytics.

MIT licensed. See README.md and docs/.
2026-10-10 11:56:42 +00:00

46 lines
2.1 KiB
TypeScript

import { IncomingMessage, ServerResponse } from "node:http";
import { Duplex } from "node:stream";
import type { Socket } from "node:net";
/** Runs real Node/Express HTTP handlers without binding a port (restricted CI). */
export async function injectHttp(
handler: (request: IncomingMessage, response: ServerResponse) => void,
input: string | URL | Request,
init: RequestInit = {},
): Promise<Response> {
const url = new URL(input instanceof Request ? input.url : String(input));
const output: Buffer[] = [];
const socket = new Duplex({
read() {},
write(chunk: Buffer, _encoding, callback) { output.push(Buffer.from(chunk)); callback(); },
});
// ServerResponse uses only Duplex operations; no network or unsafe dynamic values.
const httpSocket = socket as unknown as Socket;
const request = new IncomingMessage(httpSocket);
request.method = init.method ?? "GET";
request.complete = true;
request.url = `${url.pathname}${url.search}`;
request.headers = Object.fromEntries(new Headers(init.headers).entries());
request.headers.host = url.host;
const body = typeof init.body === "string" ? init.body : "";
if (body) request.headers["content-length"] = String(Buffer.byteLength(body));
request.push(body || null);
if (body) request.push(null);
const response = new ServerResponse(request);
response.assignSocket(httpSocket);
const completed = new Promise<Response>((resolve, reject) => {
response.once("error", reject);
response.once("finish", () => {
const bytes = Buffer.concat(output);
const bodyOffset = bytes.indexOf("\r\n\r\n") + 4;
const headers = new Headers();
for (const line of bytes.subarray(0, bodyOffset - 4).toString().split("\r\n").slice(1)) {
const separator = line.indexOf(":");
if (separator > 0) headers.append(line.slice(0, separator), line.slice(separator + 1).trim());
}
resolve(new Response([204, 304].includes(response.statusCode) ? null : bytes.subarray(bodyOffset), { status: response.statusCode, headers }));
});
});
handler(request, response);
return completed;
}