memos/apps/memos-local-plugin/server/middleware/io.ts

63 lines
1.7 KiB
TypeScript

/**
* Request-body and response-writing helpers.
*
* Keep these minimal — we don't want to accidentally re-implement a
* web framework. Handlers return plain objects; `writeJson` takes care
* of stringification + content-type + status.
*/
import type { IncomingMessage, ServerResponse } from "node:http";
export async function readBody(
req: IncomingMessage,
maxBytes: number,
): Promise<Buffer> {
if (req.method === "GET" || req.method === "HEAD") return Buffer.alloc(0);
const chunks: Buffer[] = [];
let total = 0;
for await (const chunk of req) {
const buf: Buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
total += buf.length;
if (total > maxBytes) {
throw new Error(`body exceeds max size (${maxBytes} bytes)`);
}
chunks.push(buf);
}
return Buffer.concat(chunks);
}
export function parseJsonBody<T = unknown>(body: Buffer): T {
if (body.length === 0) return {} as T;
return JSON.parse(body.toString("utf8")) as T;
}
export function writeJson(
res: ServerResponse,
status: number,
payload: unknown,
): void {
const body = JSON.stringify(payload);
res.writeHead(status, { "content-type": "application/json; charset=utf-8" });
res.end(body);
}
export function writeText(
res: ServerResponse,
status: number,
text: string,
contentType = "text/plain; charset=utf-8",
): void {
res.writeHead(status, { "content-type": contentType });
res.end(text);
}
export function writeNotFound(res: ServerResponse): void {
writeJson(res, 404, { error: { code: "not_found", message: "not found" } });
}
export function writeMethodNotAllowed(res: ServerResponse, method: string): void {
writeJson(res, 405, {
error: { code: "method_not_allowed", message: `${method} not allowed here` },
});
}