48 lines
1.5 KiB
TypeScript
48 lines
1.5 KiB
TypeScript
/**
|
|
* Shared HTTP server utilities for route handlers.
|
|
* Owner: T-1.5
|
|
*/
|
|
|
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
|
|
/** Read the full request body as a string. */
|
|
export function readBody(req: IncomingMessage): Promise<string> {
|
|
return new Promise((resolve, reject) => {
|
|
const chunks: Buffer[] = [];
|
|
req.on("data", (chunk: Buffer) => chunks.push(chunk));
|
|
req.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
|
|
req.on("error", reject);
|
|
});
|
|
}
|
|
|
|
/** Send a JSON response. */
|
|
export function sendJson(
|
|
res: ServerResponse,
|
|
status: number,
|
|
body: unknown,
|
|
): void {
|
|
const payload = JSON.stringify(body);
|
|
res.writeHead(status, {
|
|
"Content-Type": "application/json",
|
|
"Content-Length": Buffer.byteLength(payload),
|
|
});
|
|
res.end(payload);
|
|
}
|
|
|
|
/** Extract a path segment by index (0-based, after splitting on '/'). */
|
|
export function pathSegment(url: string, index: number): string | undefined {
|
|
return url.split("?")[0].split("/").filter(Boolean)[index];
|
|
}
|
|
|
|
/**
|
|
* Parse bearer token from Authorization header or ?token= query param.
|
|
* Returns the raw token string or null.
|
|
*/
|
|
export function extractBearer(req: IncomingMessage): string | null {
|
|
const auth = req.headers["authorization"];
|
|
if (auth?.startsWith("Bearer ")) return auth.slice(7).trim();
|
|
if (auth?.startsWith("bearer ")) return auth.slice(7).trim();
|
|
const url = new URL(req.url ?? "/", "http://localhost");
|
|
return url.searchParams.get("token");
|
|
}
|