mirror of
https://github.com/Kong/insomnia
synced 2024-11-08 14:49:53 +00:00
3947bdc4aa
* fix lint * fix types * remove flush db.change event send * guard against tests running electron functions * copy preload to build output * fix webview context menu * fix context menu and plugin install * move installPlugin to main context
117 lines
3.0 KiB
TypeScript
117 lines
3.0 KiB
TypeScript
import fs from 'fs';
|
|
import mimes from 'mime-types';
|
|
import path from 'path';
|
|
|
|
import type { RequestBodyParameter } from '../models/request';
|
|
|
|
export const DEFAULT_BOUNDARY = 'X-INSOMNIA-BOUNDARY';
|
|
|
|
interface Multipart {
|
|
boundary: typeof DEFAULT_BOUNDARY;
|
|
filePath: string;
|
|
contentLength: number;
|
|
}
|
|
|
|
export async function buildMultipart(params: RequestBodyParameter[]) {
|
|
return new Promise<Multipart>(async (resolve, reject) => {
|
|
const filePath = path.join(window.app.getPath('temp'), Math.random() + '.body');
|
|
const writeStream = fs.createWriteStream(filePath);
|
|
const lineBreak = '\r\n';
|
|
let totalSize = 0;
|
|
|
|
function addFile(path: string) {
|
|
return new Promise<void>((resolve, reject) => {
|
|
let size;
|
|
|
|
try {
|
|
size = fs.statSync(path).size;
|
|
} catch (err) {
|
|
reject(err);
|
|
}
|
|
|
|
const stream = fs.createReadStream(path);
|
|
stream.once('end', () => {
|
|
resolve();
|
|
});
|
|
stream.once('error', err => {
|
|
reject(err);
|
|
});
|
|
stream.pipe(writeStream, {
|
|
end: false,
|
|
});
|
|
totalSize += size;
|
|
});
|
|
}
|
|
|
|
const addString = (v: string) => {
|
|
const buffer = Buffer.from(v);
|
|
writeStream.write(buffer);
|
|
totalSize += buffer.length;
|
|
};
|
|
|
|
for (const param of params) {
|
|
const noName = !param.name;
|
|
const noValue = !(param.value || param.fileName);
|
|
|
|
if (noName && noValue) {
|
|
continue;
|
|
}
|
|
|
|
addString(`--${DEFAULT_BOUNDARY}`);
|
|
addString(lineBreak);
|
|
|
|
if (param.type === 'file' && param.fileName) {
|
|
const name = param.name || '';
|
|
const fileName = param.fileName;
|
|
const contentType = mimes.lookup(fileName) || 'application/octet-stream';
|
|
addString(
|
|
'Content-Disposition: form-data; ' +
|
|
`name="${name.replace(/"/g, '\\"')}"; ` +
|
|
`filename="${path.basename(fileName).replace(/"/g, '\\"')}"`,
|
|
);
|
|
addString(lineBreak);
|
|
addString(`Content-Type: ${contentType}`);
|
|
addString(lineBreak);
|
|
addString(lineBreak);
|
|
|
|
try {
|
|
await addFile(fileName);
|
|
} catch (err) {
|
|
return reject(err);
|
|
}
|
|
} else {
|
|
const name = param.name || '';
|
|
const value = param.value || '';
|
|
const contentType = param.multiline;
|
|
addString(`Content-Disposition: form-data; name="${name}"`);
|
|
addString(lineBreak);
|
|
|
|
if (typeof contentType === 'string') {
|
|
addString(`Content-Type: ${contentType}`);
|
|
addString(lineBreak);
|
|
}
|
|
|
|
addString(lineBreak);
|
|
addString(value);
|
|
}
|
|
|
|
addString(lineBreak);
|
|
}
|
|
|
|
addString(`--${DEFAULT_BOUNDARY}--`);
|
|
addString(lineBreak);
|
|
writeStream.once('error', err => {
|
|
reject(err);
|
|
});
|
|
writeStream.once('close', () => {
|
|
resolve({
|
|
boundary: DEFAULT_BOUNDARY,
|
|
filePath,
|
|
contentLength: totalSize,
|
|
});
|
|
});
|
|
// We're done here. End the stream and tell FS to save/close the file.
|
|
writeStream.end();
|
|
});
|
|
}
|