mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-24 21:25:45 +00:00
feat: introduce res.getSize() helper (header/body/total) (#5018)
* feat: introduce `res.getSize()` helper (header/body/total) * fix: unit test * rm: request-duration from collection runner header * change: api for getSize * fix * improve: getSize method * add: todo comment --------- Co-authored-by: lohit <lohit@usebruno.com>
This commit is contained in:
@@ -43,7 +43,11 @@ const STATIC_API_HINTS = {
|
||||
'res.getHeaders()',
|
||||
'res.getBody()',
|
||||
'res.setBody(data)',
|
||||
'res.getResponseTime()'
|
||||
'res.getResponseTime()',
|
||||
'res.getSize()',
|
||||
'res.getSize().header',
|
||||
'res.getSize().body',
|
||||
'res.getSize().total',
|
||||
],
|
||||
bru: [
|
||||
'bru',
|
||||
|
||||
@@ -415,8 +415,9 @@ const runSingleRequest = async function (
|
||||
/** @type {import('axios').AxiosResponse} */
|
||||
response = await axiosInstance(request);
|
||||
|
||||
const { data } = parseDataFromResponse(response, request.__brunoDisableParsingResponseJson);
|
||||
const { data, dataBuffer } = parseDataFromResponse(response, request.__brunoDisableParsingResponseJson);
|
||||
response.data = data;
|
||||
response.dataBuffer = dataBuffer;
|
||||
|
||||
// Prevents the duration on leaking to the actual result
|
||||
responseTime = response.headers.get('request-duration');
|
||||
@@ -428,8 +429,9 @@ const runSingleRequest = async function (
|
||||
}
|
||||
} catch (err) {
|
||||
if (err?.response) {
|
||||
const { data } = parseDataFromResponse(err?.response);
|
||||
const { data, dataBuffer } = parseDataFromResponse(err?.response);
|
||||
err.response.data = data;
|
||||
err.response.dataBuffer = dataBuffer;
|
||||
response = err.response;
|
||||
|
||||
// Prevents the duration on leaking to the actual result
|
||||
|
||||
@@ -26,6 +26,11 @@ const replacements = {
|
||||
'pm\\.response\\.headers\\.get\\(': 'res.getHeader(',
|
||||
'pm\\.response\\.to\\.have\\.body\\(': 'expect(res.getBody()).to.equal(',
|
||||
'pm\\.response\\.to\\.have\\.header\\(': 'expect(res.getHeaders()).to.have.property(',
|
||||
'pm\\.response\\.size\\(\\)': 'res.getSize()',
|
||||
'pm\\.response\\.size\\(\\)\\.body': 'res.getSize().body',
|
||||
'pm\\.response\\.responseSize': 'res.getSize().body',
|
||||
'pm\\.response\\.size\\(\\)\\.header': 'res.getSize().header',
|
||||
'pm\\.response\\.size\\(\\)\\.total': 'res.getSize().total',
|
||||
'pm\\.environment\\.name': 'bru.getEnvName()',
|
||||
'pm\\.response\\.status': 'res.statusText',
|
||||
'pm\\.response\\.headers': 'res.getHeaders()',
|
||||
|
||||
@@ -84,6 +84,11 @@ const simpleTranslations = {
|
||||
'pm.response.responseTime': 'res.getResponseTime()',
|
||||
'pm.response.statusText': 'res.statusText',
|
||||
'pm.response.headers': 'res.getHeaders()',
|
||||
'pm.response.size': 'res.getSize',
|
||||
'pm.response.responseSize': 'res.getSize().body',
|
||||
'pm.response.size().body': 'res.getSize().body',
|
||||
'pm.response.size().header': 'res.getSize().header',
|
||||
'pm.response.size().total': 'res.getSize().total',
|
||||
|
||||
// Execution control
|
||||
'pm.execution.skipRequest': 'bru.runner.skipRequest',
|
||||
|
||||
@@ -9,6 +9,11 @@ describe('postmanTranslations - response commands', () => {
|
||||
const responseJson = pm.response.json();
|
||||
const responseStatus = pm.response.status;
|
||||
const responseHeaders = pm.response.headers;
|
||||
const responseSize = pm.response.size();
|
||||
const responseSizeBody = pm.response.size().body;
|
||||
const responseSizeHeader = pm.response.size().header;
|
||||
const responseSizeTotal = pm.response.size().total;
|
||||
const responseSizeBody2 = pm.response.responseSize;
|
||||
|
||||
pm.test('Status code is 200', function() {
|
||||
pm.response.to.have.status(200);
|
||||
@@ -21,6 +26,11 @@ describe('postmanTranslations - response commands', () => {
|
||||
const responseJson = res.getBody();
|
||||
const responseStatus = res.statusText;
|
||||
const responseHeaders = res.getHeaders();
|
||||
const responseSize = res.getSize();
|
||||
const responseSizeBody = res.getSize().body;
|
||||
const responseSizeHeader = res.getSize().header;
|
||||
const responseSizeTotal = res.getSize().total;
|
||||
const responseSizeBody2 = res.getSize().body;
|
||||
|
||||
test('Status code is 200', function() {
|
||||
expect(res.getStatus()).to.equal(200);
|
||||
@@ -29,6 +39,3 @@ describe('postmanTranslations - response commands', () => {
|
||||
expect(postmanTranslation(inputScript)).toBe(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -553,4 +553,35 @@ describe('Response Translation', () => {
|
||||
expect(res.getBody()).to.equal({"status": "ok"});
|
||||
`);
|
||||
});
|
||||
|
||||
// --- getSize translations ---------------------------
|
||||
it('should translate pm.response.size()', () => {
|
||||
const code = 'const size = pm.response.size();';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toBe('const size = res.getSize();');
|
||||
});
|
||||
|
||||
it('should translate pm.response.size().body', () => {
|
||||
const code = 'const bodySize = pm.response.size().body;';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toBe('const bodySize = res.getSize().body;');
|
||||
});
|
||||
|
||||
it('should translate pm.response.size().header', () => {
|
||||
const code = 'const headerSize = pm.response.size().header;';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toBe('const headerSize = res.getSize().header;');
|
||||
});
|
||||
|
||||
it('should translate pm.response.size().total', () => {
|
||||
const code = 'const totalSize = pm.response.size().total;';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toBe('const totalSize = res.getSize().total;');
|
||||
});
|
||||
|
||||
it('should translate pm.response.responseSize alias', () => {
|
||||
const code = 'const responseSize = pm.response.responseSize;';
|
||||
const translatedCode = translateCode(code);
|
||||
expect(translatedCode).toBe('const responseSize = res.getSize().body;');
|
||||
});
|
||||
});
|
||||
@@ -876,8 +876,8 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
statusText: response.statusText,
|
||||
headers: response.headers,
|
||||
data: response.data,
|
||||
dataBuffer: dataBuffer.toString('base64'),
|
||||
size: Buffer.byteLength(dataBuffer),
|
||||
dataBuffer: response.dataBuffer.toString('base64'),
|
||||
size: Buffer.byteLength(response.dataBuffer),
|
||||
duration: responseTime ?? 0,
|
||||
timeline: response.timeline
|
||||
};
|
||||
@@ -1153,6 +1153,7 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
response.data = data;
|
||||
response.dataBuffer = dataBuffer;
|
||||
response.responseTime = response.headers.get('request-duration');
|
||||
response.headers.delete('request-duration');
|
||||
|
||||
// save cookies
|
||||
if (preferencesUtil.shouldStoreCookies()) {
|
||||
@@ -1174,8 +1175,8 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
dataBuffer: dataBuffer.toString('base64'),
|
||||
size: Buffer.byteLength(dataBuffer),
|
||||
data: response.data,
|
||||
responseTime: response.responseTime,
|
||||
timeline: response.timeline,
|
||||
responseTime: response.headers.get('request-duration')
|
||||
},
|
||||
...eventData
|
||||
});
|
||||
@@ -1187,6 +1188,8 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
|
||||
if (error?.response) {
|
||||
const { data, dataBuffer } = parseDataFromResponse(error.response);
|
||||
error.response.responseTime = error.response.headers.get('request-duration');
|
||||
error.response.headers.delete('request-duration');
|
||||
error.response.data = data;
|
||||
error.response.dataBuffer = dataBuffer;
|
||||
|
||||
@@ -1199,8 +1202,8 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
dataBuffer: dataBuffer.toString('base64'),
|
||||
size: Buffer.byteLength(dataBuffer),
|
||||
data: error.response.data,
|
||||
responseTime: error.response.responseTime,
|
||||
timeline: error.response.timeline,
|
||||
responseTime: error.response.headers.get('request-duration')
|
||||
};
|
||||
|
||||
// if we get a response from the server, we consider it as a success
|
||||
|
||||
@@ -52,6 +52,46 @@ class BrunoResponse {
|
||||
this.body = clonedData;
|
||||
}
|
||||
|
||||
// TODO: Refactor: dataBuffer size calculation should be handled in a shared utility so it can be passed and reused across the application
|
||||
getSize() {
|
||||
if (!this.res) {
|
||||
return { header: 0, body: 0, total: 0 };
|
||||
}
|
||||
|
||||
const { data, dataBuffer, headers } = this.res;
|
||||
let bodySize = 0;
|
||||
|
||||
// Use raw received bytes
|
||||
if (Buffer.isBuffer(dataBuffer)) {
|
||||
bodySize = dataBuffer.length;
|
||||
} else {
|
||||
// Use server-reported Content-Length
|
||||
const contentLength = headers && (headers['content-length'] || headers['Content-Length']);
|
||||
if (contentLength && !isNaN(contentLength)) {
|
||||
bodySize = parseInt(contentLength, 10);
|
||||
} else if (data != null) {
|
||||
// Manual calculation
|
||||
const raw = typeof data === 'string' ? data : JSON.stringify(data);
|
||||
bodySize = Buffer.byteLength(raw);
|
||||
}
|
||||
}
|
||||
|
||||
const headerLines = [
|
||||
`HTTP/1.1 ${this.res.status} ${this.res.statusText}`,
|
||||
...Object.entries(this.res.headers || {}).flatMap(([key, value]) =>
|
||||
Array.isArray(value)
|
||||
? value.map((v) => `${key}: ${v}`)
|
||||
: [`${key}: ${value}`]
|
||||
),
|
||||
'',
|
||||
''
|
||||
];
|
||||
const headerSize = Buffer.byteLength(headerLines.join('\r\n'));
|
||||
|
||||
return { header: headerSize, body: bodySize, total: headerSize + bodySize };
|
||||
|
||||
}
|
||||
|
||||
getDataBuffer() {
|
||||
return this.res ? this.res.dataBuffer : null;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,12 @@ const addBrunoResponseShimToContext = (vm, res) => {
|
||||
vm.setProp(resFn, 'setBody', setBody);
|
||||
setBody.dispose();
|
||||
|
||||
let getSize = vm.newFunction('getSize', function () {
|
||||
return marshallToVm(res.getSize(), vm);
|
||||
});
|
||||
vm.setProp(resFn, 'getSize', getSize);
|
||||
getSize.dispose();
|
||||
|
||||
vm.setProp(vm.global, 'res', resFn);
|
||||
resFn.dispose();
|
||||
};
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
meta {
|
||||
name: getSize
|
||||
type: http
|
||||
seq: 8
|
||||
}
|
||||
|
||||
get {
|
||||
url: https://www.httpfaker.org/api/random/json?size=1mb
|
||||
body: none
|
||||
auth: inherit
|
||||
}
|
||||
|
||||
params:query {
|
||||
size: 1mb
|
||||
}
|
||||
|
||||
script:post-response {
|
||||
console.log(res.getSize())
|
||||
}
|
||||
|
||||
tests {
|
||||
test("test body size", function() {
|
||||
const bodySize = res.getSize().body;
|
||||
expect(bodySize === 1048934).to.be.true;
|
||||
});
|
||||
|
||||
test("test header size", function() {
|
||||
const bodySize = res.getSize().header;
|
||||
expect(bodySize === 305).to.be.true;
|
||||
});
|
||||
|
||||
test("test total size", function() {
|
||||
const sizes = res.getSize();
|
||||
expect(sizes.total).to.equal(sizes.header + sizes.body);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user