Fix: Inconsistent JSON parsing and formatting in res.body and Res-preview (#4103)

* Fix: Revert selective JSON parsing where string response is not parsed

- Revert "Merge pull request #3706 from Pragadesh-45/fix/response-format-updates"
  - e897dc1eb0
- Revert "Merge pull request #3676 from pooja-bruno/fix/string-json-response"
  - 1f2bee1f90

* Fix: Revert interpreting Assert RHS-value wrapped in quotes literally

- Revert "Merge pull request #3806 from Pragadesh-45/fix/handle-assert-results"
  - 63d3cb380d
- Revert "Merge pull request #3805 from Pragadesh-45/fix/handle-assert-results"
  - 6abd063749

* Fix: Inconsistent JSON formatting in preview when encoded value is a string

* Fix: Prettify JSON for Res-preview without parsing to avoid JS specific roundings

* Fix(testbench): req.body is always Buffer after the binary req body related changes

* Added `/api/echo/custom` where response can be configured using request itself

* Added tests for validating Assert and Response-preview

Co-authored-by: Pragadesh-45 <temporaryg7904@gmail.com>

* Handle char-encoding in Response-preview and added more tests

* Updated API endpoint in tests to use httpfaker api

* QuickJS (Safe Mode) exec logic to handle template literals similar to Developer Mode

* Safe Mode bru.runRequest to return statusText similar to Developer Mode

---------

Co-authored-by: ramki-bruno <ramki@usebruno.com>
Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
This commit is contained in:
Pragadesh-45
2025-03-13 00:49:57 +05:30
committed by GitHub
parent 0fbbe8a996
commit 6a85635c49
35 changed files with 669 additions and 53 deletions

View File

@@ -22,6 +22,12 @@ const toNumber = (value) => {
return Number.isInteger(num) ? parseInt(value, 10) : parseFloat(value);
};
const removeQuotes = (str) => {
if ((str.startsWith('"') && str.endsWith('"')) || (str.startsWith("'") && str.endsWith("'"))) {
return str.slice(1, -1);
}
return str;
};
const executeQuickJsVm = ({ script: externalScript, context: externalContext, scriptType = 'template-literal' }) => {
if (!externalScript?.length || typeof externalScript !== 'string') {
@@ -29,16 +35,26 @@ const executeQuickJsVm = ({ script: externalScript, context: externalContext, sc
}
externalScript = externalScript?.trim();
if (!isNaN(Number(externalScript))) {
return Number(externalScript);
if(scriptType === 'template-literal') {
if (!isNaN(Number(externalScript))) {
const number = Number(externalScript);
// Check if the number is too high. Too high number might get altered, see #1000
if (number > Number.MAX_SAFE_INTEGER) {
return externalScript;
}
return toNumber(externalScript);
}
if (externalScript === 'true') return true;
if (externalScript === 'false') return false;
if (externalScript === 'null') return null;
if (externalScript === 'undefined') return undefined;
externalScript = removeQuotes(externalScript);
}
if (externalScript === 'true') return true;
if (externalScript === 'false') return false;
if (externalScript === 'null') return null;
if (externalScript === 'undefined') return undefined;
const vm = QuickJSSyncContext;
try {
@@ -78,16 +94,6 @@ const executeQuickJsVmAsync = async ({ script: externalScript, context: external
}
externalScript = externalScript?.trim();
if (!isNaN(Number(externalScript))) {
return toNumber(externalScript);
}
if (externalScript === 'true') return true;
if (externalScript === 'false') return false;
if (externalScript === 'null') return null;
if (externalScript === 'undefined') return undefined;
try {
const module = await newQuickJSWASMModule();
const vm = module.newContext();

View File

@@ -189,8 +189,8 @@ const addBruShimToContext = (vm, bru) => {
const promise = vm.newPromise();
bru.runRequest(vm.dump(args))
.then((response) => {
const { status, headers, data, dataBuffer, size } = response || {};
promise.resolve(marshallToVm(cleanJson({ status, headers, data, dataBuffer, size }), vm));
const { status, statusText, headers, data, dataBuffer, size } = response || {};
promise.resolve(marshallToVm(cleanJson({ status, statusText, headers, data, dataBuffer, size }), vm));
})
.catch((err) => {
promise.resolve(

View File

@@ -85,6 +85,14 @@ const evaluateJsTemplateLiteral = (templateLiteral, context) => {
return undefined;
}
if (templateLiteral.startsWith('"') && templateLiteral.endsWith('"')) {
return templateLiteral.slice(1, -1);
}
if (templateLiteral.startsWith("'") && templateLiteral.endsWith("'")) {
return templateLiteral.slice(1, -1);
}
if (!isNaN(templateLiteral)) {
const number = Number(templateLiteral);
// Check if the number is too high. Too high number might get altered, see #1000