@ply-ct/ply
Version:
REST API Automated Testing
115 lines • 4.93 kB
JavaScript
;
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