feat: added multipart data formatting in timeline (#6185)

refactor: remove escapeHeaderValue function and enhance formatMultipartData utility
This commit is contained in:
Sanjai Kumar
2025-11-27 18:12:20 +05:30
committed by GitHub
parent 6e88671788
commit bb0096eb38
4 changed files with 140 additions and 4 deletions

View File

@@ -1,6 +1,8 @@
const { customAlphabet } = require('nanoid');
const iconv = require('iconv-lite');
const { cloneDeep } = require('lodash');
const FormData = require('form-data');
const { formatMultipartData } = require('./form-data');
// a customized version of nanoid without using _ and -
const uuid = () => {
@@ -128,7 +130,18 @@ const parseDataFromResponse = (response, disableParsingResponseJson = false) =>
};
const parseDataFromRequest = (request) => {
const requestDataString = request.mode == 'file'? "<request body redacted>": (typeof request?.data === 'string' ? request?.data : safeStringifyJSON(request?.data));
let requestDataString;
// File uploads are redacted, multipart FormData is formatted from original data for readability, and other types are stringified as-is.
if (request.mode === 'file') {
requestDataString = '<request body redacted>';
} else if (request?.data instanceof FormData && Array.isArray(request._originalMultipartData)) {
const boundary = request.data._boundary || 'boundary';
requestDataString = formatMultipartData(request._originalMultipartData, boundary);
} else {
requestDataString = typeof request?.data === 'string' ? request?.data : safeStringifyJSON(request?.data);
}
const requestCopy = cloneDeep(request);
if (!requestCopy.data) {
return { data: null, dataBuffer: null };

View File

@@ -3,6 +3,61 @@ const FormData = require('form-data');
const fs = require('fs');
const path = require('path');
const formatMultipartData = (multipartData, boundary) => {
if (!Array.isArray(multipartData) || multipartData.length === 0) {
return '';
}
const normalizeBoundary = (b) => {
const value = b || 'boundary';
return value.replace(/^--+/, '').replace(/--+$/, '');
};
const getFileName = (filePath) => {
if (typeof filePath === 'string' && filePath.trim()) {
return path.basename(filePath) || 'file';
}
return 'file';
};
const formatValue = (value) => {
if (Array.isArray(value)) {
return value.map((v) => String(v ?? '')).join(', ');
}
return String(value ?? '');
};
const boundaryValue = normalizeBoundary(boundary);
const parts = [];
multipartData.forEach((field) => {
if (!field || !field.name) return;
parts.push(`----${boundaryValue}`);
parts.push('Content-Disposition: form-data');
if (field.type === 'file') {
const filePaths = Array.isArray(field.value) ? field.value : (field.value ? [field.value] : ['']);
filePaths.forEach((filePath) => {
parts.push(`----${boundaryValue}`);
parts.push('Content-Disposition: form-data');
const fileName = getFileName(filePath);
parts.push(`name: ${field.name}`);
parts.push(`value: [File: ${fileName}]`);
parts.push('');
});
} else {
const value = formatValue(field.value);
parts.push(`name: ${field.name}`);
parts.push(`value: ${value}`);
parts.push('');
}
});
parts.push(`----${boundaryValue}--`);
return parts.join('\n');
};
const createFormData = (data, collectionPath) => {
// make axios work in node using form data
// reference: https://github.com/axios/axios/issues/1006#issuecomment-320165427
@@ -38,5 +93,6 @@ const createFormData = (data, collectionPath) => {
};
module.exports = {
createFormData
createFormData,
formatMultipartData
};