pi-remote-control/extensions/remote-control/server/util.ts

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");
}