UNPKG

@juspay/neurolink

Version:

The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002

77 lines (76 loc) • 3.02 kB
/** * Raw request bodies and raw responses for the server adapters. * * The adapters parse JSON (and url-encoded forms) into `ctx.body`. Routes that * take uploads — `POST /v1/audio/transcriptions` takes `multipart/form-data` * the way OpenAI's API does — need the bytes instead, so for the content types * below every adapter hands the route the unparsed body as a `Buffer`, bounded * by `bodyParser.maxSize`. A route that must answer in a wire format other than * the adapters' `{ data, metadata }` envelope (an OpenAI-compatible route, a * plain-text response) returns a web `Response`, which every adapter sends as is. * * @module server/utils/rawBody */ /** Content types whose body reaches the route as a `Buffer`. */ const RAW_BODY_CONTENT_TYPE = /^\s*(multipart\/form-data|application\/octet-stream|audio\/[\w.+-]+)\s*(;|$)/i; /** `true` for a content type whose body the adapters pass through unparsed. */ export function isRawBodyContentType(contentType) { return (typeof contentType === "string" && RAW_BODY_CONTENT_TYPE.test(contentType)); } /** "10mb" / "512kb" / "1gb" / a byte count → bytes. Falls back to 10 MB. */ export function parseByteLimit(limit) { if (typeof limit === "number" && Number.isFinite(limit) && limit > 0) { return limit; } const match = typeof limit === "string" ? limit.trim().match(/^(\d+(?:\.\d+)?)\s*(b|kb|mb|gb)?$/i) : null; if (!match) { return 10 * 1024 * 1024; } const units = { b: 1, kb: 1024, mb: 1024 * 1024, gb: 1024 * 1024 * 1024, }; return Math.floor(Number(match[1]) * units[(match[2] ?? "b").toLowerCase()]); } /** Thrown when a raw body grows past the adapter's `maxSize`. */ export class RawBodyTooLargeError extends Error { status = 413; constructor(limit) { super(`Request body exceeds the server's ${limit}-byte limit`); this.name = "RawBodyTooLargeError"; } } /** Read a Node request stream into one `Buffer`, refusing more than `maxBytes`. */ export async function readRawBody(stream, maxBytes) { const chunks = []; let total = 0; for await (const chunk of stream) { const buffer = typeof chunk === "string" ? Buffer.from(chunk) : chunk; total += buffer.length; if (total > maxBytes) { throw new RawBodyTooLargeError(maxBytes); } chunks.push(buffer); } return Buffer.concat(chunks); } /** A web `Response` returned by a route handler. */ export function isWebResponse(value) { return typeof Response !== "undefined" && value instanceof Response; } /** Status, headers and body bytes of a web `Response`, for adapters that write to a Node response. */ export async function readWebResponse(response) { const headers = {}; response.headers.forEach((value, key) => { headers[key] = value; }); return { status: response.status, headers, body: Buffer.from(await response.arrayBuffer()), }; }