UNPKG

@ply-ct/ply

Version:

REST API Automated Testing

115 lines 4.93 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MultipartForm = void 0; const fs = __importStar(require("fs")); const form_data_1 = __importDefault(require("form-data")); const util = __importStar(require("./util")); class MultipartForm { constructor(request) { this.request = request; this.options = { fileNameToBase: true }; const contentTypeHeader = util.header(request.headers, 'Content-Type'); if (!contentTypeHeader) throw new Error('Missing header: Content-Type'); this.contentTypeHeader = contentTypeHeader; const contentType = this.contentTypeHeader[1]; if (!contentType.toLowerCase().startsWith('multipart/form-data')) { throw new Error(`Invalid Content-Type: ${contentType}`); } const boundary = this.getBoundary(contentType); if (!request.body) throw new Error('Body is required for multipart/form-data'); this.parts = this.getParts(request.body, boundary); } getRequest() { const formData = new form_data_1.default(); for (const part of this.parts) { if (part.filename) { if (!fs.existsSync(part.filename)) { throw new Error(`File not found: ${part.filename}`); } formData.append(part.name, fs.createReadStream(part.filename)); } else if (part.data) { formData.append(part.name, part.data); } } const contentTypeKey = this.contentTypeHeader[0]; const { [contentTypeKey]: _ctKey, ...headers } = this.request.headers; return { name: this.request.name, type: this.request.type, url: this.request.url, method: this.request.method, headers, body: formData, submitted: this.request.submitted, submit: this.request.submit }; } getBoundary(contentType) { const segs = contentType.split(';').map((s) => s.trim()); if (segs.length < 2 || !segs[1].startsWith('boundary=') || segs[1].length < 11) { throw new Error('boundary is required'); } return segs[1].substring(10, segs[1].length - 1); } getParts(body, boundary) { const lines = util.lines(body).map((l) => l.trim()); return lines.reduce((parts, line) => { if (line === boundary) { parts.push({ name: '' }); } else { const part = parts[parts.length - 1]; if (!part) throw new Error('Missing boundary start'); if (line.toLowerCase().startsWith('content-disposition')) { const segs = line.split(';').map((s) => s.trim()); if (segs.length < 2 || !segs[1].startsWith('name=') || segs[1].length < 7) { throw new Error('name is required'); } part.name = segs[1].substring(6, segs[1].length - 1); const filenameSeg = segs.find((s) => s.startsWith('filename=')); if (filenameSeg && filenameSeg.length >= 11) { part.filename = filenameSeg.substring(10, filenameSeg.length - 1); } } else if (line !== `${boundary}--`) { if (!part.data) part.data = Buffer.alloc(0); part.data = Buffer.concat([part.data, Buffer.from(line)]); } } return parts; }, []); } } exports.MultipartForm = MultipartForm; //# sourceMappingURL=form.js.map