@itentialopensource/adapter-utils 4.47.0 → 4.48.1
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.md +20 -0
- package/lib/connectorRest.js +87 -59
- package/lib/propertyUtil.js +59 -6
- package/lib/requestHandler.js +7 -2
- package/package.json +1 -1
- package/schemas/actionSchema.json +6 -4
- package/schemas/propertiesSchema.json +17 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,24 @@
|
|
|
1
1
|
|
|
2
|
+
## 4.48.1 [09-22-2022]
|
|
3
|
+
|
|
4
|
+
* Add capability to send base64 and buffer in formData
|
|
5
|
+
|
|
6
|
+
Closes ADAPT-2380
|
|
7
|
+
|
|
8
|
+
See merge request itentialopensource/adapter-utils!238
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 4.48.0 [08-16-2022]
|
|
13
|
+
|
|
14
|
+
* Changes to support entitypath object with multiple paths
|
|
15
|
+
|
|
16
|
+
Closes ADAPT-2331
|
|
17
|
+
|
|
18
|
+
See merge request itentialopensource/adapter-utils!236
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
2
22
|
## 4.47.0 [08-13-2022]
|
|
3
23
|
|
|
4
24
|
* Add SSO capability into service instance config
|
package/lib/connectorRest.js
CHANGED
|
@@ -45,6 +45,7 @@ let host = null;
|
|
|
45
45
|
let port = null;
|
|
46
46
|
let basepath = null;
|
|
47
47
|
let version = null;
|
|
48
|
+
let choosepath = null;
|
|
48
49
|
let authMethod = null;
|
|
49
50
|
let authField = null;
|
|
50
51
|
let authFormat = null;
|
|
@@ -254,11 +255,11 @@ function matchMock(uriPath, method, type, mockresponses, respDatatype) {
|
|
|
254
255
|
for (let p = 0; p < mockresponses.length; p += 1) {
|
|
255
256
|
// is this the mock data for this call
|
|
256
257
|
if (Object.hasOwnProperty.call(mockresponses[p], 'name')
|
|
257
|
-
|
|
258
|
+
&& uriPath === mockresponses[p].name) {
|
|
258
259
|
if (Object.hasOwnProperty.call(mockresponses[p], 'method')
|
|
259
|
-
|
|
260
|
+
&& method.toUpperCase() === mockresponses[p].method.toUpperCase()) {
|
|
260
261
|
if (Object.hasOwnProperty.call(mockresponses[p], 'type')
|
|
261
|
-
|
|
262
|
+
&& type.toUpperCase() === mockresponses[p].type.toUpperCase()) {
|
|
262
263
|
// This is the mock data we really want as it best matches the request
|
|
263
264
|
const specificResp = {
|
|
264
265
|
status: 'success',
|
|
@@ -269,7 +270,7 @@ function matchMock(uriPath, method, type, mockresponses, respDatatype) {
|
|
|
269
270
|
if (Object.hasOwnProperty.call(mockresponses[p], 'response')) {
|
|
270
271
|
// if a status is defined in the response, use it
|
|
271
272
|
if (Object.hasOwnProperty.call(mockresponses[p].response, 'response')
|
|
272
|
-
|
|
273
|
+
&& Object.hasOwnProperty.call(mockresponses[p].response, 'status')) {
|
|
273
274
|
specificResp.code = mockresponses[p].response.status;
|
|
274
275
|
|
|
275
276
|
if (respDatatype && respDatatype.toUpperCase() === 'XML2JSON') {
|
|
@@ -395,7 +396,7 @@ function returnStub(request, entitySchema, callProperties) {
|
|
|
395
396
|
|
|
396
397
|
// if there is a request body, see if there is something that matches a specific input
|
|
397
398
|
if (reqBody && (!entitySchema || !entitySchema.requestDatatype
|
|
398
|
-
|
|
399
|
+
|| entitySchema.requestDatatype.toUpperCase() === 'JSON' || entitySchema.requestDatatype.toUpperCase() === 'URLENCODE')) {
|
|
399
400
|
let reqBdObj = null;
|
|
400
401
|
if (entitySchema && entitySchema.requestDatatype && entitySchema.requestDatatype.toUpperCase() === 'URLENCODE') {
|
|
401
402
|
reqBdObj = querystring.parse(reqBody.trim());
|
|
@@ -660,38 +661,60 @@ function makeRequest(request, entitySchema, callProperties, startTrip, attempt,
|
|
|
660
661
|
}
|
|
661
662
|
// add the data for each field into the form
|
|
662
663
|
const mykeys = Object.keys(mybody);
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
664
|
+
if (mykeys.length === 2 && mykeys[0] === 'file' && mykeys[1] === 'convertBase64ToBuffer') {
|
|
665
|
+
const filePart = mybody[mykeys[0]].split(';');
|
|
666
|
+
let fileName = null;
|
|
667
|
+
// see if we have a filename that we should add to the formdata
|
|
668
|
+
for (let p = 1; p < filePart.length; p += 1) {
|
|
669
|
+
if (filePart[p].indexOf('name=') === 0) {
|
|
670
|
+
fileName = filePart[p].substring(5);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
if (mybody.convertBase64ToBuffer === true) {
|
|
674
|
+
let fileBuffer = filePart[filePart.length - 1];
|
|
675
|
+
if (filePart[filePart.length - 1].startsWith('base64')) {
|
|
676
|
+
fileBuffer = Buffer.from(filePart[filePart.length - 1].substring(7), 'base64');
|
|
677
|
+
}
|
|
678
|
+
log.debug(`APPENDING: ${mykeys[0]}, WITH VALUE ${fileBuffer}, AND NAME ${fileName}`);
|
|
679
|
+
formData.append(mykeys[0], fileBuffer, fileName);
|
|
680
|
+
} else {
|
|
681
|
+
log.debug(`APPENDING: ${mykeys[0]}, WITH VALUE ${filePart[filePart.length - 1]}, AND NAME ${fileName}`);
|
|
682
|
+
formData.append(mykeys[0], filePart[filePart.length - 1], fileName);
|
|
683
|
+
}
|
|
684
|
+
} else {
|
|
685
|
+
for (let k = 0; k < mykeys.length; k += 1) {
|
|
686
|
+
if (mykeys[k] === 'file') {
|
|
687
|
+
let fileVal = mybody[mykeys[k]];
|
|
688
|
+
if (fileVal.indexOf('@') === 0) {
|
|
689
|
+
// if there are multiple parts - first part is file, other part can be name
|
|
690
|
+
const filePart = fileVal.split(';');
|
|
691
|
+
let fileName = null;
|
|
692
|
+
fileVal = fs.readFileSync(`node_modules/@itentialopensource/adapter-forwardnetworks/uploads/${filePart[0].substring(1)}`);
|
|
693
|
+
|
|
694
|
+
// see if we have a filename that we should add to the formdata
|
|
695
|
+
for (let p = 1; p < filePart.length; p += 1) {
|
|
696
|
+
if (filePart[p].indexOf('name=') === 0) {
|
|
697
|
+
fileName = filePart[p].substring(5);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
if (fileName) {
|
|
701
|
+
// with filename
|
|
702
|
+
log.debug(`APPENDING: ${mykeys[k]}, WITH VALUE ${fileVal}, AND NAME ${fileName}`);
|
|
703
|
+
formData.append(mykeys[k], fileVal, fileName);
|
|
704
|
+
} else {
|
|
705
|
+
// with read in file but no file name
|
|
706
|
+
log.debug(`APPENDING: ${mykeys[k]}, WITH VALUE ${fileVal}`);
|
|
707
|
+
formData.append(mykeys[k], fileVal);
|
|
676
708
|
}
|
|
677
|
-
}
|
|
678
|
-
if (fileName) {
|
|
679
|
-
// with filename
|
|
680
|
-
log.debug(`APPENDING: ${mykeys[k]}, WITH VALUE ${fileVal}, AND NAME ${fileName}`);
|
|
681
|
-
formData.append(mykeys[k], fileVal, fileName);
|
|
682
709
|
} else {
|
|
683
|
-
//
|
|
710
|
+
// no file or file name just contents - original
|
|
684
711
|
log.debug(`APPENDING: ${mykeys[k]}, WITH VALUE ${fileVal}`);
|
|
685
712
|
formData.append(mykeys[k], fileVal);
|
|
686
713
|
}
|
|
687
714
|
} else {
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
formData.append(mykeys[k], fileVal);
|
|
715
|
+
log.debug(`APPENDING: ${mykeys[k]}, WITH VALUE ${mybody[mykeys[k]]}`);
|
|
716
|
+
formData.append(mykeys[k], mybody[mykeys[k]]);
|
|
691
717
|
}
|
|
692
|
-
} else {
|
|
693
|
-
log.debug(`APPENDING: ${mykeys[k]}, WITH VALUE ${mybody[mykeys[k]]}`);
|
|
694
|
-
formData.append(mykeys[k], mybody[mykeys[k]]);
|
|
695
718
|
}
|
|
696
719
|
}
|
|
697
720
|
// get the new headers
|
|
@@ -887,7 +910,7 @@ function makeRequest(request, entitySchema, callProperties, startTrip, attempt,
|
|
|
887
910
|
|
|
888
911
|
// write to the http request data to the body if not a get (gets do not have data in the body)
|
|
889
912
|
if ((request.header.method !== 'GET' || entitySchema.sendGetBody)
|
|
890
|
-
|
|
913
|
+
&& ((typeof request.body === 'object' && Object.keys(request.body).length > 0)
|
|
891
914
|
|| (typeof request.body === 'string' && request.body !== '{}') || entitySchema.sendEmpty)) {
|
|
892
915
|
if (entitySchema.requestDatatype.toUpperCase() === 'FORM') {
|
|
893
916
|
// pass the formData to the request
|
|
@@ -1204,7 +1227,7 @@ function getToken(reqPath, options, tokenSchema, bodyString, callProperties, cal
|
|
|
1204
1227
|
|
|
1205
1228
|
// process primary token from header
|
|
1206
1229
|
if (tokenSchema.responseSchema && tokenSchema.responseSchema.properties && tokenSchema.responseSchema.properties.token
|
|
1207
|
-
|
|
1230
|
+
&& tokenSchema.responseSchema.properties.token.placement && tokenSchema.responseSchema.properties.token.placement.toUpperCase() === 'HEADER') {
|
|
1208
1231
|
if (!tokenSchema.responseSchema.properties.token.external_name) {
|
|
1209
1232
|
const errorObj = transUtilInst.formatErrorObject(origin, 'Unable To Get Primary Token', ['Primary Token', result.code], null, null, null);
|
|
1210
1233
|
log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
|
|
@@ -1503,7 +1526,7 @@ function buildTokenRequest(reqPath, reqBody, callProperties, callback) {
|
|
|
1503
1526
|
|
|
1504
1527
|
try {
|
|
1505
1528
|
// Get the entity schema from the file system
|
|
1506
|
-
return propUtilInst.getEntitySchema('.system', 'getToken', this.dbUtil, (tokenSchema, healthError) => {
|
|
1529
|
+
return propUtilInst.getEntitySchema('.system', 'getToken', choosepath, this.dbUtil, (tokenSchema, healthError) => {
|
|
1507
1530
|
if (healthError || !tokenSchema || Object.keys(tokenSchema).length === 0) {
|
|
1508
1531
|
log.debug(`${origin}: Using adapter properties for token information`);
|
|
1509
1532
|
tokenSchema = null;
|
|
@@ -1793,7 +1816,7 @@ function buildTokenRequest(reqPath, reqBody, callProperties, callback) {
|
|
|
1793
1816
|
|
|
1794
1817
|
// only add global options if there are global options to add
|
|
1795
1818
|
if (globalRequest && globalRequest.uriOptions
|
|
1796
|
-
|
|
1819
|
+
&& Object.keys(globalRequest.uriOptions).length > 0) {
|
|
1797
1820
|
const optionString = querystring.stringify(globalRequest.uriOptions);
|
|
1798
1821
|
|
|
1799
1822
|
// if no query paramters yet - start with ?
|
|
@@ -2105,7 +2128,7 @@ function validToken(user, reqBody, invalidToken, callback) {
|
|
|
2105
2128
|
// if the token expired (or will expire within a minute),
|
|
2106
2129
|
// or it is invalid (failed) remove it from the token list
|
|
2107
2130
|
if (tokenList[i].expire < expireCheck
|
|
2108
|
-
|
|
2131
|
+
|| tokenList[i].token.token === invalidToken) {
|
|
2109
2132
|
tokenList.splice(i, 1);
|
|
2110
2133
|
break;
|
|
2111
2134
|
}
|
|
@@ -2819,7 +2842,7 @@ function handleEndThrottleResponse(request, myTransTime, claimedLic, makeResp, r
|
|
|
2819
2842
|
|
|
2820
2843
|
// If the request was successful
|
|
2821
2844
|
if (makeResp !== null && makeResp.code !== undefined
|
|
2822
|
-
|
|
2845
|
+
&& Number(makeResp.code) >= 200 && Number(makeResp.code) <= 299) {
|
|
2823
2846
|
const newResp = {
|
|
2824
2847
|
icode: `AD.${makeResp.code}`,
|
|
2825
2848
|
response: makeResp.response,
|
|
@@ -2918,7 +2941,7 @@ function retryInvalidResponse(request, callProperties, myTransTime, claimedLic,
|
|
|
2918
2941
|
let retries = numRetries;
|
|
2919
2942
|
if (callProperties && callProperties.request && callProperties.request.limit_retry_error) {
|
|
2920
2943
|
if (typeof callProperties.request.limit_retry_error === 'number'
|
|
2921
|
-
|
|
2944
|
+
|| typeof callProperties.request.limit_retry_error === 'string') {
|
|
2922
2945
|
retryError = [Number(callProperties.request.limit_retry_error)];
|
|
2923
2946
|
} else if (Array.isArray(callProperties.request.limit_retry_error)) {
|
|
2924
2947
|
retryError = [];
|
|
@@ -2926,10 +2949,10 @@ function retryInvalidResponse(request, callProperties, myTransTime, claimedLic,
|
|
|
2926
2949
|
if (typeof callProperties.request.limit_retry_error[l] === 'number') {
|
|
2927
2950
|
retryError.push(Number(callProperties.request.limit_retry_error[l]));
|
|
2928
2951
|
} else if (typeof callProperties.request.limit_retry_error[l] === 'string'
|
|
2929
|
-
|
|
2952
|
+
&& callProperties.request.limit_retry_error[l].indexOf('-') < 0) {
|
|
2930
2953
|
retryError.push(Number(callProperties.request.limit_retry_error[l]));
|
|
2931
2954
|
} else if (typeof callProperties.request.limit_retry_error[l] === 'string'
|
|
2932
|
-
|
|
2955
|
+
&& callProperties.request.limit_retry_error[l].indexOf('-') >= 0) {
|
|
2933
2956
|
const srange = Number(callProperties.request.limit_retry_error[l].split('-')[0]);
|
|
2934
2957
|
const erange = Number(callProperties.request.limit_retry_error[l].split('-')[1]);
|
|
2935
2958
|
for (let r = srange; r <= erange; r += 1) {
|
|
@@ -2946,7 +2969,7 @@ function retryInvalidResponse(request, callProperties, myTransTime, claimedLic,
|
|
|
2946
2969
|
// if the response is valid - good data or legitimate data error
|
|
2947
2970
|
// stop trying if we have tried enough
|
|
2948
2971
|
if (numTries > retries || (mres !== null && mres.code !== undefined && !retryError.includes(Number(mres.code))
|
|
2949
|
-
|
|
2972
|
+
&& (authMethod !== 'request_token' || Number(mres.code) !== Number(tokenError)))) {
|
|
2950
2973
|
const newresp = mres;
|
|
2951
2974
|
newresp.retries = numTries;
|
|
2952
2975
|
|
|
@@ -3082,7 +3105,7 @@ function noQueueRequest(request, callProperties, overallTime, entitySchema, call
|
|
|
3082
3105
|
let retries = numRetries;
|
|
3083
3106
|
if (callProperties && callProperties.request && callProperties.request.limit_retry_error) {
|
|
3084
3107
|
if (typeof callProperties.request.limit_retry_error === 'number'
|
|
3085
|
-
|
|
3108
|
+
|| typeof callProperties.request.limit_retry_error === 'string') {
|
|
3086
3109
|
retryError = [Number(callProperties.request.limit_retry_error)];
|
|
3087
3110
|
} else if (Array.isArray(callProperties.request.limit_retry_error)) {
|
|
3088
3111
|
retryError = [];
|
|
@@ -3090,10 +3113,10 @@ function noQueueRequest(request, callProperties, overallTime, entitySchema, call
|
|
|
3090
3113
|
if (typeof callProperties.request.limit_retry_error[l] === 'number') {
|
|
3091
3114
|
retryError.push(Number(callProperties.request.limit_retry_error[l]));
|
|
3092
3115
|
} else if (typeof callProperties.request.limit_retry_error[l] === 'string'
|
|
3093
|
-
|
|
3116
|
+
&& callProperties.request.limit_retry_error[l].indexOf('-') < 0) {
|
|
3094
3117
|
retryError.push(Number(callProperties.request.limit_retry_error[l]));
|
|
3095
3118
|
} else if (typeof callProperties.request.limit_retry_error[l] === 'string'
|
|
3096
|
-
|
|
3119
|
+
&& callProperties.request.limit_retry_error[l].indexOf('-') >= 0) {
|
|
3097
3120
|
const srange = Number(callProperties.request.limit_retry_error[l].split('-')[0]);
|
|
3098
3121
|
const erange = Number(callProperties.request.limit_retry_error[l].split('-')[1]);
|
|
3099
3122
|
for (let r = srange; r <= erange; r += 1) {
|
|
@@ -3109,14 +3132,14 @@ function noQueueRequest(request, callProperties, overallTime, entitySchema, call
|
|
|
3109
3132
|
|
|
3110
3133
|
// if invalid token, handle that and retry
|
|
3111
3134
|
if (mres !== null && mres.code !== undefined && Number(mres.code) === Number(tokenError)
|
|
3112
|
-
|
|
3135
|
+
&& authMethod === 'request_token') {
|
|
3113
3136
|
// if we took an invalid token - try one more time
|
|
3114
3137
|
return handleInvalidToken(request, callProperties, 0, { request_id: 0 }, mres, overallTime, overallTime, 0, 1, entitySchema, callback);
|
|
3115
3138
|
}
|
|
3116
3139
|
|
|
3117
3140
|
// if the response is valid - good data or legitimate data error
|
|
3118
3141
|
if (retries < 1 || (mres !== null && mres.code !== undefined && !retryError.includes(Number(mres.code))
|
|
3119
|
-
|
|
3142
|
+
&& (authMethod !== 'request_token' || Number(mres.code) !== Number(tokenError)))) {
|
|
3120
3143
|
return handleEndResponse(request, mres, overallTime, callback);
|
|
3121
3144
|
}
|
|
3122
3145
|
|
|
@@ -3181,7 +3204,7 @@ function queueThrottleRequest(request, callProperties, myRequestId, myTransTime,
|
|
|
3181
3204
|
let retries = numRetries;
|
|
3182
3205
|
if (callProperties && callProperties.request && callProperties.request.limit_retry_error) {
|
|
3183
3206
|
if (typeof callProperties.request.limit_retry_error === 'number'
|
|
3184
|
-
|
|
3207
|
+
|| typeof callProperties.request.limit_retry_error === 'string') {
|
|
3185
3208
|
retryError = [Number(callProperties.request.limit_retry_error)];
|
|
3186
3209
|
} else if (Array.isArray(callProperties.request.limit_retry_error)) {
|
|
3187
3210
|
retryError = [];
|
|
@@ -3189,10 +3212,10 @@ function queueThrottleRequest(request, callProperties, myRequestId, myTransTime,
|
|
|
3189
3212
|
if (typeof callProperties.request.limit_retry_error[l] === 'number') {
|
|
3190
3213
|
retryError.push(Number(callProperties.request.limit_retry_error[l]));
|
|
3191
3214
|
} else if (typeof callProperties.request.limit_retry_error[l] === 'string'
|
|
3192
|
-
|
|
3215
|
+
&& callProperties.request.limit_retry_error[l].indexOf('-') < 0) {
|
|
3193
3216
|
retryError.push(Number(callProperties.request.limit_retry_error[l]));
|
|
3194
3217
|
} else if (typeof callProperties.request.limit_retry_error[l] === 'string'
|
|
3195
|
-
|
|
3218
|
+
&& callProperties.request.limit_retry_error[l].indexOf('-') >= 0) {
|
|
3196
3219
|
const srange = Number(callProperties.request.limit_retry_error[l].split('-')[0]);
|
|
3197
3220
|
const erange = Number(callProperties.request.limit_retry_error[l].split('-')[1]);
|
|
3198
3221
|
for (let r = srange; r <= erange; r += 1) {
|
|
@@ -3208,14 +3231,14 @@ function queueThrottleRequest(request, callProperties, myRequestId, myTransTime,
|
|
|
3208
3231
|
|
|
3209
3232
|
// if invalid token, handle that and retry
|
|
3210
3233
|
if (mres !== null && mres.code !== undefined && Number(mres.code) === Number(tokenError)
|
|
3211
|
-
|
|
3234
|
+
&& authMethod === 'request_token') {
|
|
3212
3235
|
// if we took an invalid token - try one more time
|
|
3213
3236
|
return handleInvalidToken(request, callProperties, myTransTime, claimedLic, mres, reqTime, overallTime, waitEnd, 1, entitySchema, callback);
|
|
3214
3237
|
}
|
|
3215
3238
|
|
|
3216
3239
|
// if the response is valid - good data or legitimate data error
|
|
3217
3240
|
if (retries < 1 || (mres !== null && mres.code !== undefined && !retryError.includes(Number(mres.code))
|
|
3218
|
-
|
|
3241
|
+
&& (authMethod !== 'request_token' || Number(mres.code) !== Number(tokenError)))) {
|
|
3219
3242
|
return handleEndThrottleResponse(request, myTransTime, claimedLic, mres, reqTime, overallTime, waitEnd, callback);
|
|
3220
3243
|
}
|
|
3221
3244
|
|
|
@@ -3317,6 +3340,11 @@ class ConnectorRest {
|
|
|
3317
3340
|
version = props.version;
|
|
3318
3341
|
}
|
|
3319
3342
|
|
|
3343
|
+
// set the choosepath (optional - default is null)
|
|
3344
|
+
if (typeof props.choosepath === 'string') {
|
|
3345
|
+
choosepath = props.choosepath;
|
|
3346
|
+
}
|
|
3347
|
+
|
|
3320
3348
|
if (props.authentication) {
|
|
3321
3349
|
// set the authentication method (required - default is null)
|
|
3322
3350
|
if (typeof props.authentication.auth_method === 'string') {
|
|
@@ -3360,13 +3388,13 @@ class ConnectorRest {
|
|
|
3360
3388
|
|
|
3361
3389
|
// set the invalid token error (optional - default is null)
|
|
3362
3390
|
if (typeof props.authentication.invalid_token_error === 'number'
|
|
3363
|
-
|
|
3391
|
+
|| typeof props.authentication.invalid_token_error === 'string') {
|
|
3364
3392
|
tokenError = Number(props.authentication.invalid_token_error);
|
|
3365
3393
|
}
|
|
3366
3394
|
|
|
3367
3395
|
// set the token timeout (optional - default is null)
|
|
3368
3396
|
if (typeof props.authentication.token_timeout === 'number'
|
|
3369
|
-
|
|
3397
|
+
|| typeof props.authentication.token_timeout === 'string') {
|
|
3370
3398
|
tokenTimeout = Number(props.authentication.token_timeout);
|
|
3371
3399
|
}
|
|
3372
3400
|
|
|
@@ -3447,19 +3475,19 @@ class ConnectorRest {
|
|
|
3447
3475
|
if (props.request) {
|
|
3448
3476
|
// set the number of redirects (optional - default is 0)
|
|
3449
3477
|
if (typeof props.request.number_redirects === 'number'
|
|
3450
|
-
|
|
3478
|
+
|| typeof props.request.number_redirects === 'string') {
|
|
3451
3479
|
numRedirects = Number(props.request.number_redirects);
|
|
3452
3480
|
}
|
|
3453
3481
|
|
|
3454
3482
|
// set the number of retries (optional - default is 3)
|
|
3455
3483
|
if (typeof props.request.number_retries === 'number'
|
|
3456
|
-
|
|
3484
|
+
|| typeof props.request.number_retries === 'string') {
|
|
3457
3485
|
numRetries = Number(props.request.number_retries);
|
|
3458
3486
|
}
|
|
3459
3487
|
|
|
3460
3488
|
// set the request retry error (optional - default is 0)
|
|
3461
3489
|
if (typeof props.request.limit_retry_error === 'number'
|
|
3462
|
-
|
|
3490
|
+
|| typeof props.request.limit_retry_error === 'string') {
|
|
3463
3491
|
limitRetryError = [Number(props.request.limit_retry_error)];
|
|
3464
3492
|
} else if (Array.isArray(props.request.limit_retry_error)) {
|
|
3465
3493
|
limitRetryError = [];
|
|
@@ -3467,10 +3495,10 @@ class ConnectorRest {
|
|
|
3467
3495
|
if (typeof props.request.limit_retry_error[l] === 'number') {
|
|
3468
3496
|
limitRetryError.push(Number(props.request.limit_retry_error[l]));
|
|
3469
3497
|
} else if (typeof props.request.limit_retry_error[l] === 'string'
|
|
3470
|
-
|
|
3498
|
+
&& props.request.limit_retry_error[l].indexOf('-') < 0) {
|
|
3471
3499
|
limitRetryError.push(Number(props.request.limit_retry_error[l]));
|
|
3472
3500
|
} else if (typeof props.request.limit_retry_error[l] === 'string'
|
|
3473
|
-
|
|
3501
|
+
&& props.request.limit_retry_error[l].indexOf('-') >= 0) {
|
|
3474
3502
|
const srange = Number(props.request.limit_retry_error[l].split('-')[0]);
|
|
3475
3503
|
const erange = Number(props.request.limit_retry_error[l].split('-')[1]);
|
|
3476
3504
|
for (let r = srange; r <= erange; r += 1) {
|
|
@@ -3482,7 +3510,7 @@ class ConnectorRest {
|
|
|
3482
3510
|
|
|
3483
3511
|
// set the request attempt timeout (optional - default is 5000)
|
|
3484
3512
|
if (typeof props.request.attempt_timeout === 'number'
|
|
3485
|
-
|
|
3513
|
+
|| typeof props.request.attempt_timeout === 'string') {
|
|
3486
3514
|
attemptTimeout = Number(props.request.attempt_timeout);
|
|
3487
3515
|
}
|
|
3488
3516
|
|
|
@@ -3904,7 +3932,7 @@ class ConnectorRest {
|
|
|
3904
3932
|
}
|
|
3905
3933
|
|
|
3906
3934
|
if (pres !== null && pres.code !== undefined
|
|
3907
|
-
|
|
3935
|
+
&& (Number(pres.code) < 200 || Number(pres.code) > 299)) {
|
|
3908
3936
|
let errorObj = null;
|
|
3909
3937
|
|
|
3910
3938
|
if (pres.code === -2) {
|
package/lib/propertyUtil.js
CHANGED
|
@@ -30,7 +30,7 @@ class AdapterPropertyUtil {
|
|
|
30
30
|
*
|
|
31
31
|
* @return {Object} entitySchema - the entity schema object
|
|
32
32
|
*/
|
|
33
|
-
getEntitySchemaFromFS(entityName, actionName) {
|
|
33
|
+
getEntitySchemaFromFS(entityName, actionName, choosepath) {
|
|
34
34
|
const origin = `${this.myid}-propertyUtil-getEntitySchemaFromFS`;
|
|
35
35
|
log.trace(origin);
|
|
36
36
|
|
|
@@ -264,6 +264,32 @@ class AdapterPropertyUtil {
|
|
|
264
264
|
entitySchema.responseObjects = [];
|
|
265
265
|
entitySchema.mockresponses = [];
|
|
266
266
|
|
|
267
|
+
// if the entitypath is an object instead of a string need to figure out which path to use
|
|
268
|
+
if (actionInfo.entitypath && typeof actionInfo.entitypath === 'object') {
|
|
269
|
+
const ekeys = Object.keys(actionInfo.entitypath);
|
|
270
|
+
if (ekeys.length > 0) {
|
|
271
|
+
// the first one is the default so if we do not have a match that is the one that will be used
|
|
272
|
+
entitySchema.entitypath = actionInfo.entitypath[ekeys[0]];
|
|
273
|
+
for (let ep = 1; ep < ekeys.length; ep += 1) {
|
|
274
|
+
// see if the key matches the choosepath value, if it does set the entitypath
|
|
275
|
+
if (choosepath && ekeys[ep] === choosepath) {
|
|
276
|
+
entitySchema.entitypath = actionInfo.entitypath[ekeys[ep]];
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
} else {
|
|
281
|
+
// add the specific pieces of the error object
|
|
282
|
+
errorObj.type = 'Invalid Action File';
|
|
283
|
+
errorObj.vars = ['missing entity path', actionFile];
|
|
284
|
+
|
|
285
|
+
// log (if not system entity) and throw the error
|
|
286
|
+
if (entityName !== '.system') {
|
|
287
|
+
log.error(`${origin}: Entity ${entityName} action ${actionName} - missing entity path`);
|
|
288
|
+
}
|
|
289
|
+
throw new Error(JSON.stringify(errorObj));
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
267
293
|
// if info provided, replace the defaults
|
|
268
294
|
if (actionInfo.querykey) {
|
|
269
295
|
entitySchema.querykey = actionInfo.querykey;
|
|
@@ -399,7 +425,7 @@ class AdapterPropertyUtil {
|
|
|
399
425
|
*
|
|
400
426
|
* @return {Object} entitySchema - the entity schema object
|
|
401
427
|
*/
|
|
402
|
-
getEntitySchemaFromDB(dbObj, entityName, actionName, dbUtils, callback) {
|
|
428
|
+
getEntitySchemaFromDB(dbObj, entityName, actionName, choosepath, dbUtils, callback) {
|
|
403
429
|
const origin = `${this.myid}-propertyUtil-getEntitySchemaFromDB`;
|
|
404
430
|
log.trace(origin);
|
|
405
431
|
|
|
@@ -672,6 +698,33 @@ class AdapterPropertyUtil {
|
|
|
672
698
|
entitySchema.responseObjects = [];
|
|
673
699
|
entitySchema.mockresponses = [];
|
|
674
700
|
|
|
701
|
+
// if the entitypath is an object instead of a string need to figure out which path to use
|
|
702
|
+
if (actionInfo.entitypath && typeof actionInfo.entitypath === 'object') {
|
|
703
|
+
const ekeys = Object.keys(actionInfo.entitypath);
|
|
704
|
+
if (ekeys.length > 0) {
|
|
705
|
+
// the first one is the default so if we do not have a match that is the one that will be used
|
|
706
|
+
entitySchema.entitypath = actionInfo.entitypath[ekeys[0]];
|
|
707
|
+
for (let ep = 1; ep < ekeys.length; ep += 1) {
|
|
708
|
+
// see if the key matches the choosepath value, if it does set the entitypath
|
|
709
|
+
if (choosepath && ekeys[ep] === choosepath) {
|
|
710
|
+
entitySchema.entitypath = actionInfo.entitypath[ekeys[ep]];
|
|
711
|
+
break;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
} else {
|
|
715
|
+
// add the specific pieces of the error object
|
|
716
|
+
errorObj.type = 'Invalid Action File';
|
|
717
|
+
errorObj.vars = ['missing entity path', entityName];
|
|
718
|
+
|
|
719
|
+
// log (if not system entity) and return the error
|
|
720
|
+
if (entityName !== '.system') {
|
|
721
|
+
log.error(`${origin}: Entity ${entityName} action ${actionName} - missing entity path`);
|
|
722
|
+
errorObj.error = [`${origin}: Entity ${entityName} action ${actionName} - missing entity path`];
|
|
723
|
+
}
|
|
724
|
+
return callback(null, errorObj);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
675
728
|
// if info provided, replace the defaults
|
|
676
729
|
if (actionInfo.querykey) {
|
|
677
730
|
entitySchema.querykey = actionInfo.querykey;
|
|
@@ -796,14 +849,14 @@ class AdapterPropertyUtil {
|
|
|
796
849
|
*
|
|
797
850
|
* @return {Object} entitySchema - the entity schema object
|
|
798
851
|
*/
|
|
799
|
-
getEntitySchema(entityName, actionName, dbUtils, callback) {
|
|
852
|
+
getEntitySchema(entityName, actionName, choosepath, dbUtils, callback) {
|
|
800
853
|
const origin = `${this.myid}-propertyUtil-getEntitySchema`;
|
|
801
854
|
log.trace(origin);
|
|
802
855
|
|
|
803
856
|
// need to try to get the entity schema from the adapter database
|
|
804
857
|
try {
|
|
805
858
|
// call to get the adapter schema from the database
|
|
806
|
-
return this.getEntitySchemaFromDB(null, entityName, actionName, dbUtils, (dbresp, dberror) => {
|
|
859
|
+
return this.getEntitySchemaFromDB(null, entityName, actionName, choosepath, dbUtils, (dbresp, dberror) => {
|
|
807
860
|
// if we got an error back - just means db config not in place
|
|
808
861
|
if (dberror || !dbresp || (dbresp && Object.keys(dbresp).length === 0)) {
|
|
809
862
|
log.debug('unable to get adapter config from adapter database');
|
|
@@ -816,7 +869,7 @@ class AdapterPropertyUtil {
|
|
|
816
869
|
};
|
|
817
870
|
|
|
818
871
|
// need to try to get the entity schema from the iap database
|
|
819
|
-
return this.getEntitySchemaFromDB(iapDB, entityName, actionName, dbUtils, (iapdbresp, iapdberror) => {
|
|
872
|
+
return this.getEntitySchemaFromDB(iapDB, entityName, actionName, choosepath, dbUtils, (iapdbresp, iapdberror) => {
|
|
820
873
|
// if we got an error back - just means db config not in place
|
|
821
874
|
if (iapdberror || !iapdbresp || (iapdbresp && Object.keys(iapdbresp).length === 0)) {
|
|
822
875
|
log.debug('unable to get adapter config from iap database');
|
|
@@ -824,7 +877,7 @@ class AdapterPropertyUtil {
|
|
|
824
877
|
// need to try to get the entity schema from the filesystem
|
|
825
878
|
log.debug('returning adapter config from file system');
|
|
826
879
|
try {
|
|
827
|
-
return callback(this.getEntitySchemaFromFS(entityName, actionName), null);
|
|
880
|
+
return callback(this.getEntitySchemaFromFS(entityName, actionName, choosepath), null);
|
|
828
881
|
} catch (exc) {
|
|
829
882
|
log.error('Exception caught on File System');
|
|
830
883
|
return callback(null, exc);
|
package/lib/requestHandler.js
CHANGED
|
@@ -117,6 +117,11 @@ function walkThroughActionFiles(directory) {
|
|
|
117
117
|
const actionSchema = JSON.parse(fs.readFileSync(actionSchemaFile, 'utf-8'));
|
|
118
118
|
const entitydir = `${directory}/entities`;
|
|
119
119
|
|
|
120
|
+
// if there is no entity directory - return
|
|
121
|
+
if (!fs.existsSync(directory) || !fs.existsSync(entitydir)) {
|
|
122
|
+
return clean;
|
|
123
|
+
}
|
|
124
|
+
|
|
120
125
|
// if there is an entity directory
|
|
121
126
|
if (fs.statSync(directory).isDirectory() && fs.statSync(entitydir).isDirectory()) {
|
|
122
127
|
const entities = fs.readdirSync(entitydir);
|
|
@@ -577,7 +582,7 @@ class RequestHandler {
|
|
|
577
582
|
}
|
|
578
583
|
|
|
579
584
|
// Get the entity schema from the file system
|
|
580
|
-
return this.propUtil.getEntitySchema(entity, action, this.dbUtil, (entitySchema, entityError) => {
|
|
585
|
+
return this.propUtil.getEntitySchema(entity, action, this.props.choosepath, this.dbUtil, (entitySchema, entityError) => {
|
|
581
586
|
// verify protocol for call
|
|
582
587
|
if (entityError) {
|
|
583
588
|
const errorObj = this.transUtil.checkAndReturn(entityError, origin, 'Issue identifiying request');
|
|
@@ -673,7 +678,7 @@ class RequestHandler {
|
|
|
673
678
|
let prot = this.props.healthcheck.protocol;
|
|
674
679
|
|
|
675
680
|
// Get the entity schema from the file system
|
|
676
|
-
return this.propUtil.getEntitySchema('.system', 'healthcheck', this.dbUtil, (healthSchema, healthError) => {
|
|
681
|
+
return this.propUtil.getEntitySchema('.system', 'healthcheck', this.props.choosepath, this.dbUtil, (healthSchema, healthError) => {
|
|
677
682
|
if (healthError || !healthSchema || Object.keys(healthSchema).length === 0) {
|
|
678
683
|
log.debug(`${origin}: Using adapter properties for healthcheck information`);
|
|
679
684
|
} else {
|
package/package.json
CHANGED
|
@@ -32,10 +32,12 @@
|
|
|
32
32
|
]
|
|
33
33
|
},
|
|
34
34
|
"entitypath": {
|
|
35
|
-
"type":
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
"type": [
|
|
36
|
+
"string",
|
|
37
|
+
"object"
|
|
38
|
+
],
|
|
39
|
+
"description": "the path(s) to use for this action",
|
|
40
|
+
"default": "",
|
|
39
41
|
"examples": [
|
|
40
42
|
"/api/devices{pathv1}{query}", "/api/devices{pathv1}/components{pathv2}{query}",
|
|
41
43
|
"/api/devices", "/api/devices{query}"
|
|
@@ -18,6 +18,11 @@
|
|
|
18
18
|
"minimum": 1,
|
|
19
19
|
"maximum": 65535
|
|
20
20
|
},
|
|
21
|
+
"choosepath": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"description": "choose the path to use -- requires entityPath choices",
|
|
24
|
+
"default": ""
|
|
25
|
+
},
|
|
21
26
|
"base_path": {
|
|
22
27
|
"type": "string",
|
|
23
28
|
"description": "a base path that is consistent across api calls",
|
|
@@ -382,7 +387,8 @@
|
|
|
382
387
|
},
|
|
383
388
|
"query_object": {
|
|
384
389
|
"type": "object",
|
|
385
|
-
"description": "Query object { device: xxxxx } to be placed into the healthcheck, will be converted to query string by the adapter"
|
|
390
|
+
"description": "Query object { device: xxxxx } to be placed into the healthcheck, will be converted to query string by the adapter",
|
|
391
|
+
"default": {}
|
|
386
392
|
}
|
|
387
393
|
},
|
|
388
394
|
"required": [
|
|
@@ -462,6 +468,7 @@
|
|
|
462
468
|
"priorities": {
|
|
463
469
|
"type": "array",
|
|
464
470
|
"description": "define your priorities here",
|
|
471
|
+
"default": [],
|
|
465
472
|
"items": {
|
|
466
473
|
"type": "object",
|
|
467
474
|
"properties": {
|
|
@@ -532,6 +539,7 @@
|
|
|
532
539
|
"failover_codes": {
|
|
533
540
|
"type": "array",
|
|
534
541
|
"description": "An array of codes where it is ok to try another method",
|
|
542
|
+
"default": [],
|
|
535
543
|
"items": {
|
|
536
544
|
"type": "integer"
|
|
537
545
|
}
|
|
@@ -549,19 +557,23 @@
|
|
|
549
557
|
"properties": {
|
|
550
558
|
"payload": {
|
|
551
559
|
"type": "object",
|
|
552
|
-
"description": "payload fields that will be appended to the provided payload (excluding GET calls)"
|
|
560
|
+
"description": "payload fields that will be appended to the provided payload (excluding GET calls)",
|
|
561
|
+
"default": {}
|
|
553
562
|
},
|
|
554
563
|
"uriOptions": {
|
|
555
564
|
"type": "object",
|
|
556
|
-
"description": "options that will be appended to all GET calls"
|
|
565
|
+
"description": "options that will be appended to all GET calls",
|
|
566
|
+
"default": {}
|
|
557
567
|
},
|
|
558
568
|
"addlHeaders": {
|
|
559
569
|
"type": "object",
|
|
560
|
-
"description": "headers that will be appended to the headers for the call"
|
|
570
|
+
"description": "headers that will be appended to the headers for the call",
|
|
571
|
+
"default": {}
|
|
561
572
|
},
|
|
562
573
|
"authData": {
|
|
563
574
|
"type": "object",
|
|
564
|
-
"description": "authentication data that will be appended to the payload for authentication calls"
|
|
575
|
+
"description": "authentication data that will be appended to the payload for authentication calls",
|
|
576
|
+
"default": {}
|
|
565
577
|
}
|
|
566
578
|
}
|
|
567
579
|
},
|