Fix: Passing the raw decoded data to Res-preview and avoid decoding twice

This commit is contained in:
ramki-bruno
2025-03-20 14:25:11 +05:30
parent 391348e3d3
commit c08717afb2
9 changed files with 28 additions and 38 deletions

1
package-lock.json generated
View File

@@ -25052,7 +25052,6 @@
"graphql-request": "^3.7.0",
"httpsnippet": "^3.0.9",
"i18next": "24.1.2",
"iconv-lite": "^0.6.3",
"idb": "^7.0.0",
"immer": "^9.0.15",
"jsesc": "^3.0.2",

View File

@@ -36,7 +36,6 @@
"graphql-request": "^3.7.0",
"httpsnippet": "^3.0.9",
"i18next": "24.1.2",
"iconv-lite": "^0.6.3",
"idb": "^7.0.0",
"immer": "^9.0.15",
"jsesc": "^3.0.2",

View File

@@ -3,7 +3,6 @@ import QueryResultFilter from './QueryResultFilter';
import { JSONPath } from 'jsonpath-plus';
import React from 'react';
import classnames from 'classnames';
import iconv from 'iconv-lite';
import { getContentType, safeStringifyJSON, safeParseXML } from 'utils/common';
import { getCodeMirrorModeBasedOnContentType } from 'utils/common/codemirror';
import QueryResultPreview from './QueryResultPreview';
@@ -12,26 +11,18 @@ import { useState, useMemo, useEffect } from 'react';
import { useTheme } from 'providers/Theme/index';
import { getEncoding, prettifyJson, uuid } from 'utils/common/index';
const formatResponse = (data, dataBuffer, encoding, mode, filter) => {
if (data === undefined || !dataBuffer) {
const formatResponse = (data, dataRaw, mode, filter) => {
if (data === undefined || !dataRaw) {
return '';
}
// TODO: We need a better way to get the raw response-data here instead
// of using this dataBuffer param.
// Also, we only need the raw response-data and content-type to show the preview.
const rawData = iconv.decode(
Buffer.from(dataBuffer, "base64"),
iconv.encodingExists(encoding) ? encoding : "utf-8"
);
if (mode.includes('json')) {
try {
JSON.parse(rawData);
JSON.parse(dataRaw);
} catch (error) {
// If the response content-type is JSON and it fails parsing, its an invalid JSON.
// In that case, just show the response as it is in the preview.
return rawData;
return dataRaw;
}
if (filter) {
@@ -45,7 +36,7 @@ const formatResponse = (data, dataBuffer, encoding, mode, filter) => {
// Prettify the JSON string directly instead of parse->stringify to avoid
// issues like rounding numbers bigger than Number.MAX_SAFE_INTEGER etc.
return prettifyJson(rawData);
return prettifyJson(dataRaw);
}
if (mode.includes('xml')) {
@@ -60,7 +51,7 @@ const formatResponse = (data, dataBuffer, encoding, mode, filter) => {
return data;
}
return prettifyJson(rawData);
return prettifyJson(dataRaw);
};
const formatErrorMessage = (error) => {
@@ -76,14 +67,13 @@ const formatErrorMessage = (error) => {
return error;
};
const QueryResult = ({ item, collection, data, dataBuffer, width, disableRunEventListener, headers, error }) => {
const QueryResult = ({ item, collection, data, dataBuffer, dataRaw, width, disableRunEventListener, headers, error }) => {
const contentType = getContentType(headers);
const mode = getCodeMirrorModeBasedOnContentType(contentType, data);
const [filter, setFilter] = useState(null);
const responseEncoding = getEncoding(headers);
const formattedData = useMemo(
() => formatResponse(data, dataBuffer, responseEncoding, mode, filter),
[data, dataBuffer, responseEncoding, mode, filter]
() => formatResponse(data, dataRaw, mode, filter),
[data, dataRaw, mode, filter]
);
const { displayedTheme } = useTheme();

View File

@@ -53,6 +53,7 @@ const ResponsePane = ({ rightPaneWidth, item, collection }) => {
width={rightPaneWidth}
data={response.data}
dataBuffer={response.dataBuffer}
dataRaw={response.dataRaw}
headers={response.headers}
error={response.error}
key={item.filename}

View File

@@ -35,6 +35,7 @@ const ResponsePane = ({ rightPaneWidth, item, collection }) => {
disableRunEventListener={true}
data={responseReceived.data}
dataBuffer={responseReceived.dataBuffer}
dataRaw={responseReceived.dataRaw}
headers={responseReceived.headers}
error={error}
key={item.filename}

View File

@@ -190,9 +190,3 @@ export const generateUidBasedOnHash = (str) => {
};
export const stringifyIfNot = v => typeof v === 'string' ? v : String(v);
export const getEncoding = (headers) => {
// Parse the charset from content type: https://stackoverflow.com/a/33192813
const charsetMatch = /charset=([^()<>@,;:"/[\]?.=\s]*)/i.exec(headers?.['content-type'] || '');
return charsetMatch?.[1];
}

View File

@@ -10,6 +10,7 @@ export const sendNetworkRequest = async (item, collection, environment, runtimeV
data: response.data,
// Note that the Buffer is encoded as a base64 string, because Buffers / TypedArrays are not allowed in the redux store
dataBuffer: response.dataBuffer,
dataRaw: response.dataRaw,
headers: response.headers,
size: response.size,
status: response.status,

View File

@@ -23,12 +23,13 @@ const parseDataFromResponse = (response, disableParsingResponseJson = false) =>
const charsetValue = charsetMatch?.[1];
const dataBuffer = Buffer.from(response.data);
// Overwrite the original data for backwards compatibility
let data;
let dataRaw;
if (iconv.encodingExists(charsetValue)) {
data = iconv.decode(dataBuffer, charsetValue);
dataRaw = iconv.decode(dataBuffer, charsetValue);
} else {
data = iconv.decode(dataBuffer, 'utf-8');
dataRaw = iconv.decode(dataBuffer, 'utf-8');
}
let data = dataRaw;
// Try to parse response to JSON, this can quietly fail
try {
// Filter out ZWNBSP character
@@ -39,7 +40,7 @@ const parseDataFromResponse = (response, disableParsingResponseJson = false) =>
}
} catch { }
return { data, dataBuffer };
return { data, dataBuffer, dataRaw };
};
module.exports = {

View File

@@ -387,12 +387,13 @@ const parseDataFromResponse = (response, disableParsingResponseJson = false) =>
const charsetValue = charsetMatch?.[1];
const dataBuffer = Buffer.from(response.data);
// Overwrite the original data for backwards compatibility
let data;
let dataRaw;
if (iconv.encodingExists(charsetValue)) {
data = iconv.decode(dataBuffer, charsetValue);
dataRaw = iconv.decode(dataBuffer, charsetValue);
} else {
data = iconv.decode(dataBuffer, 'utf-8');
dataRaw = iconv.decode(dataBuffer, 'utf-8');
}
let data = dataRaw;
// Try to parse response to JSON, this can quietly fail
try {
// Filter out ZWNBSP character
@@ -403,7 +404,7 @@ const parseDataFromResponse = (response, disableParsingResponseJson = false) =>
}
} catch { }
return { data, dataBuffer };
return { data, dataBuffer, dataRaw };
};
@@ -695,7 +696,7 @@ const registerNetworkIpc = (mainWindow) => {
// Continue with the rest of the request lifecycle - post response vars, script, assertions, tests
const { data, dataBuffer } = parseDataFromResponse(response, request.__brunoDisableParsingResponseJson);
const { data, dataBuffer, dataRaw } = parseDataFromResponse(response, request.__brunoDisableParsingResponseJson);
response.data = data;
response.responseTime = responseTime;
@@ -811,6 +812,7 @@ const registerNetworkIpc = (mainWindow) => {
data: response.data,
dataBuffer: dataBuffer.toString('base64'),
size: Buffer.byteLength(dataBuffer),
dataRaw,
duration: responseTime ?? 0
};
} catch (error) {
@@ -1183,7 +1185,7 @@ const registerNetworkIpc = (mainWindow) => {
response = await axiosInstance(request);
timeEnd = Date.now();
const { data, dataBuffer } = parseDataFromResponse(response, request.__brunoDisableParsingResponseJson);
const { data, dataBuffer, dataRaw } = parseDataFromResponse(response, request.__brunoDisableParsingResponseJson);
response.data = data;
response.responseTime = response.headers.get('request-duration');
@@ -1206,6 +1208,7 @@ const registerNetworkIpc = (mainWindow) => {
duration: timeEnd - timeStart,
dataBuffer: dataBuffer.toString('base64'),
size: Buffer.byteLength(dataBuffer),
dataRaw,
data: response.data,
responseTime: response.headers.get('request-duration')
},
@@ -1213,7 +1216,7 @@ const registerNetworkIpc = (mainWindow) => {
});
} catch (error) {
if (error?.response && !axios.isCancel(error)) {
const { data, dataBuffer } = parseDataFromResponse(error.response);
const { data, dataBuffer, dataRaw } = parseDataFromResponse(error.response);
error.response.data = data;
timeEnd = Date.now();
@@ -1224,6 +1227,7 @@ const registerNetworkIpc = (mainWindow) => {
duration: timeEnd - timeStart,
dataBuffer: dataBuffer.toString('base64'),
size: Buffer.byteLength(dataBuffer),
dataRaw,
data: error.response.data,
responseTime: error.response.headers.get('request-duration')
};