postman-runtime 7.37.3 → 7.39.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/CHANGELOG.yaml +17 -0
- package/dist/index.js +1 -1
- package/lib/authorizer/digest.js +19 -0
- package/lib/authorizer/edgegrid.js +34 -6
- package/lib/authorizer/ntlm.js +19 -8
- package/lib/runner/create-item-context.js +2 -2
- package/lib/runner/extensions/http-request.command.js +11 -3
- package/lib/runner/extensions/request.command.js +1 -81
- package/lib/runner/replay-controller.js +3 -0
- package/lib/runner/request-helpers-presend.js +6 -2
- package/lib/runner/util.js +84 -0
- package/package.json +3 -3
package/lib/authorizer/digest.js
CHANGED
|
@@ -226,6 +226,21 @@ function computeBodyHash (body, algorithm, digestEncoding, callback) {
|
|
|
226
226
|
return callback();
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
+
/**
|
|
230
|
+
* increase nonce count by 1
|
|
231
|
+
*
|
|
232
|
+
* @param {String} nonceCount - nonce count
|
|
233
|
+
*/
|
|
234
|
+
function increaseNonceCount (nonceCount) {
|
|
235
|
+
const nc = _.parseInt(nonceCount);
|
|
236
|
+
|
|
237
|
+
if (_.isNaN(nc)) {
|
|
238
|
+
return ONE;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return _.padStart((nc + 1).toString(), ONE.length, '0');
|
|
242
|
+
}
|
|
243
|
+
|
|
229
244
|
/**
|
|
230
245
|
* All the auth definition parameters excluding username and password should be stored and resued.
|
|
231
246
|
*
|
|
@@ -298,6 +313,7 @@ module.exports = {
|
|
|
298
313
|
}
|
|
299
314
|
|
|
300
315
|
var code,
|
|
316
|
+
nonceCount,
|
|
301
317
|
realm,
|
|
302
318
|
nonce,
|
|
303
319
|
qop,
|
|
@@ -306,6 +322,7 @@ module.exports = {
|
|
|
306
322
|
authParams = {};
|
|
307
323
|
|
|
308
324
|
code = response.code;
|
|
325
|
+
nonceCount = auth.get('nonceCount');
|
|
309
326
|
authHeader = _getDigestAuthHeader(response.headers);
|
|
310
327
|
|
|
311
328
|
// If code is forbidden or unauthorized, and an auth header exists,
|
|
@@ -337,6 +354,8 @@ module.exports = {
|
|
|
337
354
|
return done(null, false);
|
|
338
355
|
}
|
|
339
356
|
|
|
357
|
+
auth.set('nonceCount', increaseNonceCount(nonceCount));
|
|
358
|
+
|
|
340
359
|
done(null, true);
|
|
341
360
|
},
|
|
342
361
|
|
|
@@ -88,15 +88,37 @@ var _ = require('lodash'),
|
|
|
88
88
|
return encrypt.digest('base64');
|
|
89
89
|
},
|
|
90
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Trim the body if it exceeds the max body limit.
|
|
93
|
+
*
|
|
94
|
+
* @param {String|Buffer} body Request body
|
|
95
|
+
* @param {Number} size Maximum body size to hash
|
|
96
|
+
*/
|
|
97
|
+
limitRequestBody = function (body, size) {
|
|
98
|
+
if (!body || size <= 0) { return EMPTY; }
|
|
99
|
+
|
|
100
|
+
if (!Buffer.isBuffer(body)) {
|
|
101
|
+
// We are converting the body to a buffer to obtain the exact byte length and to precisely trim the body.
|
|
102
|
+
body = Buffer.from(body);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (body.byteLength > size) {
|
|
106
|
+
body = body.subarray(0, size);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return body;
|
|
110
|
+
},
|
|
111
|
+
|
|
91
112
|
/**
|
|
92
113
|
* Calculates body hash with given algorithm and digestEncoding.
|
|
93
114
|
*
|
|
94
115
|
* @param {RequestBody} body Request body
|
|
95
116
|
* @param {String} algorithm Hash algorithm to use
|
|
96
117
|
* @param {String} digestEncoding Encoding of the hash
|
|
118
|
+
* @param {Number} maxBodySize Maximum body size to hash
|
|
97
119
|
* @param {Function} callback Callback function that will be called with body hash
|
|
98
120
|
*/
|
|
99
|
-
computeBodyHash = function (body, algorithm, digestEncoding, callback) {
|
|
121
|
+
computeBodyHash = function (body, algorithm, digestEncoding, maxBodySize, callback) {
|
|
100
122
|
if (!(body && algorithm && digestEncoding) || body.isEmpty()) { return callback(); }
|
|
101
123
|
|
|
102
124
|
var hash = crypto.createHash(algorithm),
|
|
@@ -107,7 +129,7 @@ var _ = require('lodash'),
|
|
|
107
129
|
|
|
108
130
|
if (body.mode === RequestBody.MODES.raw) {
|
|
109
131
|
rawBody = bodyBuilder.raw(body.raw).body;
|
|
110
|
-
hash.update(rawBody);
|
|
132
|
+
hash.update(limitRequestBody(rawBody, maxBodySize));
|
|
111
133
|
|
|
112
134
|
return callback(hash.digest(digestEncoding));
|
|
113
135
|
}
|
|
@@ -115,7 +137,7 @@ var _ = require('lodash'),
|
|
|
115
137
|
if (body.mode === RequestBody.MODES.urlencoded) {
|
|
116
138
|
urlencodedBody = bodyBuilder.urlencoded(body.urlencoded).form;
|
|
117
139
|
urlencodedBody = urlEncoder.encodeQueryString(urlencodedBody);
|
|
118
|
-
hash.update(urlencodedBody);
|
|
140
|
+
hash.update(limitRequestBody(urlencodedBody, maxBodySize));
|
|
119
141
|
|
|
120
142
|
return callback(hash.digest(digestEncoding));
|
|
121
143
|
}
|
|
@@ -129,9 +151,13 @@ var _ = require('lodash'),
|
|
|
129
151
|
|
|
130
152
|
return originalReadStream.cloneReadStream(function (err, clonedStream) {
|
|
131
153
|
if (err) { return callback(); }
|
|
154
|
+
let readBytes = 0;
|
|
132
155
|
|
|
133
156
|
clonedStream.on('data', function (chunk) {
|
|
134
|
-
|
|
157
|
+
if (readBytes <= maxBodySize) {
|
|
158
|
+
hash.update(limitRequestBody(chunk, maxBodySize - readBytes));
|
|
159
|
+
readBytes += chunk.byteLength;
|
|
160
|
+
}
|
|
135
161
|
});
|
|
136
162
|
|
|
137
163
|
clonedStream.on('end', function () {
|
|
@@ -142,7 +168,7 @@ var _ = require('lodash'),
|
|
|
142
168
|
|
|
143
169
|
if (body.mode === RequestBody.MODES.graphql) {
|
|
144
170
|
graphqlBody = bodyBuilder.graphql(body.graphql).body;
|
|
145
|
-
hash.update(graphqlBody);
|
|
171
|
+
hash.update(limitRequestBody(graphqlBody, maxBodySize));
|
|
146
172
|
|
|
147
173
|
return callback(hash.digest(digestEncoding));
|
|
148
174
|
}
|
|
@@ -257,6 +283,7 @@ module.exports = {
|
|
|
257
283
|
sign: function (auth, request, done) {
|
|
258
284
|
var params = auth.get([
|
|
259
285
|
'accessToken',
|
|
286
|
+
'maxBodySize',
|
|
260
287
|
'clientToken',
|
|
261
288
|
'clientSecret',
|
|
262
289
|
'baseURL',
|
|
@@ -279,6 +306,7 @@ module.exports = {
|
|
|
279
306
|
params.timestamp = params.timestamp || getTimestamp();
|
|
280
307
|
params.url = url;
|
|
281
308
|
params.method = request.method;
|
|
309
|
+
params.maxBodySize = params.maxBodySize || 131072; // 128 KB
|
|
282
310
|
|
|
283
311
|
// ensure that headers are case-insensitive as specified in the documentation
|
|
284
312
|
params.headers = request.getHeaders({ enabled: true, ignoreCase: true });
|
|
@@ -292,7 +320,7 @@ module.exports = {
|
|
|
292
320
|
|
|
293
321
|
// only calculate body hash for POST requests according to specification
|
|
294
322
|
if (request.method === 'POST') {
|
|
295
|
-
return computeBodyHash(request.body, 'sha256', 'base64', function (bodyHash) {
|
|
323
|
+
return computeBodyHash(request.body, 'sha256', 'base64', params.maxBodySize, function (bodyHash) {
|
|
296
324
|
params.bodyHash = bodyHash;
|
|
297
325
|
|
|
298
326
|
request.addHeader({
|
package/lib/authorizer/ntlm.js
CHANGED
|
@@ -150,7 +150,10 @@ module.exports = {
|
|
|
150
150
|
* @param {AuthHandlerInterface~authPreHookCallback} done -
|
|
151
151
|
*/
|
|
152
152
|
pre: function (auth, done) {
|
|
153
|
-
!auth.get(STATE)
|
|
153
|
+
if (!auth.get(STATE)) {
|
|
154
|
+
auth.set(STATE, STATES.INITIALIZED);
|
|
155
|
+
auth.set(NTLM_HEADER, undefined);
|
|
156
|
+
}
|
|
154
157
|
|
|
155
158
|
done(null, true);
|
|
156
159
|
},
|
|
@@ -176,10 +179,18 @@ module.exports = {
|
|
|
176
179
|
challengeMessage, // type 2
|
|
177
180
|
authenticateMessage, // type 3
|
|
178
181
|
ntlmType2Header,
|
|
179
|
-
parsedParameters
|
|
182
|
+
parsedParameters,
|
|
183
|
+
|
|
184
|
+
// resets the state and NTLM header and exits replay loop
|
|
185
|
+
resetStateAndStop = function (err) {
|
|
186
|
+
auth.set(STATE, STATES.INITIALIZED);
|
|
187
|
+
auth.set(NTLM_HEADER, undefined);
|
|
188
|
+
|
|
189
|
+
return done(err || null, true);
|
|
190
|
+
};
|
|
180
191
|
|
|
181
192
|
if (response.code !== 401 && response.code !== 403) {
|
|
182
|
-
return
|
|
193
|
+
return resetStateAndStop();
|
|
183
194
|
}
|
|
184
195
|
|
|
185
196
|
// we try to extract domain from username if not specified.
|
|
@@ -193,7 +204,7 @@ module.exports = {
|
|
|
193
204
|
if (state === STATES.INITIALIZED) {
|
|
194
205
|
// Nothing to do if the server does not ask us for auth in the first place.
|
|
195
206
|
if (!hasNTLMChallenge(response.headers)) {
|
|
196
|
-
return
|
|
207
|
+
return resetStateAndStop();
|
|
197
208
|
}
|
|
198
209
|
|
|
199
210
|
// Create a type 1 message to send to the server
|
|
@@ -223,13 +234,13 @@ module.exports = {
|
|
|
223
234
|
});
|
|
224
235
|
|
|
225
236
|
if (!ntlmType2Header) {
|
|
226
|
-
return
|
|
237
|
+
return resetStateAndStop(new Error('ntlm: server did not send NTLM type 2 message'));
|
|
227
238
|
}
|
|
228
239
|
|
|
229
240
|
challengeMessage = ntlmUtil.parseType2Message(ntlmType2Header.valueOf(), _.noop);
|
|
230
241
|
|
|
231
242
|
if (!challengeMessage) {
|
|
232
|
-
return
|
|
243
|
+
return resetStateAndStop(new Error('ntlm: server did not correctly process authentication request'));
|
|
233
244
|
}
|
|
234
245
|
|
|
235
246
|
authenticateMessage = ntlmUtil.createType3Message(challengeMessage, {
|
|
@@ -248,11 +259,11 @@ module.exports = {
|
|
|
248
259
|
}
|
|
249
260
|
else if (state === STATES.T3_MSG_CREATED) {
|
|
250
261
|
// Means we have tried to authenticate, so we should stop here without worrying about anything
|
|
251
|
-
return
|
|
262
|
+
return resetStateAndStop();
|
|
252
263
|
}
|
|
253
264
|
|
|
254
265
|
// We are in an undefined state
|
|
255
|
-
return
|
|
266
|
+
return resetStateAndStop();
|
|
256
267
|
},
|
|
257
268
|
|
|
258
269
|
/**
|
|
@@ -7,7 +7,7 @@ var _ = require('lodash'),
|
|
|
7
7
|
*/
|
|
8
8
|
FUNCTION = 'function',
|
|
9
9
|
|
|
10
|
-
SAFE_CONTEXT_PROPERTIES = ['replayState', 'coords'];
|
|
10
|
+
SAFE_CONTEXT_PROPERTIES = ['replayState', 'coords', 'originalItem'];
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Creates a context object to be used with `http-request.command` extension.
|
|
@@ -31,7 +31,7 @@ module.exports = function (payload, defaults) {
|
|
|
31
31
|
!context.coords && (context.coords = payload.coords);
|
|
32
32
|
|
|
33
33
|
// save original item for reference
|
|
34
|
-
context.originalItem = payload.item;
|
|
34
|
+
context.originalItem = context.originalItem || payload.item;
|
|
35
35
|
|
|
36
36
|
// we clone item from the payload, so that we can make any changes we need there, without mutating the
|
|
37
37
|
// collection
|
|
@@ -83,7 +83,7 @@ module.exports = {
|
|
|
83
83
|
|
|
84
84
|
// Helper function to call the afterRequest trigger.
|
|
85
85
|
afterRequest = function (err, response, request, cookies, history) {
|
|
86
|
-
self.triggers.request(err, context.coords, response, request,
|
|
86
|
+
self.triggers.request(err, context.coords, response, request, context.item, cookies, history);
|
|
87
87
|
};
|
|
88
88
|
|
|
89
89
|
// Ensure that this is called.
|
|
@@ -159,7 +159,7 @@ module.exports = {
|
|
|
159
159
|
var nextPayload = {
|
|
160
160
|
response: res,
|
|
161
161
|
request: req,
|
|
162
|
-
item: context.
|
|
162
|
+
item: context.item,
|
|
163
163
|
cookies: cookies,
|
|
164
164
|
coords: context.coords,
|
|
165
165
|
history: history
|
|
@@ -188,9 +188,17 @@ module.exports = {
|
|
|
188
188
|
// replay controller invokes callback no. 1 when replaying the request
|
|
189
189
|
// invokes callback no. 2 when replay count has exceeded maximum limit
|
|
190
190
|
// @note: errors in replayed requests are passed to callback no. 1
|
|
191
|
+
// @note: we are adding variables list to resolve variables after new context is created
|
|
191
192
|
return replayController.requestReplay(context,
|
|
192
193
|
context.item,
|
|
193
|
-
{ source: replayOptions.helper
|
|
194
|
+
{ source: replayOptions.helper, ..._.pick(payload, [
|
|
195
|
+
'_variables',
|
|
196
|
+
'data',
|
|
197
|
+
'environment',
|
|
198
|
+
'collectionVariables',
|
|
199
|
+
'globals',
|
|
200
|
+
'vaultSecrets'
|
|
201
|
+
]) },
|
|
194
202
|
// new payload with response from replay is sent to `next`
|
|
195
203
|
function (err, payloadFromReplay) { safeNext(err, payloadFromReplay); },
|
|
196
204
|
// replay was stopped, move on with older payload
|
|
@@ -1,87 +1,7 @@
|
|
|
1
1
|
var _ = require('lodash'),
|
|
2
|
-
sdk = require('postman-collection'),
|
|
3
2
|
createItemContext = require('../create-item-context'),
|
|
3
|
+
{ resolveVariables } = require('../util');
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* Resolve variables in item and auth in context.
|
|
7
|
-
*
|
|
8
|
-
* @param {ItemContext} context -
|
|
9
|
-
* @param {Item} [context.item] -
|
|
10
|
-
* @param {RequestAuth} [context.auth] -
|
|
11
|
-
* @param {Object} payload -
|
|
12
|
-
* @param {VariableScope} payload._variables -
|
|
13
|
-
* @param {Object} payload.data -
|
|
14
|
-
* @param {VariableScope} payload.environment -
|
|
15
|
-
* @param {VariableScope} payload.collectionVariables -
|
|
16
|
-
* @param {VariableScope} payload.globals -
|
|
17
|
-
* @param {VariableScope} payload.vaultSecrets -
|
|
18
|
-
*/
|
|
19
|
-
resolveVariables = function (context, payload) {
|
|
20
|
-
if (!(context.item && context.item.request)) { return; }
|
|
21
|
-
|
|
22
|
-
// @todo - resolve variables in a more graceful way
|
|
23
|
-
var variableDefinitions = [
|
|
24
|
-
// extract the variable list from variable scopes
|
|
25
|
-
// @note: this is the order of precedence for variable resolution - don't change it
|
|
26
|
-
payload._variables.values,
|
|
27
|
-
payload.data,
|
|
28
|
-
payload.environment.values,
|
|
29
|
-
payload.collectionVariables.values,
|
|
30
|
-
payload.globals.values
|
|
31
|
-
// @note vault variables are added later
|
|
32
|
-
],
|
|
33
|
-
|
|
34
|
-
hasVaultSecrets = payload.vaultSecrets.values.count() > 0,
|
|
35
|
-
|
|
36
|
-
urlObj = context.item.request.url,
|
|
37
|
-
// @note URL string is used to resolve nested variables as URL parser doesn't support them well.
|
|
38
|
-
urlString = urlObj.toString(),
|
|
39
|
-
unresolvedUrlString = urlString,
|
|
40
|
-
|
|
41
|
-
vaultVariables,
|
|
42
|
-
vaultUrl,
|
|
43
|
-
item,
|
|
44
|
-
auth;
|
|
45
|
-
|
|
46
|
-
if (hasVaultSecrets) {
|
|
47
|
-
// get the vault variables that match the unresolved URL string
|
|
48
|
-
vaultUrl = urlObj.protocol ? urlString : `http://${urlString}`; // force protocol
|
|
49
|
-
vaultVariables = payload.vaultSecrets.__getMatchingVariables(vaultUrl);
|
|
50
|
-
|
|
51
|
-
// resolve variables in URL string with initial vault variables
|
|
52
|
-
urlString = sdk.Property.replaceSubstitutions(urlString, [...variableDefinitions, vaultVariables]);
|
|
53
|
-
|
|
54
|
-
if (urlString !== unresolvedUrlString) {
|
|
55
|
-
// get the final list of vault variables that match the resolved URL string
|
|
56
|
-
vaultUrl = new sdk.Url(urlString).toString(true);
|
|
57
|
-
vaultVariables = payload.vaultSecrets.__getMatchingVariables(vaultUrl);
|
|
58
|
-
|
|
59
|
-
// resolve vault variables in URL string
|
|
60
|
-
// @note other variable scopes are skipped as they are already resolved
|
|
61
|
-
urlString = sdk.Property.replaceSubstitutions(urlString, [vaultVariables]);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// add vault variables to the list of variable definitions
|
|
65
|
-
variableDefinitions.push(vaultVariables);
|
|
66
|
-
}
|
|
67
|
-
else if (urlString) {
|
|
68
|
-
urlString = sdk.Property.replaceSubstitutions(urlString, variableDefinitions);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// @todo - no need to sync variables when SDK starts supporting resolution from scope directly
|
|
72
|
-
// @todo - avoid resolving the entire item as this unnecessarily resolves URL
|
|
73
|
-
item = context.item = new sdk.Item(context.item.toObjectResolved(null,
|
|
74
|
-
variableDefinitions, { ignoreOwnVariables: true }));
|
|
75
|
-
|
|
76
|
-
// re-parse and update the URL from the resolved string
|
|
77
|
-
urlString && (item.request.url = new sdk.Url(urlString));
|
|
78
|
-
|
|
79
|
-
auth = context.auth;
|
|
80
|
-
|
|
81
|
-
// resolve variables in auth
|
|
82
|
-
auth && (context.auth = new sdk.RequestAuth(auth.toObjectResolved(null,
|
|
83
|
-
variableDefinitions, { ignoreOwnVariables: true })));
|
|
84
|
-
};
|
|
85
5
|
|
|
86
6
|
module.exports = {
|
|
87
7
|
init: function (done) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
var _ = require('lodash'),
|
|
2
2
|
createItemContext = require('./create-item-context'),
|
|
3
|
+
{ resolveVariables } = require('./util'),
|
|
3
4
|
|
|
4
5
|
// total number of replays allowed
|
|
5
6
|
MAX_REPLAY_COUNT = 3,
|
|
@@ -54,6 +55,8 @@ _.assign(ReplayController.prototype, /** @lends ReplayController.prototype */{
|
|
|
54
55
|
// create item context from the new item
|
|
55
56
|
payload.context = createItemContext(payload, context);
|
|
56
57
|
|
|
58
|
+
resolveVariables(payload.context, payload);
|
|
59
|
+
|
|
57
60
|
this.run.immediate('httprequest', payload)
|
|
58
61
|
.done(function (response) {
|
|
59
62
|
success(null, response);
|
|
@@ -314,15 +314,18 @@ module.exports = [
|
|
|
314
314
|
|
|
315
315
|
// prepare for sending intermediate request
|
|
316
316
|
var replayController = new ReplayController(context.replayState, run),
|
|
317
|
-
item = new sdk.Item({ request })
|
|
317
|
+
item = new sdk.Item({ request }),
|
|
318
|
+
originalItem = context.originalItem;
|
|
318
319
|
|
|
319
320
|
// auth handler gave a no go, and an intermediate request.
|
|
320
321
|
// make the intermediate request the response is passed to `init` hook
|
|
321
|
-
|
|
322
|
+
// we are overriding the originalItem because in pre we have a entire new request
|
|
323
|
+
replayController.requestReplay(_.assign(context, { originalItem: item }),
|
|
322
324
|
item,
|
|
323
325
|
// marks the auth as source for intermediate request
|
|
324
326
|
{ source: auth.type + DOT_AUTH },
|
|
325
327
|
function (err, response) {
|
|
328
|
+
context.originalItem = originalItem; // reset the original item
|
|
326
329
|
// errors for intermediate requests are passed to request callback
|
|
327
330
|
// passing it here will add it to original request as well, so don't do it
|
|
328
331
|
if (err) { return done(); }
|
|
@@ -343,6 +346,7 @@ module.exports = [
|
|
|
343
346
|
});
|
|
344
347
|
},
|
|
345
348
|
function (err) {
|
|
349
|
+
context.originalItem = originalItem; // reset the original item
|
|
346
350
|
// warn users that maximum retries have exceeded
|
|
347
351
|
if (err) {
|
|
348
352
|
run.triggers.console(context.coords,
|
package/lib/runner/util.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
var { Url, UrlMatchPatternList, VariableList } = require('postman-collection'),
|
|
2
|
+
sdk = require('postman-collection'),
|
|
3
|
+
_ = require('lodash'),
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* @const
|
|
@@ -234,5 +236,87 @@ module.exports = {
|
|
|
234
236
|
|
|
235
237
|
// mark the scope as a vault variable scope
|
|
236
238
|
scope.__vaultVariableScope = true;
|
|
239
|
+
},
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Resolve variables in item and auth in context.
|
|
243
|
+
*
|
|
244
|
+
* @param {ItemContext} context -
|
|
245
|
+
* @param {Item} [context.item] -
|
|
246
|
+
* @param {RequestAuth} [context.auth] -
|
|
247
|
+
* @param {Object} payload -
|
|
248
|
+
* @param {VariableScope} payload._variables -
|
|
249
|
+
* @param {Object} payload.data -
|
|
250
|
+
* @param {VariableScope} payload.environment -
|
|
251
|
+
* @param {VariableScope} payload.collectionVariables -
|
|
252
|
+
* @param {VariableScope} payload.globals -
|
|
253
|
+
* @param {VariableScope} payload.vaultSecrets -
|
|
254
|
+
*/
|
|
255
|
+
resolveVariables (context, payload) {
|
|
256
|
+
if (!(context.item && context.item.request)) { return; }
|
|
257
|
+
|
|
258
|
+
// @todo - resolve variables in a more graceful way
|
|
259
|
+
var variableDefinitions = [
|
|
260
|
+
// extract the variable list from variable scopes
|
|
261
|
+
// @note: this is the order of precedence for variable resolution - don't change it
|
|
262
|
+
_.get(payload, '_variables.values', []),
|
|
263
|
+
_.get(payload, 'data', []),
|
|
264
|
+
_.get(payload, 'environment.values', []),
|
|
265
|
+
_.get(payload, 'collectionVariables.values', []),
|
|
266
|
+
_.get(payload, 'globals.values', [])
|
|
267
|
+
// @note vault variables are added later
|
|
268
|
+
],
|
|
269
|
+
vaultValues = _.get(payload, 'vaultSecrets.values'),
|
|
270
|
+
|
|
271
|
+
hasVaultSecrets = vaultValues ? vaultValues.count() > 0 : false,
|
|
272
|
+
|
|
273
|
+
urlObj = context.item.request.url,
|
|
274
|
+
// @note URL string is used to resolve nested variables as URL parser doesn't support them well.
|
|
275
|
+
urlString = urlObj.toString(),
|
|
276
|
+
unresolvedUrlString = urlString,
|
|
277
|
+
|
|
278
|
+
vaultVariables,
|
|
279
|
+
vaultUrl,
|
|
280
|
+
item,
|
|
281
|
+
auth;
|
|
282
|
+
|
|
283
|
+
if (hasVaultSecrets) {
|
|
284
|
+
// get the vault variables that match the unresolved URL string
|
|
285
|
+
vaultUrl = urlObj.protocol ? urlString : `http://${urlString}`; // force protocol
|
|
286
|
+
vaultVariables = payload.vaultSecrets.__getMatchingVariables(vaultUrl);
|
|
287
|
+
|
|
288
|
+
// resolve variables in URL string with initial vault variables
|
|
289
|
+
urlString = sdk.Property.replaceSubstitutions(urlString, [...variableDefinitions, vaultVariables]);
|
|
290
|
+
|
|
291
|
+
if (urlString !== unresolvedUrlString) {
|
|
292
|
+
// get the final list of vault variables that match the resolved URL string
|
|
293
|
+
vaultUrl = new sdk.Url(urlString).toString(true);
|
|
294
|
+
vaultVariables = payload.vaultSecrets.__getMatchingVariables(vaultUrl);
|
|
295
|
+
|
|
296
|
+
// resolve vault variables in URL string
|
|
297
|
+
// @note other variable scopes are skipped as they are already resolved
|
|
298
|
+
urlString = sdk.Property.replaceSubstitutions(urlString, [vaultVariables]);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// add vault variables to the list of variable definitions
|
|
302
|
+
variableDefinitions.push(vaultVariables);
|
|
303
|
+
}
|
|
304
|
+
else if (urlString) {
|
|
305
|
+
urlString = sdk.Property.replaceSubstitutions(urlString, variableDefinitions);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// @todo - no need to sync variables when SDK starts supporting resolution from scope directly
|
|
309
|
+
// @todo - avoid resolving the entire item as this unnecessarily resolves URL
|
|
310
|
+
item = context.item = new sdk.Item(context.item.toObjectResolved(null,
|
|
311
|
+
variableDefinitions, { ignoreOwnVariables: true }));
|
|
312
|
+
|
|
313
|
+
// re-parse and update the URL from the resolved string
|
|
314
|
+
urlString && (item.request.url = new sdk.Url(urlString));
|
|
315
|
+
|
|
316
|
+
auth = context.auth;
|
|
317
|
+
|
|
318
|
+
// resolve variables in auth
|
|
319
|
+
auth && (context.auth = new sdk.RequestAuth(auth.toObjectResolved(null,
|
|
320
|
+
variableDefinitions, { ignoreOwnVariables: true })));
|
|
237
321
|
}
|
|
238
322
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "postman-runtime",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.39.0",
|
|
4
4
|
"description": "Underlying library of executing Postman Collections",
|
|
5
5
|
"author": "Postman Inc.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"performance-now": "2.1.0",
|
|
57
57
|
"postman-collection": "4.4.0",
|
|
58
58
|
"postman-request": "2.88.1-postman.33",
|
|
59
|
-
"postman-sandbox": "4.
|
|
59
|
+
"postman-sandbox": "4.7.1",
|
|
60
60
|
"postman-url-encoder": "3.0.5",
|
|
61
61
|
"serialised-error": "1.1.3",
|
|
62
62
|
"strip-json-comments": "3.1.1",
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
"shelljs": "^0.8.5",
|
|
94
94
|
"sinon": "^12.0.1",
|
|
95
95
|
"teleport-javascript": "^1.0.0",
|
|
96
|
-
"terser": "^5.30.
|
|
96
|
+
"terser": "^5.30.2",
|
|
97
97
|
"tmp": "^0.2.3",
|
|
98
98
|
"webpack": "^5.91.0",
|
|
99
99
|
"yankee": "^1.0.8"
|