2017-10-28 22:16:34 +00:00
|
|
|
import * as electron from 'electron';
|
2017-10-11 21:43:21 +00:00
|
|
|
import mimes from 'mime-types';
|
|
|
|
import fs from 'fs';
|
|
|
|
import path from 'path';
|
2018-06-25 17:42:50 +00:00
|
|
|
import type { RequestBodyParameter } from '../models/request';
|
2017-10-11 21:43:21 +00:00
|
|
|
|
2017-10-28 22:16:34 +00:00
|
|
|
export const DEFAULT_BOUNDARY = 'X-INSOMNIA-BOUNDARY';
|
2017-10-11 21:43:21 +00:00
|
|
|
|
2021-05-12 06:35:00 +00:00
|
|
|
interface Multipart {
|
|
|
|
boundary: typeof DEFAULT_BOUNDARY,
|
|
|
|
filePath: string;
|
|
|
|
contentLength: number;
|
|
|
|
}
|
|
|
|
|
2018-06-25 17:42:50 +00:00
|
|
|
export async function buildMultipart(params: Array<RequestBodyParameter>) {
|
2021-05-12 06:35:00 +00:00
|
|
|
return new Promise<Multipart>(async (resolve, reject) => {
|
2018-10-17 16:42:33 +00:00
|
|
|
const filePath = path.join(electron.remote.app.getPath('temp'), Math.random() + '.body');
|
2017-10-28 22:16:34 +00:00
|
|
|
const writeStream = fs.createWriteStream(filePath);
|
|
|
|
const lineBreak = '\r\n';
|
|
|
|
let totalSize = 0;
|
|
|
|
|
2021-05-12 06:35:00 +00:00
|
|
|
function addFile(path: string) {
|
|
|
|
return new Promise<void>((resolve, reject) => {
|
2017-11-10 17:30:09 +00:00
|
|
|
let size;
|
2021-05-12 06:35:00 +00:00
|
|
|
|
2017-11-10 17:30:09 +00:00
|
|
|
try {
|
|
|
|
size = fs.statSync(path).size;
|
|
|
|
} catch (err) {
|
|
|
|
reject(err);
|
|
|
|
}
|
2019-12-13 23:54:08 +00:00
|
|
|
|
2017-10-28 22:16:34 +00:00
|
|
|
const stream = fs.createReadStream(path);
|
|
|
|
stream.once('end', () => {
|
|
|
|
resolve();
|
|
|
|
});
|
2019-12-13 23:54:08 +00:00
|
|
|
stream.once('error', err => {
|
|
|
|
reject(err);
|
|
|
|
});
|
2021-05-12 06:35:00 +00:00
|
|
|
stream.pipe(writeStream, {
|
|
|
|
end: false,
|
|
|
|
});
|
2017-10-28 22:16:34 +00:00
|
|
|
totalSize += size;
|
|
|
|
});
|
2017-10-11 21:43:21 +00:00
|
|
|
}
|
|
|
|
|
2017-10-28 22:16:34 +00:00
|
|
|
const addString = (v: string) => {
|
|
|
|
const buffer = Buffer.from(v);
|
|
|
|
writeStream.write(buffer);
|
|
|
|
totalSize += buffer.length;
|
|
|
|
};
|
2017-10-11 21:43:21 +00:00
|
|
|
|
2017-10-28 22:16:34 +00:00
|
|
|
for (const param of params) {
|
|
|
|
const noName = !param.name;
|
|
|
|
const noValue = !(param.value || param.fileName);
|
|
|
|
|
|
|
|
if (noName && noValue) {
|
|
|
|
continue;
|
|
|
|
}
|
2017-10-11 21:43:21 +00:00
|
|
|
|
2017-10-28 22:16:34 +00:00
|
|
|
addString(`--${DEFAULT_BOUNDARY}`);
|
|
|
|
addString(lineBreak);
|
|
|
|
|
|
|
|
if (param.type === 'file' && param.fileName) {
|
|
|
|
const name = param.name || '';
|
|
|
|
const fileName = param.fileName;
|
2018-10-17 16:42:33 +00:00
|
|
|
const contentType = mimes.lookup(fileName) || 'application/octet-stream';
|
2017-10-28 22:16:34 +00:00
|
|
|
addString(
|
|
|
|
'Content-Disposition: form-data; ' +
|
2018-06-25 17:42:50 +00:00
|
|
|
`name="${name.replace(/"/g, '\\"')}"; ` +
|
2018-12-12 17:36:11 +00:00
|
|
|
`filename="${path.basename(fileName).replace(/"/g, '\\"')}"`,
|
2017-10-28 22:16:34 +00:00
|
|
|
);
|
|
|
|
addString(lineBreak);
|
|
|
|
addString(`Content-Type: ${contentType}`);
|
|
|
|
addString(lineBreak);
|
|
|
|
addString(lineBreak);
|
2021-05-12 06:35:00 +00:00
|
|
|
|
2017-11-10 17:30:09 +00:00
|
|
|
try {
|
|
|
|
await addFile(fileName);
|
|
|
|
} catch (err) {
|
|
|
|
return reject(err);
|
|
|
|
}
|
2017-10-28 22:16:34 +00:00
|
|
|
} else {
|
|
|
|
const name = param.name || '';
|
|
|
|
const value = param.value || '';
|
2019-11-27 14:59:04 +00:00
|
|
|
const contentType = param.multiline;
|
2017-10-28 22:16:34 +00:00
|
|
|
addString(`Content-Disposition: form-data; name="${name}"`);
|
|
|
|
addString(lineBreak);
|
2021-05-12 06:35:00 +00:00
|
|
|
|
2020-02-11 19:32:43 +00:00
|
|
|
if (typeof contentType === 'string') {
|
2019-11-27 14:59:04 +00:00
|
|
|
addString(`Content-Type: ${contentType}`);
|
|
|
|
addString(lineBreak);
|
|
|
|
}
|
2021-05-12 06:35:00 +00:00
|
|
|
|
2017-10-28 22:16:34 +00:00
|
|
|
addString(lineBreak);
|
|
|
|
addString(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
addString(lineBreak);
|
2017-10-11 21:43:21 +00:00
|
|
|
}
|
|
|
|
|
2017-10-28 22:16:34 +00:00
|
|
|
addString(`--${DEFAULT_BOUNDARY}--`);
|
|
|
|
addString(lineBreak);
|
2019-12-13 23:54:08 +00:00
|
|
|
writeStream.once('error', err => {
|
2017-10-28 22:16:34 +00:00
|
|
|
reject(err);
|
|
|
|
});
|
2019-12-13 23:54:08 +00:00
|
|
|
writeStream.once('close', () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
resolve({
|
|
|
|
boundary: DEFAULT_BOUNDARY,
|
|
|
|
filePath,
|
2018-12-12 17:36:11 +00:00
|
|
|
contentLength: totalSize,
|
2018-06-25 17:42:50 +00:00
|
|
|
});
|
2017-10-28 22:16:34 +00:00
|
|
|
});
|
|
|
|
// We're done here. End the stream and tell FS to save/close the file.
|
|
|
|
writeStream.end();
|
|
|
|
});
|
2017-10-11 21:43:21 +00:00
|
|
|
}
|