// @flow import * as electron from 'electron'; import mimes from 'mime-types'; import fs from 'fs'; import path from 'path'; import type {RequestBodyParameter} from '../models/request'; export const DEFAULT_BOUNDARY = 'X-INSOMNIA-BOUNDARY'; export async function buildMultipart (params: Array) { return new Promise(async (resolve: Function, reject: Function) => { const filePath = path.join(electron.remote.app.getPath('temp'), Math.random() + '.body'); const writeStream = fs.createWriteStream(filePath); const lineBreak = '\r\n'; let totalSize = 0; async function addFile (path: string) { return new Promise(resolve => { const {size} = fs.statSync(path); const stream = fs.createReadStream(path); stream.once('end', () => { resolve(); }); 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); await addFile(fileName); } else { const name = param.name || ''; const value = param.value || ''; addString(`Content-Disposition: form-data; name="${name}"`); addString(lineBreak); addString(lineBreak); addString(value); } addString(lineBreak); } addString(`--${DEFAULT_BOUNDARY}--`); addString(lineBreak); writeStream.on('error', err => { reject(err); }); writeStream.on('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(); }); }