mirror of
https://github.com/usebruno/bruno.git
synced 2025-06-26 06:51:54 +02:00
Fix serilization issues of bigint in json body --------- Co-authored-by: lohit <lohit.jiddimani@gmail.com>
This commit is contained in:
parent
b4fd350334
commit
9e5148f032
@ -67,6 +67,7 @@ if (!SERVER_RENDERED) {
|
|||||||
'bru.setVar(key,value)',
|
'bru.setVar(key,value)',
|
||||||
'bru.deleteVar(key)',
|
'bru.deleteVar(key)',
|
||||||
'bru.setNextRequest(requestName)',
|
'bru.setNextRequest(requestName)',
|
||||||
|
'req.disableParsingResponseJson()'
|
||||||
'bru.getRequestVar(key)',
|
'bru.getRequestVar(key)',
|
||||||
'bru.sleep(ms)'
|
'bru.sleep(ms)'
|
||||||
];
|
];
|
||||||
|
@ -17,8 +17,6 @@ const Timeline = ({ request, response }) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let requestData = safeStringifyJSON(request.data);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper className="pb-4 w-full">
|
<StyledWrapper className="pb-4 w-full">
|
||||||
<div>
|
<div>
|
||||||
@ -33,9 +31,10 @@ const Timeline = ({ request, response }) => {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
||||||
{requestData ? (
|
{request.data ? (
|
||||||
<pre className="line request">
|
<pre className="line request">
|
||||||
<span className="arrow">{'>'}</span> data {requestData}
|
<span className="arrow">{'>'}</span> data{' '}
|
||||||
|
<pre className="text-sm flex flex-wrap whitespace-break-spaces">{request.data}</pre>
|
||||||
</pre>
|
</pre>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
@ -272,7 +272,7 @@ const configureRequest = async (
|
|||||||
return axiosInstance;
|
return axiosInstance;
|
||||||
};
|
};
|
||||||
|
|
||||||
const parseDataFromResponse = (response) => {
|
const parseDataFromResponse = (response, disableParsingResponseJson = false) => {
|
||||||
// Parse the charset from content type: https://stackoverflow.com/a/33192813
|
// Parse the charset from content type: https://stackoverflow.com/a/33192813
|
||||||
const charsetMatch = /charset=([^()<>@,;:"/[\]?.=\s]*)/i.exec(response.headers['content-type'] || '');
|
const charsetMatch = /charset=([^()<>@,;:"/[\]?.=\s]*)/i.exec(response.headers['content-type'] || '');
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec#using_exec_with_regexp_literals
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec#using_exec_with_regexp_literals
|
||||||
@ -290,7 +290,9 @@ const parseDataFromResponse = (response) => {
|
|||||||
// Filter out ZWNBSP character
|
// Filter out ZWNBSP character
|
||||||
// https://gist.github.com/antic183/619f42b559b78028d1fe9e7ae8a1352d
|
// https://gist.github.com/antic183/619f42b559b78028d1fe9e7ae8a1352d
|
||||||
data = data.replace(/^\uFEFF/, '');
|
data = data.replace(/^\uFEFF/, '');
|
||||||
|
if(!disableParsingResponseJson) {
|
||||||
data = JSON.parse(data);
|
data = JSON.parse(data);
|
||||||
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
return { data, dataBuffer };
|
return { data, dataBuffer };
|
||||||
@ -540,7 +542,7 @@ const registerNetworkIpc = (mainWindow) => {
|
|||||||
|
|
||||||
// Continue with the rest of the request lifecycle - post response vars, script, assertions, tests
|
// Continue with the rest of the request lifecycle - post response vars, script, assertions, tests
|
||||||
|
|
||||||
const { data, dataBuffer } = parseDataFromResponse(response);
|
const { data, dataBuffer } = parseDataFromResponse(response, request.__brunoDisableParsingResponseJson);
|
||||||
response.data = data;
|
response.data = data;
|
||||||
|
|
||||||
response.responseTime = responseTime;
|
response.responseTime = responseTime;
|
||||||
@ -701,7 +703,7 @@ const registerNetworkIpc = (mainWindow) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data } = parseDataFromResponse(response);
|
const { data } = parseDataFromResponse(response, request.__brunoDisableParsingResponseJson);
|
||||||
response.data = data;
|
response.data = data;
|
||||||
|
|
||||||
await runPostResponse(
|
await runPostResponse(
|
||||||
@ -969,7 +971,7 @@ const registerNetworkIpc = (mainWindow) => {
|
|||||||
response = await axiosInstance(request);
|
response = await axiosInstance(request);
|
||||||
timeEnd = Date.now();
|
timeEnd = Date.now();
|
||||||
|
|
||||||
const { data, dataBuffer } = parseDataFromResponse(response);
|
const { data, dataBuffer } = parseDataFromResponse(response, request.__brunoDisableParsingResponseJson);
|
||||||
response.data = data;
|
response.data = data;
|
||||||
response.responseTime = response.headers.get('request-duration');
|
response.responseTime = response.headers.get('request-duration');
|
||||||
|
|
||||||
|
@ -59,14 +59,6 @@ const interpolateVars = (request, envVars = {}, runtimeVariables = {}, processEn
|
|||||||
const contentType = getContentType(request.headers);
|
const contentType = getContentType(request.headers);
|
||||||
|
|
||||||
if (contentType.includes('json')) {
|
if (contentType.includes('json')) {
|
||||||
if (typeof request.data === 'object') {
|
|
||||||
try {
|
|
||||||
let parsed = JSON.stringify(request.data);
|
|
||||||
parsed = _interpolate(parsed);
|
|
||||||
request.data = JSON.parse(parsed);
|
|
||||||
} catch (err) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof request.data === 'string') {
|
if (typeof request.data === 'string') {
|
||||||
if (request.data.length) {
|
if (request.data.length) {
|
||||||
request.data = _interpolate(request.data);
|
request.data = _interpolate(request.data);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
const os = require('os');
|
const os = require('os');
|
||||||
const { get, each, filter, extend, compact } = require('lodash');
|
const { get, each, filter, extend, compact } = require('lodash');
|
||||||
const decomment = require('decomment');
|
const decomment = require('decomment');
|
||||||
var JSONbig = require('json-bigint');
|
|
||||||
const FormData = require('form-data');
|
const FormData = require('form-data');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
@ -342,16 +341,10 @@ const prepareRequest = (item, collection) => {
|
|||||||
if (!contentTypeDefined) {
|
if (!contentTypeDefined) {
|
||||||
axiosRequest.headers['content-type'] = 'application/json';
|
axiosRequest.headers['content-type'] = 'application/json';
|
||||||
}
|
}
|
||||||
let jsonBody;
|
|
||||||
try {
|
try {
|
||||||
jsonBody = decomment(request?.body?.json);
|
axiosRequest.data = decomment(request?.body?.json);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
jsonBody = request?.body?.json;
|
axiosRequest.data = request?.body?.json;
|
||||||
}
|
|
||||||
try {
|
|
||||||
axiosRequest.data = JSONbig.parse(jsonBody);
|
|
||||||
} catch (error) {
|
|
||||||
axiosRequest.data = jsonBody;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ describe('prepare-request: prepareRequest', () => {
|
|||||||
describe('Decomments request body', () => {
|
describe('Decomments request body', () => {
|
||||||
it('If request body is valid JSON', async () => {
|
it('If request body is valid JSON', async () => {
|
||||||
const body = { mode: 'json', json: '{\n"test": "{{someVar}}" // comment\n}' };
|
const body = { mode: 'json', json: '{\n"test": "{{someVar}}" // comment\n}' };
|
||||||
const expected = { test: '{{someVar}}' };
|
const expected = '{\n"test": "{{someVar}}" \n}';
|
||||||
const result = prepareRequest({ request: { body } }, {});
|
const result = prepareRequest({ request: { body } }, {});
|
||||||
expect(result.data).toEqual(expected);
|
expect(result.data).toEqual(expected);
|
||||||
});
|
});
|
||||||
|
@ -1,11 +1,34 @@
|
|||||||
class BrunoRequest {
|
class BrunoRequest {
|
||||||
|
/**
|
||||||
|
* The following properties are available as shorthand:
|
||||||
|
* - req.url
|
||||||
|
* - req.method
|
||||||
|
* - req.headers
|
||||||
|
* - req.timeout
|
||||||
|
* - req.body
|
||||||
|
*
|
||||||
|
* Above shorthands are useful for accessing the request properties directly in the scripts
|
||||||
|
* It must be noted that the user cannot set these properties directly.
|
||||||
|
* They should use the respective setter methods to set these properties.
|
||||||
|
*/
|
||||||
constructor(req) {
|
constructor(req) {
|
||||||
this.req = req;
|
this.req = req;
|
||||||
this.url = req.url;
|
this.url = req.url;
|
||||||
this.method = req.method;
|
this.method = req.method;
|
||||||
this.headers = req.headers;
|
this.headers = req.headers;
|
||||||
this.body = req.data;
|
|
||||||
this.timeout = req.timeout;
|
this.timeout = req.timeout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We automatically parse the JSON body if the content type is JSON
|
||||||
|
* This is to make it easier for the user to access the body directly
|
||||||
|
*
|
||||||
|
* It must be noted that the request data is always a string and is what gets sent over the network
|
||||||
|
* If the user wants to access the raw data, they can use getBody({raw: true}) method
|
||||||
|
*/
|
||||||
|
const isJson = this.hasJSONContentType(this.req.headers);
|
||||||
|
if (isJson) {
|
||||||
|
this.body = this.__safeParseJSON(req.data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getUrl() {
|
getUrl() {
|
||||||
@ -13,6 +36,7 @@ class BrunoRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setUrl(url) {
|
setUrl(url) {
|
||||||
|
this.url = url;
|
||||||
this.req.url = url;
|
this.req.url = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,6 +61,7 @@ class BrunoRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setMethod(method) {
|
setMethod(method) {
|
||||||
|
this.method = method;
|
||||||
this.req.method = method;
|
this.req.method = method;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,6 +70,7 @@ class BrunoRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setHeaders(headers) {
|
setHeaders(headers) {
|
||||||
|
this.headers = headers;
|
||||||
this.req.headers = headers;
|
this.req.headers = headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,15 +79,60 @@ class BrunoRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setHeader(name, value) {
|
setHeader(name, value) {
|
||||||
|
this.headers[name] = value;
|
||||||
this.req.headers[name] = value;
|
this.req.headers[name] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
getBody() {
|
hasJSONContentType(headers) {
|
||||||
|
const contentType = headers?.['Content-Type'] || headers?.['content-type'] || '';
|
||||||
|
return contentType.includes('json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the body of the request
|
||||||
|
*
|
||||||
|
* We automatically parse and return the JSON body if the content type is JSON
|
||||||
|
* If the user wants the raw body, they can pass the raw option as true
|
||||||
|
*/
|
||||||
|
getBody(options = {}) {
|
||||||
|
if (options.raw) {
|
||||||
return this.req.data;
|
return this.req.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
setBody(data) {
|
const isJson = this.hasJSONContentType(this.req.headers);
|
||||||
|
if (isJson) {
|
||||||
|
return this.__safeParseJSON(this.req.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.req.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the content type is JSON and if the data is an object
|
||||||
|
* - We set the body property as the object itself
|
||||||
|
* - We set the request data as the stringified JSON as it is what gets sent over the network
|
||||||
|
* Otherwise
|
||||||
|
* - We set the request data as the data itself
|
||||||
|
* - We set the body property as the data itself
|
||||||
|
*
|
||||||
|
* If the user wants to override this behavior, they can pass the raw option as true
|
||||||
|
*/
|
||||||
|
setBody(data, options = {}) {
|
||||||
|
if (options.raw) {
|
||||||
this.req.data = data;
|
this.req.data = data;
|
||||||
|
this.body = data;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isJson = this.hasJSONContentType(this.req.headers);
|
||||||
|
if (isJson && this.__isObject(data)) {
|
||||||
|
this.body = data;
|
||||||
|
this.req.data = this.__safeStringifyJSON(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.req.data = data;
|
||||||
|
this.body = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
setMaxRedirects(maxRedirects) {
|
setMaxRedirects(maxRedirects) {
|
||||||
@ -73,8 +144,34 @@ class BrunoRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(timeout) {
|
setTimeout(timeout) {
|
||||||
|
this.timeout = timeout;
|
||||||
this.req.timeout = timeout;
|
this.req.timeout = timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__safeParseJSON(str) {
|
||||||
|
try {
|
||||||
|
return JSON.parse(str);
|
||||||
|
} catch (e) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__safeStringifyJSON(obj) {
|
||||||
|
try {
|
||||||
|
return JSON.stringify(obj);
|
||||||
|
} catch (e) {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__isObject(obj) {
|
||||||
|
return obj !== null && typeof obj === 'object';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
disableParsingResponseJson() {
|
||||||
|
this.req.__brunoDisableParsingResponseJson = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = BrunoRequest;
|
module.exports = BrunoRequest;
|
||||||
|
44
packages/bruno-tests/collection/echo/echo bigint.bru
Normal file
44
packages/bruno-tests/collection/echo/echo bigint.bru
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
meta {
|
||||||
|
name: echo bigint
|
||||||
|
type: http
|
||||||
|
seq: 6
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: {{host}}/api/echo/json
|
||||||
|
body: json
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
foo: bar
|
||||||
|
}
|
||||||
|
|
||||||
|
auth:basic {
|
||||||
|
username: asd
|
||||||
|
password: j
|
||||||
|
}
|
||||||
|
|
||||||
|
auth:bearer {
|
||||||
|
token:
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"hello": 990531470713421825
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body:text {
|
||||||
|
{
|
||||||
|
"hello": 990531470713421825
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {
|
||||||
|
res.status: eq 200
|
||||||
|
}
|
||||||
|
|
||||||
|
script:pre-request {
|
||||||
|
bru.setVar("foo", "foo-world-2");
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user