diff --git a/packages/bruno-cli/src/runner/prepare-request.js b/packages/bruno-cli/src/runner/prepare-request.js index 9c2493a35..1885ef2b2 100644 --- a/packages/bruno-cli/src/runner/prepare-request.js +++ b/packages/bruno-cli/src/runner/prepare-request.js @@ -2,7 +2,7 @@ const { get, each, filter } = require('lodash'); const decomment = require('decomment'); const crypto = require('node:crypto'); const { mergeHeaders, mergeScripts, mergeVars, mergeAuth, getTreePathFromCollectionToItem } = require('../utils/collection'); -const { createFormData } = require('../utils/form-data'); +const { buildFormUrlEncodedPayload } = require('../utils/form-data'); const prepareRequest = (item = {}, collection = {}) => { const request = item?.request; @@ -288,13 +288,13 @@ const prepareRequest = (item = {}, collection = {}) => { } if (request.body.mode === 'formUrlEncoded') { - axiosRequest.headers['content-type'] = 'application/x-www-form-urlencoded'; - const params = {}; + if (!contentTypeDefined) { + axiosRequest.headers['content-type'] = 'application/x-www-form-urlencoded'; + } const enabledParams = filter(request.body.formUrlEncoded, (p) => p.enabled); - each(enabledParams, (p) => (params[p.name] = p.value)); - axiosRequest.data = params; + axiosRequest.data = buildFormUrlEncodedPayload(enabledParams); } - + if (request.body.mode === 'multipartForm') { axiosRequest.headers['content-type'] = 'multipart/form-data'; const enabledParams = filter(request.body.multipartForm, (p) => p.enabled); diff --git a/packages/bruno-cli/src/runner/run-single-request.js b/packages/bruno-cli/src/runner/run-single-request.js index e632edf20..1019c4072 100644 --- a/packages/bruno-cli/src/runner/run-single-request.js +++ b/packages/bruno-cli/src/runner/run-single-request.js @@ -329,11 +329,14 @@ const runSingleRequest = async function ( } // stringify the request url encoded params - if (request.headers['content-type'] === 'application/x-www-form-urlencoded') { + const contentTypeHeader = Object.keys(request.headers).find( + name => name.toLowerCase() === 'content-type' + ); + if (contentTypeHeader && request.headers[contentTypeHeader] === 'application/x-www-form-urlencoded') { request.data = qs.stringify(request.data, { arrayFormat: "repeat" }); } - if (request?.headers?.['content-type'] === 'multipart/form-data') { + if (contentTypeHeader && request.headers[contentTypeHeader] === 'multipart/form-data') { if (!(request?.data instanceof FormData)) { let form = createFormData(request.data, collectionPath); request.data = form; diff --git a/packages/bruno-cli/src/utils/form-data.js b/packages/bruno-cli/src/utils/form-data.js index eab5d5824..7bb00ba81 100644 --- a/packages/bruno-cli/src/utils/form-data.js +++ b/packages/bruno-cli/src/utils/form-data.js @@ -3,6 +3,25 @@ const FormData = require('form-data'); const fs = require('fs'); const path = require('path'); +/** + * @param {Array.} params The request body Array + * @returns {object} Returns an obj with repeating key as an array of values + * {item: 2, item: 3, item1: 4} becomes {item: [2,3], item1: 4} + */ +const buildFormUrlEncodedPayload = (params) => { + return params.reduce((acc, p) => { + if (!acc[p.name]) { + acc[p.name] = p.value; + } else if (Array.isArray(acc[p.name])) { + acc[p.name].push(p.value); + } else { + acc[p.name] = [acc[p.name], p.value]; + } + return acc; + }, {}); +}; + + const createFormData = (data, collectionPath) => { // make axios work in node using form data // reference: https://github.com/axios/axios/issues/1006#issuecomment-320165427 @@ -38,5 +57,6 @@ const createFormData = (data, collectionPath) => { }; module.exports = { + buildFormUrlEncodedPayload, createFormData } \ No newline at end of file