UNPKG

ufiber

Version:

Next-gen webserver for node-js developer

94 lines (92 loc) 2.89 kB
import { formatBytes } from "./tools.js"; import uws from "../../uws"; //#region src/utils/body.ts /** * Simple FormData-like container for Node. * Supports multiple values per key and JSON conversion. */ var FormData = class extends Map { /** * Appends a new value for the given key. * If the key already exists, converts the value into an array * and pushes the new value into it. * * @param name - The key name. * @param value - The value to append. */ append(key, value) { const current = this.get(key); if (current === void 0) this.set(key, value); else if (Array.isArray(current)) current.push(value); else this.set(key, [current, value]); } /** * Returns the first value associated with the given key. * If multiple values exist, only the first one is returned. * * @param name - The key to look up. * @returns The first value, or `undefined` if not found. */ get(name) { const val = super.get(name); return Array.isArray(val) ? val[0] : val; } /** * Returns all values associated with the given key. * Always returns an array (empty if key not found). * * @param name - The key to look up. * @returns An array of values. */ getAll(key) { const v = super.get(key); return Array.isArray(v) ? v : v !== void 0 ? [v] : []; } /** * Converts the entire form to a plain JavaScript object. * * @returns A `Record<string, any>` containing all keys and values. */ toJSON() { const obj = {}; for (const [k, v] of this.entries()) obj[k] = v; return obj; } }; /** * Parse multipart/form-data bodies from a readable stream. */ const formParse = (buf, cType, options = {}) => { const { files = 5, fileSize = 5 * 1024 * 1024, fileFields } = options; const form = new FormData(); const parts = uws.getParts(buf, cType); if (parts) { let fileCount = 0; parts.forEach((part) => { const { name, data, filename, type: mimeType } = part; const buffer = Buffer.from(data); if (!filename || !mimeType) { const value = buffer.toString("utf8"); form.append(name, value); return; } fileCount++; if (fileCount > files) throw new Error(`Too many files uploaded. Maximum allowed: ${files}, received: ${fileCount}`); if (fileFields && !(Array.isArray(fileFields) && fileFields.includes(name) || fileFields === name)) throw new Error(`File upload not allowed for field '${name}'`); if (buffer.byteLength > fileSize) throw new RangeError(`File '${filename}' is ${formatBytes(buffer.byteLength)}, max allowed ${formatBytes(fileSize)}`); const ext = filename.includes(".") ? filename.split(".").pop().toLowerCase().slice(0, 10) : ""; const fileInfo = { filename, mimeType: mimeType.slice(0, 100), extension: ext, readable: formatBytes(buffer.length), bytes: buffer.length, buffer }; form.append(name, fileInfo); }); } return form; }; //#endregion export { FormData, formParse };