Files
pikasTech-HWLAB/internal/cloud/server-http-utils.ts
T

74 lines
2.1 KiB
TypeScript

const DEFAULT_BODY_LIMIT_BYTES = 1024 * 1024;
export function readBody(request, limitBytes = DEFAULT_BODY_LIMIT_BYTES) {
const limit = Number.isInteger(limitBytes) && limitBytes > 0 ? limitBytes : DEFAULT_BODY_LIMIT_BYTES;
return new Promise((resolve, reject) => {
let body = "";
request.setEncoding("utf8");
request.on("data", (chunk) => {
body += chunk;
if (Buffer.byteLength(body, "utf8") > limit) {
request.destroy(new Error(`request body exceeds ${limit} bytes`));
}
});
request.on("end", () => resolve(body));
request.on("error", reject);
});
}
export function sendJson(response, statusCode, body) {
response.writeHead(statusCode, {
"content-type": "application/json; charset=utf-8",
"cache-control": "no-store"
});
response.end(JSON.stringify(body) + "\n");
}
export function getHeader(request, name) {
const value = request.headers[name.toLowerCase()];
if (Array.isArray(value)) return value[0];
return value;
}
export function firstHeaderValue(request, name) {
return getHeader(request, name);
}
export function truthyFlag(value) {
return /^(?:1|true|yes|on|enabled)$/iu.test(String(value ?? "").trim());
}
export function safeTraceId(value) {
const text = String(value ?? "").trim();
return /^trc_[A-Za-z0-9_.:-]+$/u.test(text) ? text : null;
}
export function safeSessionId(value) {
const text = String(value ?? "").trim();
return /^ses_[A-Za-z0-9_.:-]+$/u.test(text) ? text : null;
}
export function safeConversationId(value) {
const text = String(value ?? "").trim();
return /^cnv_[A-Za-z0-9_.:-]+$/u.test(text) ? text : null;
}
export function safeOpaqueId(value) {
const text = String(value ?? "").trim();
return /^[A-Za-z0-9_.:-]{3,180}$/u.test(text) ? text : null;
}
export function parsePositiveInteger(value, fallback) {
const parsed = Number.parseInt(value ?? "", 10);
return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
}
export function positiveInteger(value, fallback) {
const parsed = Number.parseInt(value ?? "", 10);
return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
}