@usebruno/js 0.46.1 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +9 -7
- package/src/bru.js +173 -75
- package/src/bruno-request.js +15 -7
- package/src/bruno-response.js +4 -0
- package/src/cookie-list.js +272 -0
- package/src/header-list.js +497 -0
- package/src/index.js +27 -2
- package/src/property-list.js +184 -0
- package/src/readonly-property-list.js +227 -0
- package/src/runtime/assert-runtime.js +164 -10
- package/src/runtime/script-runtime.js +55 -6
- package/src/runtime/test-runtime.js +19 -1
- package/src/runtime/vars-runtime.js +20 -3
- package/src/sandbox/bundle-browser-rollup.js +72 -66
- package/src/sandbox/bundle-libraries.js +10 -2
- package/src/sandbox/quickjs/index.js +8 -41
- package/src/sandbox/quickjs/shims/bru.js +31 -1
- package/src/sandbox/quickjs/shims/bruno-request.js +24 -3
- package/src/sandbox/quickjs/shims/bruno-response.js +57 -5
- package/src/sandbox/quickjs/shims/bruno-response.spec.js +91 -0
- package/src/sandbox/quickjs/shims/lib/uuid.spec.js +166 -0
- package/src/sandbox/quickjs/shims/require.js +56 -0
- package/src/sandbox/quickjs/shims/require.spec.js +154 -0
- package/src/sandbox/quickjs/shims/test.js +175 -2
- package/src/sandbox/quickjs/utils/property-list-bridge.js +190 -0
- package/src/sandbox/quickjs/utils/test-helpers.js +31 -0
- package/src/utils/error-formatter.js +345 -20
- package/src/utils/error-formatter.spec.js +683 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usebruno/js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.48.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
"prepack": "npm run test"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@usebruno/common": "0.
|
|
17
|
-
"@usebruno/query": "0.2.
|
|
16
|
+
"@usebruno/common": "0.22.0",
|
|
17
|
+
"@usebruno/query": "0.2.2",
|
|
18
18
|
"ajv": "^8.12.0",
|
|
19
19
|
"ajv-formats": "^2.1.1",
|
|
20
20
|
"atob": "^2.1.2",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"chai-string": "^1.5.0",
|
|
25
25
|
"cheerio": "^1.0.0",
|
|
26
26
|
"crypto-js": "^4.2.0",
|
|
27
|
+
"handlebars": "^4.7.9",
|
|
27
28
|
"json-query": "^2.2.2",
|
|
28
29
|
"jsonwebtoken": "^9.0.3",
|
|
29
30
|
"lodash": "^4.17.21",
|
|
@@ -31,17 +32,18 @@
|
|
|
31
32
|
"nanoid": "3.3.8",
|
|
32
33
|
"node-fetch": "^2.7.0",
|
|
33
34
|
"path": "^0.12.7",
|
|
34
|
-
"quickjs-emscripten": "^0.
|
|
35
|
+
"quickjs-emscripten": "^0.32.0",
|
|
35
36
|
"tv4": "^1.3.0",
|
|
36
|
-
"uuid": "^
|
|
37
|
+
"uuid": "^10.0.0",
|
|
37
38
|
"xml-formatter": "^3.5.0",
|
|
38
39
|
"xml2js": "^0.6.2",
|
|
39
40
|
"yaml": "^2.3.4"
|
|
40
41
|
},
|
|
41
42
|
"devDependencies": {
|
|
42
43
|
"@rollup/plugin-commonjs": "^23.0.2",
|
|
44
|
+
"@rollup/plugin-json": "^6.0.0",
|
|
43
45
|
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
44
|
-
"rollup": "
|
|
45
|
-
"rollup
|
|
46
|
+
"@rollup/plugin-terser": "^1.0.0",
|
|
47
|
+
"rollup": "3.30.0"
|
|
46
48
|
}
|
|
47
49
|
}
|
package/src/bru.js
CHANGED
|
@@ -3,31 +3,90 @@ const { uuid } = require('./utils');
|
|
|
3
3
|
const xmlFormat = require('xml-formatter');
|
|
4
4
|
const { interpolate: _interpolate } = require('@usebruno/common');
|
|
5
5
|
const { sendRequest, createSendRequest } = require('@usebruno/requests').scripting;
|
|
6
|
-
const { jar: createCookieJar } = require('@usebruno/requests').cookies;
|
|
7
|
-
|
|
6
|
+
const { jar: createCookieJar, getCookiesForUrl } = require('@usebruno/requests').cookies;
|
|
7
|
+
const CookieList = require('./cookie-list');
|
|
8
|
+
const Handlebars = require('handlebars');
|
|
9
|
+
|
|
10
|
+
const VISUALIZATION_CLEAR = '__clear__';
|
|
11
|
+
const MAX_TEMPLATE_LENGTH = 1_000_000; // 1 million characters
|
|
12
|
+
/*
|
|
13
|
+
* All Handlebars.compile() options (v4.x):
|
|
14
|
+
* data - set false to disable @data tracking
|
|
15
|
+
* compat - enable recursive field lookup
|
|
16
|
+
* knownHelpers - hash of helpers known at compile time (optimization)
|
|
17
|
+
* knownHelpersOnly - only allow known helpers (optimization) [SAFE]
|
|
18
|
+
* noEscape - skip HTML escaping of content [SAFE]
|
|
19
|
+
* strict - throw on missing fields instead of ignoring [SAFE]
|
|
20
|
+
* assumeObjects - skip object existence checks on paths [SAFE]
|
|
21
|
+
* preventIndent - disable auto-indent for partials [SAFE]
|
|
22
|
+
* ignoreStandalone - disable standalone tag removal [SAFE]
|
|
23
|
+
* explicitPartialContext - disable implicit context for partials [SAFE]
|
|
24
|
+
*
|
|
25
|
+
* Excluded from allowlist:
|
|
26
|
+
* data, compat, knownHelpers - can alter template resolution in unexpected ways
|
|
27
|
+
* allowProtoPropertiesByDefault, allowProtoMethodsByDefault - defense-in-depth against
|
|
28
|
+
* prototype traversal. Handlebars >=4.3.0 fixed the original CVE-2019-19919 and >=4.7.0
|
|
29
|
+
* hardcodes blocks on __proto__, constructor, etc. even when these flags are true, but
|
|
30
|
+
* we still exclude them to avoid relaxing the security posture.
|
|
31
|
+
* https://nvd.nist.gov/vuln/detail/CVE-2019-19919
|
|
32
|
+
*
|
|
33
|
+
* Use `dangerouslyAllowAllOptions: true` in data.options to bypass the allowlist.
|
|
34
|
+
*/
|
|
35
|
+
const SAFE_HBS_OPTIONS = new Set([
|
|
36
|
+
'noEscape', 'strict', 'assumeObjects', 'preventIndent',
|
|
37
|
+
'ignoreStandalone', 'explicitPartialContext', 'knownHelpersOnly'
|
|
38
|
+
]);
|
|
8
39
|
const variableNameRegex = /^[\w-.]*$/;
|
|
9
40
|
|
|
10
41
|
class Bru {
|
|
11
42
|
/**
|
|
12
|
-
* @param {
|
|
13
|
-
* @
|
|
14
|
-
* @
|
|
15
|
-
* @
|
|
16
|
-
* @
|
|
17
|
-
* @
|
|
18
|
-
* @
|
|
19
|
-
* @
|
|
20
|
-
* @
|
|
21
|
-
* @
|
|
22
|
-
* @
|
|
23
|
-
* @
|
|
24
|
-
* @
|
|
25
|
-
* @
|
|
26
|
-
* @
|
|
27
|
-
* @
|
|
28
|
-
* @
|
|
43
|
+
* @param {object} options - Single options object (destructured)
|
|
44
|
+
* @property {string} options.runtime - The runtime environment ('quickjs' or 'nodevm')
|
|
45
|
+
* @property {object} [options.envVariables={}] - Environment variables
|
|
46
|
+
* @property {object} [options.runtimeVariables={}] - Runtime variables
|
|
47
|
+
* @property {object} [options.processEnvVars={}] - Process environment variables (deep cloned)
|
|
48
|
+
* @property {string} [options.collectionPath] - Path to the collection
|
|
49
|
+
* @property {function} [options.historyLogger] - History logger function
|
|
50
|
+
* @property {function} [options.setVisualizations] - Visualizations setter function
|
|
51
|
+
* @property {object} [options.secretVariables={}] - Secret variables (deep cloned)
|
|
52
|
+
* @property {object} [options.collectionVariables={}] - Collection-level variables
|
|
53
|
+
* @property {object} [options.folderVariables={}] - Folder-level variables
|
|
54
|
+
* @property {object} [options.requestVariables={}] - Request-level variables
|
|
55
|
+
* @property {object} [options.globalEnvironmentVariables={}] - Global environment variables
|
|
56
|
+
* @property {object} [options.oauth2CredentialVariables={}] - OAuth2 credential variables
|
|
57
|
+
* @property {object} [options.iterationDetails] - Iteration details for runner
|
|
58
|
+
* @property {string} [options.collectionName] - Name of the collection
|
|
59
|
+
* @property {object} [options.promptVariables={}] - Prompt variables
|
|
60
|
+
* @property {object} [options.certsAndProxyConfig] - Configuration for bru.sendRequest (proxy, certs, TLS)
|
|
61
|
+
* @property {string} [options.certsAndProxyConfig.collectionPath] - Path to the collection
|
|
62
|
+
* @property {object} [options.certsAndProxyConfig.options] - TLS and proxy options
|
|
63
|
+
* @property {object} [options.certsAndProxyConfig.clientCertificates] - Client certificate configuration
|
|
64
|
+
* @property {object} [options.certsAndProxyConfig.collectionLevelProxy] - Collection-level proxy settings
|
|
65
|
+
* @property {object} [options.certsAndProxyConfig.systemProxyConfig] - System proxy configuration
|
|
66
|
+
* @property {string} [options.requestUrl] - The URL of the current request (used for cookie access)
|
|
67
|
+
* @property {function} [options.onConsoleLog] - Console callback `(type, args) => void` to route warnings to the UI
|
|
29
68
|
*/
|
|
30
|
-
constructor(
|
|
69
|
+
constructor({
|
|
70
|
+
runtime,
|
|
71
|
+
envVariables,
|
|
72
|
+
runtimeVariables,
|
|
73
|
+
processEnvVars,
|
|
74
|
+
collectionPath,
|
|
75
|
+
historyLogger,
|
|
76
|
+
setVisualizations,
|
|
77
|
+
secretVariables,
|
|
78
|
+
collectionVariables,
|
|
79
|
+
folderVariables,
|
|
80
|
+
requestVariables,
|
|
81
|
+
globalEnvironmentVariables,
|
|
82
|
+
oauth2CredentialVariables,
|
|
83
|
+
iterationDetails,
|
|
84
|
+
collectionName,
|
|
85
|
+
promptVariables,
|
|
86
|
+
certsAndProxyConfig,
|
|
87
|
+
requestUrl,
|
|
88
|
+
onConsoleLog
|
|
89
|
+
}) {
|
|
31
90
|
this.envVariables = envVariables || {};
|
|
32
91
|
this.runtimeVariables = runtimeVariables || {};
|
|
33
92
|
this.promptVariables = promptVariables || {};
|
|
@@ -41,58 +100,18 @@ class Bru {
|
|
|
41
100
|
this.collectionPath = collectionPath;
|
|
42
101
|
this.historyLogger = historyLogger;
|
|
43
102
|
this.setVisualizations = setVisualizations;
|
|
103
|
+
this.onConsoleLog = onConsoleLog || null;
|
|
44
104
|
this.collectionName = collectionName;
|
|
45
105
|
// Use createSendRequest with config if provided, otherwise use default sendRequest
|
|
46
106
|
this.sendRequest = certsAndProxyConfig ? createSendRequest(certsAndProxyConfig) : sendRequest;
|
|
47
107
|
this.runtime = runtime;
|
|
48
|
-
this.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return cookieJar.getCookie(interpolatedUrl, cookieName, callback);
|
|
56
|
-
},
|
|
57
|
-
|
|
58
|
-
getCookies: (url, callback) => {
|
|
59
|
-
const interpolatedUrl = this.interpolate(url);
|
|
60
|
-
return cookieJar.getCookies(interpolatedUrl, callback);
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
setCookie: (url, nameOrCookieObj, valueOrCallback, maybeCallback) => {
|
|
64
|
-
const interpolatedUrl = this.interpolate(url);
|
|
65
|
-
return cookieJar.setCookie(interpolatedUrl, nameOrCookieObj, valueOrCallback, maybeCallback);
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
setCookies: (url, cookiesArray, callback) => {
|
|
69
|
-
const interpolatedUrl = this.interpolate(url);
|
|
70
|
-
return cookieJar.setCookies(interpolatedUrl, cookiesArray, callback);
|
|
71
|
-
},
|
|
72
|
-
|
|
73
|
-
// Clear entire cookie jar
|
|
74
|
-
clear: (callback) => {
|
|
75
|
-
return cookieJar.clear(callback);
|
|
76
|
-
},
|
|
77
|
-
|
|
78
|
-
// Delete cookies for a specific URL/domain
|
|
79
|
-
deleteCookies: (url, callback) => {
|
|
80
|
-
const interpolatedUrl = this.interpolate(url);
|
|
81
|
-
return cookieJar.deleteCookies(interpolatedUrl, callback);
|
|
82
|
-
},
|
|
83
|
-
|
|
84
|
-
deleteCookie: (url, cookieName, callback) => {
|
|
85
|
-
const interpolatedUrl = this.interpolate(url);
|
|
86
|
-
return cookieJar.deleteCookie(interpolatedUrl, cookieName, callback);
|
|
87
|
-
},
|
|
88
|
-
|
|
89
|
-
hasCookie: (url, cookieName, callback) => {
|
|
90
|
-
const interpolatedUrl = this.interpolate(url);
|
|
91
|
-
return cookieJar.hasCookie(interpolatedUrl, cookieName, callback);
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
};
|
|
108
|
+
this.requestUrl = requestUrl;
|
|
109
|
+
this.cookies = new CookieList({
|
|
110
|
+
getUrl: () => this.interpolate(this.requestUrl),
|
|
111
|
+
interpolate: (str) => this.interpolate(str),
|
|
112
|
+
createCookieJar,
|
|
113
|
+
getCookiesForUrl
|
|
114
|
+
});
|
|
96
115
|
// Holds variables that are marked as persistent by scripts
|
|
97
116
|
this.persistentEnvVariables = {};
|
|
98
117
|
// Holds credential IDs to be reset after script execution
|
|
@@ -414,9 +433,41 @@ class Bru {
|
|
|
414
433
|
return this.secretVariables?.[`$secrets.${key}`];
|
|
415
434
|
}
|
|
416
435
|
|
|
436
|
+
/**
|
|
437
|
+
* Render a visualization in the response pane.
|
|
438
|
+
*
|
|
439
|
+
* @param {'table' | 'html'} type - The visualization type.
|
|
440
|
+
* @param {Object} data - Shape depends on `type`:
|
|
441
|
+
*
|
|
442
|
+
* **When `type` is `'table'`:**
|
|
443
|
+
* @param {string} data.provider - `'ag-grid'` or `'react-table'`.
|
|
444
|
+
* @param {Object} data.props - Props forwarded to the grid component.
|
|
445
|
+
* @param {Array} data.props.columnDefinitions - (ag-grid) Column definitions.
|
|
446
|
+
* @param {Array} data.props.rowData - (ag-grid) Row data.
|
|
447
|
+
*
|
|
448
|
+
* **When `type` is `'html'`** (raw mode):
|
|
449
|
+
* @param {string} data.content - Pre-rendered HTML string.
|
|
450
|
+
*
|
|
451
|
+
* **When `type` is `'html'`** (Handlebars template mode):
|
|
452
|
+
* @param {string} data.template - Handlebars template string (required).
|
|
453
|
+
* @param {Object} [data.data={}] - Context object passed to the compiled template.
|
|
454
|
+
* @param {Object} [data.options] - Handlebars compile options.
|
|
455
|
+
* @param {boolean} [data.options.noEscape] - Disable HTML escaping.
|
|
456
|
+
* @param {boolean} [data.options.strict] - Throw on missing variables.
|
|
457
|
+
* @param {boolean} [data.options.assumeObjects] - Skip null checks on nested paths.
|
|
458
|
+
* @param {boolean} [data.options.dangerouslyAllowAllOptions] - Bypass the safe-options
|
|
459
|
+
* allowlist (forwards all remaining options directly to `Handlebars.compile`).
|
|
460
|
+
*
|
|
461
|
+
* @throws {Error} If `type` is falsy.
|
|
462
|
+
* @throws {Error} If `type` is `'html'` and neither `data.content` nor `data.template` is provided.
|
|
463
|
+
* @throws {Error} If template exceeds `MAX_TEMPLATE_LENGTH`.
|
|
464
|
+
*/
|
|
417
465
|
visualize(type, data) {
|
|
418
|
-
if (type
|
|
419
|
-
|
|
466
|
+
if (!type) {
|
|
467
|
+
throw new Error('visualization type is required');
|
|
468
|
+
}
|
|
469
|
+
if (type === 'table') {
|
|
470
|
+
if (data?.provider === 'ag-grid') {
|
|
420
471
|
if (!data?.props?.columnDefinitions) {
|
|
421
472
|
throw new Error(`columns definitions are required`);
|
|
422
473
|
}
|
|
@@ -424,17 +475,63 @@ class Bru {
|
|
|
424
475
|
throw new Error(`row data is required`);
|
|
425
476
|
}
|
|
426
477
|
this.setVisualizations({ uid: uuid(), type, data });
|
|
427
|
-
} else if (data?.provider
|
|
478
|
+
} else if (data?.provider === 'react-table') {
|
|
428
479
|
this.setVisualizations({ uid: uuid(), type, data });
|
|
429
480
|
}
|
|
430
|
-
} else if (type
|
|
431
|
-
if (
|
|
432
|
-
|
|
481
|
+
} else if (type === 'html') {
|
|
482
|
+
if (typeof data?.template === 'string') {
|
|
483
|
+
// Handlebars template mode (translated from pm.visualizer.set)
|
|
484
|
+
if (data.template.length > MAX_TEMPLATE_LENGTH) {
|
|
485
|
+
throw new Error(`template exceeds maximum length of ${MAX_TEMPLATE_LENGTH} characters`);
|
|
486
|
+
}
|
|
487
|
+
// Isolated instance so globally-registered helpers can't be exploited (SSTI prevention)
|
|
488
|
+
const hbs = Handlebars.create();
|
|
489
|
+
// Allowlist safe compile options to prevent re-enabling prototype traversal (CVE-2019-19919)
|
|
490
|
+
let compileOptions;
|
|
491
|
+
if (data.options?.dangerouslyAllowAllOptions) {
|
|
492
|
+
const { dangerouslyAllowAllOptions, ...rest } = data.options;
|
|
493
|
+
compileOptions = rest;
|
|
494
|
+
} else {
|
|
495
|
+
compileOptions = {};
|
|
496
|
+
if (data.options) {
|
|
497
|
+
const blocked = [];
|
|
498
|
+
for (const key of Object.keys(data.options)) {
|
|
499
|
+
if (SAFE_HBS_OPTIONS.has(key)) {
|
|
500
|
+
compileOptions[key] = data.options[key];
|
|
501
|
+
} else {
|
|
502
|
+
blocked.push(key);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
if (blocked.length > 0) {
|
|
506
|
+
const msg = `bru.visualize: the following compile options were blocked and ignored: ${blocked.map((k) => `"${k}"`).join(', ')}. `
|
|
507
|
+
+ 'Use { dangerouslyAllowAllOptions: true } in options to bypass the allowlist.';
|
|
508
|
+
if (this.onConsoleLog) {
|
|
509
|
+
this.onConsoleLog('warn', [msg]);
|
|
510
|
+
} else {
|
|
511
|
+
console.warn(msg);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
const compiled = hbs.compile(data.template, compileOptions);
|
|
517
|
+
const renderedHtml = compiled(data.data || {});
|
|
518
|
+
this.setVisualizations({
|
|
519
|
+
uid: uuid(), type,
|
|
520
|
+
data: { content: renderedHtml, rawData: data.data || {} }
|
|
521
|
+
});
|
|
522
|
+
} else if (data?.content) {
|
|
523
|
+
// Existing raw HTML mode
|
|
524
|
+
this.setVisualizations({ uid: uuid(), type, data });
|
|
525
|
+
} else {
|
|
526
|
+
throw new Error('html content or template is required');
|
|
433
527
|
}
|
|
434
|
-
this.setVisualizations({ uid: uuid(), type, data });
|
|
435
528
|
}
|
|
436
529
|
}
|
|
437
530
|
|
|
531
|
+
clearVisualizations() {
|
|
532
|
+
this.setVisualizations({ type: VISUALIZATION_CLEAR });
|
|
533
|
+
}
|
|
534
|
+
|
|
438
535
|
sleep(ms) {
|
|
439
536
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
440
537
|
}
|
|
@@ -488,3 +585,4 @@ class IterationDataManager {
|
|
|
488
585
|
}
|
|
489
586
|
|
|
490
587
|
module.exports = Bru;
|
|
588
|
+
module.exports.VISUALIZATION_CLEAR = VISUALIZATION_CLEAR;
|
package/src/bruno-request.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
const HeaderList = require('./header-list');
|
|
2
|
+
|
|
1
3
|
class BrunoRequest {
|
|
2
4
|
/**
|
|
3
5
|
* The following properties are available as shorthand:
|
|
4
6
|
* - req.url
|
|
5
7
|
* - req.method
|
|
6
|
-
* - req.headers
|
|
8
|
+
* - req.headers (raw headers object)
|
|
9
|
+
* - req.headerList (PropertyList API for headers)
|
|
7
10
|
* - req.timeout
|
|
8
11
|
* - req.body
|
|
9
12
|
*
|
|
@@ -22,6 +25,7 @@ class BrunoRequest {
|
|
|
22
25
|
this.name = req.name;
|
|
23
26
|
this.pathParams = req.pathParams;
|
|
24
27
|
this.tags = req.tags || [];
|
|
28
|
+
this.headerList = new HeaderList(this.req);
|
|
25
29
|
/**
|
|
26
30
|
* We automatically parse the JSON body if the content type is JSON
|
|
27
31
|
* This is to make it easier for the user to access the body directly
|
|
@@ -96,17 +100,24 @@ class BrunoRequest {
|
|
|
96
100
|
}
|
|
97
101
|
|
|
98
102
|
getAuthMode() {
|
|
103
|
+
const headers = this.req.headers;
|
|
99
104
|
if (this.req?.oauth2) {
|
|
100
105
|
return 'oauth2';
|
|
101
|
-
} else if (this.
|
|
106
|
+
} else if (this.req?.oauth1config) {
|
|
107
|
+
return 'oauth1';
|
|
108
|
+
} else if (headers?.['Authorization']?.startsWith('Bearer')) {
|
|
102
109
|
return 'bearer';
|
|
103
|
-
} else if (
|
|
110
|
+
} else if (headers?.['Authorization']?.startsWith('Basic') || this.req?.auth?.username) {
|
|
104
111
|
return 'basic';
|
|
112
|
+
} else if (this.req?.apiKeyAuthValueForQueryParams) {
|
|
113
|
+
return 'apikey';
|
|
114
|
+
} else if (this.req?.apiKeyHeaderName && this.headers?.[this.req.apiKeyHeaderName] !== undefined) {
|
|
115
|
+
return 'apikey';
|
|
105
116
|
} else if (this.req?.awsv4) {
|
|
106
117
|
return 'awsv4';
|
|
107
118
|
} else if (this.req?.digestConfig) {
|
|
108
119
|
return 'digest';
|
|
109
|
-
} else if (
|
|
120
|
+
} else if (headers?.['X-WSSE'] || this.req?.auth?.username) {
|
|
110
121
|
return 'wsse';
|
|
111
122
|
} else {
|
|
112
123
|
return 'none';
|
|
@@ -123,7 +134,6 @@ class BrunoRequest {
|
|
|
123
134
|
}
|
|
124
135
|
|
|
125
136
|
setHeaders(headers) {
|
|
126
|
-
this.headers = headers;
|
|
127
137
|
this.req.headers = headers;
|
|
128
138
|
}
|
|
129
139
|
|
|
@@ -136,12 +146,10 @@ class BrunoRequest {
|
|
|
136
146
|
}
|
|
137
147
|
|
|
138
148
|
setHeader(name, value) {
|
|
139
|
-
this.headers[name] = value;
|
|
140
149
|
this.req.headers[name] = value;
|
|
141
150
|
}
|
|
142
151
|
|
|
143
152
|
deleteHeader(name) {
|
|
144
|
-
delete this.headers[name];
|
|
145
153
|
delete this.req.headers[name];
|
|
146
154
|
|
|
147
155
|
/**
|
package/src/bruno-response.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const { get } = require('@usebruno/query');
|
|
2
2
|
const _ = require('lodash');
|
|
3
|
+
const HeaderList = require('./header-list');
|
|
3
4
|
|
|
4
5
|
class BrunoResponse {
|
|
5
6
|
constructor(res) {
|
|
@@ -11,6 +12,9 @@ class BrunoResponse {
|
|
|
11
12
|
this.responseTime = res ? res.responseTime : null;
|
|
12
13
|
this.url = res?.request ? res.request.protocol + '//' + res.request.host + res.request.path : null;
|
|
13
14
|
|
|
15
|
+
// HeaderList in static read-only mode — write methods throw
|
|
16
|
+
this.headerList = new HeaderList(res, { writable: false });
|
|
17
|
+
|
|
14
18
|
// Make the instance callable
|
|
15
19
|
const callable = (...args) => get(this.body, ...args);
|
|
16
20
|
Object.setPrototypeOf(callable, this.constructor.prototype);
|