@mojaloop/central-services-shared 14.0.0 → 15.2.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.md +32 -0
- package/audit-resolve.json +67 -24
- package/package.json +22 -22
- package/src/enums/events.js +5 -0
- package/src/enums/kafka.js +8 -0
- package/src/index.d.ts +10 -1
- package/src/util/hapi/plugins/headerValidation.js +9 -6
- package/src/util/headerValidation/index.js +28 -3
- package/src/util/headers/transformer.js +67 -7
- package/src/util/request.js +13 -6
- package/test/unit/headers/transformer.test.js +77 -0
- package/test/unit/util/headerValidation/{validation.test.js → index.test.js} +92 -1
- package/test/unit/util/request.test.js +53 -0
- package/test/util/helper.js +6 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [15.2.0](https://github.com/mojaloop/central-services-shared/compare/v15.1.0...v15.2.0) (2021-12-13)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **mojaloop/#2608:** injected resource versions config for outbound requests ([#319](https://github.com/mojaloop/central-services-shared/issues/319)) ([13a3d9d](https://github.com/mojaloop/central-services-shared/commit/13a3d9dc8ab8d4815db2aea22563317e3670a19b)), closes [mojaloop/#2608](https://github.com/mojaloop/central-services-shared/issues/2608)
|
|
11
|
+
|
|
12
|
+
## [15.1.0](https://github.com/mojaloop/central-services-shared/compare/v15.0.1...v15.1.0) (2021-11-17)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* add a new action enum for `RESERVED_ABORTED` ([#317](https://github.com/mojaloop/central-services-shared/issues/317)) ([0e743b8](https://github.com/mojaloop/central-services-shared/commit/0e743b82a90dd0c97ce3c72454621c191d2a6675))
|
|
18
|
+
|
|
19
|
+
### [15.0.1](https://github.com/mojaloop/central-services-shared/compare/v15.0.0...v15.0.1) (2021-11-08)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Bug Fixes
|
|
23
|
+
|
|
24
|
+
* **#2557:** error notification to payer fsp, header for source having wrong value ([#316](https://github.com/mojaloop/central-services-shared/issues/316)) ([d4b95b6](https://github.com/mojaloop/central-services-shared/commit/d4b95b619ce2c4f810ae6909859ef6dbf5894ad0)), closes [#2557](https://github.com/mojaloop/central-services-shared/issues/2557)
|
|
25
|
+
|
|
26
|
+
## [15.0.0](https://github.com/mojaloop/central-services-shared/compare/v14.0.0...v15.0.0) (2021-10-18)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### ⚠ BREAKING CHANGES
|
|
30
|
+
|
|
31
|
+
* **mojaloop/#2536:** split options config for supportedProtocolVersions to supportedProtocolVersions & supportedProtocolAcceptVersions of HeaderValidation Hapi Plugin. It should be backward compatible, but forcing a major version bump to reflect this new functionality.
|
|
32
|
+
|
|
33
|
+
### Bug Fixes
|
|
34
|
+
|
|
35
|
+
* **mojaloop/#2536:** fspiop api version negotiation not handled by transfers service ([#315](https://github.com/mojaloop/central-services-shared/issues/315)) ([e3a8748](https://github.com/mojaloop/central-services-shared/commit/e3a874829794ed8b85b6487dd58bcb58f31a5dd1)), closes [mojaloop/#2536](https://github.com/mojaloop/central-services-shared/issues/2536) [mojaloop/#2536](https://github.com/mojaloop/central-services-shared/issues/2536)
|
|
36
|
+
|
|
5
37
|
## [14.0.0](https://github.com/mojaloop/central-services-shared/compare/v13.4.1...v14.0.0) (2021-09-10)
|
|
6
38
|
|
|
7
39
|
|
package/audit-resolve.json
CHANGED
|
@@ -1,41 +1,84 @@
|
|
|
1
1
|
{
|
|
2
2
|
"decisions": {
|
|
3
|
-
"
|
|
3
|
+
"1002401|widdershins>yargs>string-width>strip-ansi>ansi-regex": {
|
|
4
4
|
"decision": "ignore",
|
|
5
|
-
"madeAt":
|
|
6
|
-
"expiresAt":
|
|
5
|
+
"madeAt": 1636372052422,
|
|
6
|
+
"expiresAt": 1638964045850
|
|
7
7
|
},
|
|
8
|
-
"
|
|
9
|
-
"decision": "
|
|
10
|
-
"madeAt":
|
|
8
|
+
"1002401|widdershins>yargs>cliui>string-width>strip-ansi>ansi-regex": {
|
|
9
|
+
"decision": "ignore",
|
|
10
|
+
"madeAt": 1636372052422,
|
|
11
|
+
"expiresAt": 1638964045850
|
|
12
|
+
},
|
|
13
|
+
"1002865|shins>sanitize-html": {
|
|
14
|
+
"decision": "ignore",
|
|
15
|
+
"madeAt": 1636372053964,
|
|
16
|
+
"expiresAt": 1638964045850
|
|
17
|
+
},
|
|
18
|
+
"1002866|shins>sanitize-html": {
|
|
19
|
+
"decision": "ignore",
|
|
20
|
+
"madeAt": 1636372053964,
|
|
21
|
+
"expiresAt": 1638964045850
|
|
11
22
|
},
|
|
12
|
-
"
|
|
13
|
-
"decision": "
|
|
14
|
-
"madeAt":
|
|
23
|
+
"1003019|widdershins>yargs>yargs-parser": {
|
|
24
|
+
"decision": "ignore",
|
|
25
|
+
"madeAt": 1636372055094,
|
|
26
|
+
"expiresAt": 1638964045850
|
|
27
|
+
},
|
|
28
|
+
"1004809|widdershins>openapi-sampler>json-pointer": {
|
|
29
|
+
"decision": "ignore",
|
|
30
|
+
"madeAt": 1636956486789,
|
|
31
|
+
"expiresAt": 1639548471465
|
|
32
|
+
},
|
|
33
|
+
"1004812|widdershins>swagger2openapi>better-ajv-errors>jsonpointer": {
|
|
34
|
+
"decision": "ignore",
|
|
35
|
+
"madeAt": 1636956491233,
|
|
36
|
+
"expiresAt": 1639548471465
|
|
15
37
|
},
|
|
16
|
-
"
|
|
17
|
-
"decision": "
|
|
18
|
-
"madeAt":
|
|
38
|
+
"1004812|widdershins>swagger2openapi>oas-validator>better-ajv-errors>jsonpointer": {
|
|
39
|
+
"decision": "ignore",
|
|
40
|
+
"madeAt": 1636956491233,
|
|
41
|
+
"expiresAt": 1639548471465
|
|
42
|
+
},
|
|
43
|
+
"1004854|widdershins>openapi-sampler>json-pointer": {
|
|
44
|
+
"decision": "ignore",
|
|
45
|
+
"madeAt": 1637925238134,
|
|
46
|
+
"expiresAt": 1640517233443
|
|
47
|
+
},
|
|
48
|
+
"1004869|widdershins>swagger2openapi>better-ajv-errors>jsonpointer": {
|
|
49
|
+
"decision": "ignore",
|
|
50
|
+
"madeAt": 1637925239670,
|
|
51
|
+
"expiresAt": 1640517233443
|
|
52
|
+
},
|
|
53
|
+
"1004869|widdershins>swagger2openapi>oas-validator>better-ajv-errors>jsonpointer": {
|
|
54
|
+
"decision": "ignore",
|
|
55
|
+
"madeAt": 1637925239670,
|
|
56
|
+
"expiresAt": 1640517233443
|
|
57
|
+
},
|
|
58
|
+
"1004946|widdershins>yargs>string-width>strip-ansi>ansi-regex": {
|
|
59
|
+
"decision": "ignore",
|
|
60
|
+
"madeAt": 1637925241156,
|
|
61
|
+
"expiresAt": 1640517233443
|
|
19
62
|
},
|
|
20
|
-
"
|
|
63
|
+
"1004946|widdershins>yargs>cliui>string-width>strip-ansi>ansi-regex": {
|
|
21
64
|
"decision": "ignore",
|
|
22
|
-
"madeAt":
|
|
23
|
-
"expiresAt":
|
|
65
|
+
"madeAt": 1637925241156,
|
|
66
|
+
"expiresAt": 1640517233443
|
|
24
67
|
},
|
|
25
|
-
"
|
|
68
|
+
"1005383|shins>sanitize-html": {
|
|
26
69
|
"decision": "ignore",
|
|
27
|
-
"madeAt":
|
|
28
|
-
"expiresAt":
|
|
70
|
+
"madeAt": 1637925243300,
|
|
71
|
+
"expiresAt": 1640517233443
|
|
29
72
|
},
|
|
30
|
-
"
|
|
73
|
+
"1005384|shins>sanitize-html": {
|
|
31
74
|
"decision": "ignore",
|
|
32
|
-
"madeAt":
|
|
33
|
-
"expiresAt":
|
|
75
|
+
"madeAt": 1637925243300,
|
|
76
|
+
"expiresAt": 1640517233443
|
|
34
77
|
},
|
|
35
|
-
"
|
|
78
|
+
"1005534|widdershins>yargs>yargs-parser": {
|
|
36
79
|
"decision": "ignore",
|
|
37
|
-
"madeAt":
|
|
38
|
-
"expiresAt":
|
|
80
|
+
"madeAt": 1637925244682,
|
|
81
|
+
"expiresAt": 1640517233443
|
|
39
82
|
}
|
|
40
83
|
},
|
|
41
84
|
"rules": {},
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mojaloop/central-services-shared",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "15.2.0",
|
|
4
4
|
"description": "Shared code for mojaloop central services",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "src/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"test": "npm run test:unit | npx faucet",
|
|
9
8
|
"pretest": "standard",
|
|
10
9
|
"standard": "standard",
|
|
11
10
|
"standard:fix": "standard --fix",
|
|
12
11
|
"lint": "npm run standard",
|
|
13
12
|
"lint:fix": "npm run standard:fix",
|
|
14
|
-
"test
|
|
15
|
-
"test:
|
|
13
|
+
"test": "npm run test:unit",
|
|
14
|
+
"test:unit": "tape 'test/unit/**/*.test.js' | tap-spec",
|
|
15
|
+
"test:xunit": "tape 'test/unit/**/*.test.js' | tap-xunit",
|
|
16
16
|
"test:coverage": "nyc --reporter=lcov --reporter=text-summary tapes -- 'test/unit/**/**.test.js'",
|
|
17
17
|
"test:coverage-check": "npm run test:coverage && nyc check-coverage",
|
|
18
18
|
"audit:resolve": "SHELL=sh resolve-audit --production",
|
|
@@ -48,16 +48,16 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@hapi/catbox": "11.1.1",
|
|
50
50
|
"@hapi/catbox-memory": "5.0.1",
|
|
51
|
-
"axios": "0.
|
|
51
|
+
"axios": "0.24.0",
|
|
52
52
|
"clone": "2.1.2",
|
|
53
53
|
"dotenv": "10.0.0",
|
|
54
|
-
"env-var": "7.
|
|
54
|
+
"env-var": "7.1.1",
|
|
55
55
|
"event-stream": "4.0.1",
|
|
56
|
-
"immutable": "
|
|
56
|
+
"immutable": "4.0.0",
|
|
57
57
|
"lodash": "4.17.21",
|
|
58
58
|
"mustache": "4.2.0",
|
|
59
|
-
"openapi-backend": "
|
|
60
|
-
"raw-body": "2.4.
|
|
59
|
+
"openapi-backend": "5.0.1",
|
|
60
|
+
"raw-body": "2.4.2",
|
|
61
61
|
"rc": "1.2.8",
|
|
62
62
|
"shins": "2.6.0",
|
|
63
63
|
"uuid4": "2.0.2",
|
|
@@ -65,38 +65,38 @@
|
|
|
65
65
|
"yaml": "1.10.2"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
|
-
"@hapi/hapi": "20.1
|
|
68
|
+
"@hapi/hapi": "20.2.1",
|
|
69
69
|
"@hapi/joi": "17.1.1",
|
|
70
70
|
"@mojaloop/central-services-error-handling": "11.3.0",
|
|
71
|
-
"@mojaloop/central-services-logger": "10.6.
|
|
71
|
+
"@mojaloop/central-services-logger": "10.6.2",
|
|
72
72
|
"@mojaloop/central-services-metrics": "11.0.0",
|
|
73
73
|
"@mojaloop/event-sdk": "10.7.1",
|
|
74
74
|
"@mojaloop/sdk-standard-components": "10.3.2",
|
|
75
|
-
"ajv": "8.
|
|
76
|
-
"ajv-keywords": "5.
|
|
75
|
+
"ajv": "8.8.2",
|
|
76
|
+
"ajv-keywords": "5.1.0",
|
|
77
77
|
"base64url": "3.0.1",
|
|
78
78
|
"chance": "1.1.8",
|
|
79
|
-
"faucet": "0.0.1",
|
|
80
79
|
"npm-audit-resolver": "2.3.1",
|
|
81
|
-
"npm-check-updates": "
|
|
80
|
+
"npm-check-updates": "12.0.2",
|
|
82
81
|
"nyc": "15.1.0",
|
|
83
82
|
"pre-commit": "1.2.2",
|
|
84
83
|
"proxyquire": "2.1.3",
|
|
85
84
|
"rewire": "5.0.0",
|
|
86
|
-
"sinon": "
|
|
87
|
-
"standard": "16.0.
|
|
88
|
-
"standard-version": "9.3.
|
|
85
|
+
"sinon": "12.0.1",
|
|
86
|
+
"standard": "16.0.4",
|
|
87
|
+
"standard-version": "9.3.2",
|
|
88
|
+
"tap-spec": "^5.0.0",
|
|
89
89
|
"tap-xunit": "2.4.1",
|
|
90
|
-
"tape": "5.3.
|
|
90
|
+
"tape": "5.3.2",
|
|
91
91
|
"tapes": "4.1.0"
|
|
92
92
|
},
|
|
93
93
|
"peerDependencies": {
|
|
94
94
|
"@mojaloop/central-services-error-handling": "11.3.0",
|
|
95
|
-
"@mojaloop/central-services-logger": "10.6.
|
|
95
|
+
"@mojaloop/central-services-logger": "10.6.2",
|
|
96
96
|
"@mojaloop/central-services-metrics": "11.0.0",
|
|
97
97
|
"@mojaloop/event-sdk": "10.7.1",
|
|
98
|
-
"ajv": "8.
|
|
99
|
-
"ajv-keywords": "5.
|
|
98
|
+
"ajv": "8.8.2",
|
|
99
|
+
"ajv-keywords": "5.1.0"
|
|
100
100
|
},
|
|
101
101
|
"peerDependenciesMeta": {
|
|
102
102
|
"@mojaloop/central-services-error-handling": {
|
package/src/enums/events.js
CHANGED
|
@@ -60,6 +60,7 @@ const Event = {
|
|
|
60
60
|
Action: {
|
|
61
61
|
ABORT: 'abort',
|
|
62
62
|
ABORT_DUPLICATE: 'abort-duplicate',
|
|
63
|
+
ABORT_VALIDATION: 'abort-validation',
|
|
63
64
|
ACCEPT: 'accept',
|
|
64
65
|
BULK_ABORT: 'bulk-abort',
|
|
65
66
|
BULK_COMMIT: 'bulk-commit',
|
|
@@ -92,6 +93,10 @@ const Event = {
|
|
|
92
93
|
RECORD_FUNDS_OUT_PREPARE_RESERVE: 'recordFundsOutPrepareReserve',
|
|
93
94
|
REJECT: 'reject',
|
|
94
95
|
RESOLVE: 'resolve',
|
|
96
|
+
|
|
97
|
+
// The Transfer was marked as RESERVED by the payee DFSP
|
|
98
|
+
// and was then aborted by the switch
|
|
99
|
+
RESERVED_ABORTED: 'reserved-aborted',
|
|
95
100
|
REQUEST: 'request',
|
|
96
101
|
RESERVE: 'reserve',
|
|
97
102
|
SETTLEMENT_WINDOW: 'settlement-window',
|
package/src/enums/kafka.js
CHANGED
|
@@ -90,6 +90,10 @@ const TopicMap = {
|
|
|
90
90
|
functionality: transferEventType.NOTIFICATION,
|
|
91
91
|
action: transferEventAction.EVENT
|
|
92
92
|
},
|
|
93
|
+
'abort-validation': {
|
|
94
|
+
functionality: transferEventType.NOTIFICATION,
|
|
95
|
+
action: transferEventAction.EVENT
|
|
96
|
+
},
|
|
93
97
|
'bulk-abort': {
|
|
94
98
|
functionality: transferEventType.NOTIFICATION,
|
|
95
99
|
action: transferEventAction.EVENT
|
|
@@ -203,6 +207,10 @@ const TopicMap = {
|
|
|
203
207
|
abort: {
|
|
204
208
|
functionality: transferEventType.TRANSFER,
|
|
205
209
|
action: transferEventAction.POSITION
|
|
210
|
+
},
|
|
211
|
+
'abort-validation': {
|
|
212
|
+
functionality: transferEventType.TRANSFER,
|
|
213
|
+
action: transferEventAction.POSITION
|
|
206
214
|
}
|
|
207
215
|
},
|
|
208
216
|
prepare: {
|
package/src/index.d.ts
CHANGED
|
@@ -260,6 +260,7 @@ declare namespace CentralServicesShared {
|
|
|
260
260
|
enum EventActionEnum {
|
|
261
261
|
ABORT = 'abort',
|
|
262
262
|
ABORT_DUPLICATE = 'abort-duplicate',
|
|
263
|
+
ABORT_VALIDATION = 'abort-validation',
|
|
263
264
|
ACCEPT = 'accept',
|
|
264
265
|
BULK_ABORT = 'bulk-abort',
|
|
265
266
|
BULK_COMMIT = 'bulk-commit',
|
|
@@ -294,6 +295,7 @@ declare namespace CentralServicesShared {
|
|
|
294
295
|
RESOLVE = 'resolve',
|
|
295
296
|
REQUEST = 'request',
|
|
296
297
|
RESERVE = 'reserve',
|
|
298
|
+
RESERVED_ABORTED = 'reserved-aborted',
|
|
297
299
|
SETTLEMENT_WINDOW = 'settlement-window',
|
|
298
300
|
TIMEOUT_RECEIVED = 'timeout-received',
|
|
299
301
|
TIMEOUT_RESERVED = 'timeout-reserved',
|
|
@@ -317,6 +319,7 @@ declare namespace CentralServicesShared {
|
|
|
317
319
|
Action: {
|
|
318
320
|
ABORT: EventActionEnum.ABORT;
|
|
319
321
|
ABORT_DUPLICATE: EventActionEnum.ABORT_DUPLICATE;
|
|
322
|
+
ABORT_VALIDATION: EventActionEnum.ABORT_VALIDATION;
|
|
320
323
|
ACCEPT: EventActionEnum.ACCEPT;
|
|
321
324
|
BULK_ABORT: EventActionEnum.BULK_ABORT;
|
|
322
325
|
BULK_COMMIT: EventActionEnum.BULK_COMMIT;
|
|
@@ -351,6 +354,7 @@ declare namespace CentralServicesShared {
|
|
|
351
354
|
RESOLVE: EventActionEnum.RESOLVE;
|
|
352
355
|
REQUEST: EventActionEnum.REQUEST;
|
|
353
356
|
RESERVE: EventActionEnum.RESERVE;
|
|
357
|
+
RESERVED_ABORTED: EventActionEnum.RESERVED_ABORTED;
|
|
354
358
|
SETTLEMENT_WINDOW: EventActionEnum.SETTLEMENT_WINDOW;
|
|
355
359
|
TIMEOUT_RECEIVED: EventActionEnum.TIMEOUT_RECEIVED;
|
|
356
360
|
TIMEOUT_RESERVED: EventActionEnum.TIMEOUT_RESERVED;
|
|
@@ -399,8 +403,13 @@ declare namespace CentralServicesShared {
|
|
|
399
403
|
getEndpointAndRender(switchUrl: string, fsp: string, endpointType: FspEndpointTypesEnum, path: string, options?: any): Promise<string>
|
|
400
404
|
}
|
|
401
405
|
|
|
406
|
+
interface ProtocolVersionsType {
|
|
407
|
+
content: string,
|
|
408
|
+
accept: string
|
|
409
|
+
}
|
|
410
|
+
|
|
402
411
|
interface Request {
|
|
403
|
-
sendRequest(url: string, headers: HapiUtil.Dictionary<string>, source: string, destination: string, method?: RestMethodsEnum, payload?: any, responseType?: string, span?: any, jwsSigner?: any): Promise<any>
|
|
412
|
+
sendRequest(url: string, headers: HapiUtil.Dictionary<string>, source: string, destination: string, method?: RestMethodsEnum, payload?: any, responseType?: string, span?: any, jwsSigner?: any, protocolVersions?: ProtocolVersionsType): Promise<any>
|
|
404
413
|
}
|
|
405
414
|
|
|
406
415
|
interface Kafka {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// accuracy of this statement has not been thoroughly tested.
|
|
7
7
|
|
|
8
8
|
const { Factory: { createFSPIOPError }, Enums } = require('@mojaloop/central-services-error-handling')
|
|
9
|
-
const { parseAcceptHeader, parseContentTypeHeader, protocolVersions,
|
|
9
|
+
const { parseAcceptHeader, parseContentTypeHeader, protocolVersions, convertSupportedVersionToExtensionList } = require('../../headerValidation')
|
|
10
10
|
|
|
11
11
|
// Some defaults
|
|
12
12
|
|
|
@@ -49,7 +49,8 @@ const plugin = {
|
|
|
49
49
|
name: 'fspiop-api-protocol-version-header-validator',
|
|
50
50
|
register: function (server, /* options: */ {
|
|
51
51
|
resources = defaultProtocolResources,
|
|
52
|
-
|
|
52
|
+
supportedProtocolContentVersions = defaultProtocolVersions,
|
|
53
|
+
supportedProtocolAcceptVersions = defaultProtocolVersions
|
|
53
54
|
}) {
|
|
54
55
|
server.ext('onPostAuth', (request, h) => {
|
|
55
56
|
// First, extract the resource type from the path
|
|
@@ -73,13 +74,14 @@ const plugin = {
|
|
|
73
74
|
errorMessages.INVALID_ACCEPT_HEADER
|
|
74
75
|
)
|
|
75
76
|
}
|
|
76
|
-
if (!
|
|
77
|
+
if (!supportedProtocolAcceptVersions.some(supportedVer => accept.versions.has(supportedVer))) {
|
|
78
|
+
const supportedVersionExtensionListMap = convertSupportedVersionToExtensionList(supportedProtocolAcceptVersions)
|
|
77
79
|
throw createFSPIOPError(
|
|
78
80
|
Enums.FSPIOPErrorCodes.UNACCEPTABLE_VERSION,
|
|
79
81
|
errorMessages.REQUESTED_VERSION_NOT_SUPPORTED,
|
|
80
82
|
null,
|
|
81
83
|
null,
|
|
82
|
-
|
|
84
|
+
supportedVersionExtensionListMap
|
|
83
85
|
)
|
|
84
86
|
}
|
|
85
87
|
}
|
|
@@ -95,13 +97,14 @@ const plugin = {
|
|
|
95
97
|
errorMessages.INVALID_CONTENT_TYPE_HEADER
|
|
96
98
|
)
|
|
97
99
|
}
|
|
98
|
-
if (!
|
|
100
|
+
if (!supportedProtocolContentVersions.includes(contentType.version)) {
|
|
101
|
+
const supportedVersionExtensionListMap = convertSupportedVersionToExtensionList(supportedProtocolContentVersions)
|
|
99
102
|
throw createFSPIOPError(
|
|
100
103
|
Enums.FSPIOPErrorCodes.UNACCEPTABLE_VERSION,
|
|
101
104
|
errorMessages.SUPPLIED_VERSION_NOT_SUPPORTED,
|
|
102
105
|
null,
|
|
103
106
|
null,
|
|
104
|
-
|
|
107
|
+
supportedVersionExtensionListMap
|
|
105
108
|
)
|
|
106
109
|
}
|
|
107
110
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const assert = require('assert').strict
|
|
4
|
+
const _ = require('lodash')
|
|
4
5
|
|
|
5
6
|
const protocolVersions = {
|
|
6
|
-
anyVersion: Symbol('Any
|
|
7
|
+
anyVersion: Symbol('Any'),
|
|
7
8
|
ONE: ['1', '1.0', '1.1']
|
|
8
9
|
}
|
|
9
10
|
|
|
@@ -20,6 +21,9 @@ const generateContentTypeRegex = resource =>
|
|
|
20
21
|
const generateAcceptRegex = resource =>
|
|
21
22
|
new RegExp(`^${generateSingleAcceptRegexStr(resource)}(,${generateSingleAcceptRegexStr(resource)})*$`)
|
|
22
23
|
|
|
24
|
+
const generateSingleAcceptRegex = resource =>
|
|
25
|
+
new RegExp(generateSingleAcceptRegexStr(resource))
|
|
26
|
+
|
|
23
27
|
const generateSingleAcceptRegexStr = resource =>
|
|
24
28
|
`application/vnd\\.interoperability\\.${resource}\\+json(\\s{0,1};\\s{0,1}version=\\d+(\\.\\d+)?)?`
|
|
25
29
|
|
|
@@ -55,7 +59,8 @@ const parseAcceptHeader = (resource, header) => {
|
|
|
55
59
|
// The header contains a comma-delimited set of versions, extract these
|
|
56
60
|
const versions = new Set(header
|
|
57
61
|
.split(',')
|
|
58
|
-
|
|
62
|
+
// @ts-ignore
|
|
63
|
+
.map(verStr => verStr.match(generateSingleAcceptRegex(resource))[1])
|
|
59
64
|
.map(match => match === undefined ? protocolVersions.anyVersion : match.split('=')[1])
|
|
60
65
|
)
|
|
61
66
|
|
|
@@ -65,11 +70,31 @@ const parseAcceptHeader = (resource, header) => {
|
|
|
65
70
|
}
|
|
66
71
|
}
|
|
67
72
|
|
|
73
|
+
const convertSupportedVersionToExtensionList = (supportedVersions) => {
|
|
74
|
+
const supportedVersionsExtensionListMap = []
|
|
75
|
+
for (const version of supportedVersions) {
|
|
76
|
+
const versionList = version.toString().split('.').filter(num => num !== '')
|
|
77
|
+
if (versionList != null && versionList.length === 2) {
|
|
78
|
+
const versionMap = {}
|
|
79
|
+
versionMap.key = versionList[0]
|
|
80
|
+
versionMap.value = versionList[1]
|
|
81
|
+
supportedVersionsExtensionListMap.push(versionMap)
|
|
82
|
+
} else if (versionList != null && versionList.length === 1 && version !== protocolVersions.anyVersion) {
|
|
83
|
+
const versionMap = {}
|
|
84
|
+
versionMap.key = versionList[0]
|
|
85
|
+
versionMap.value = '0'
|
|
86
|
+
supportedVersionsExtensionListMap.push(versionMap)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return _.uniqWith(supportedVersionsExtensionListMap, _.isEqual)
|
|
90
|
+
}
|
|
91
|
+
|
|
68
92
|
module.exports = {
|
|
69
93
|
protocolVersions,
|
|
70
94
|
protocolVersionsMap,
|
|
71
95
|
generateAcceptRegex,
|
|
72
96
|
generateContentTypeRegex,
|
|
73
97
|
parseAcceptHeader,
|
|
74
|
-
parseContentTypeHeader
|
|
98
|
+
parseContentTypeHeader,
|
|
99
|
+
convertSupportedVersionToExtensionList
|
|
75
100
|
}
|
|
@@ -30,12 +30,36 @@ const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
|
|
30
30
|
|
|
31
31
|
const resourceVersions = require('../helpers').resourceVersions
|
|
32
32
|
|
|
33
|
-
const regexForContentAndAcceptHeaders = /(application\/vnd\.interoperability\.)(\w*)+(\+json\s{0,1};\s{0,1}version=)(.*)/
|
|
34
|
-
|
|
35
33
|
/**
|
|
36
34
|
* @module src/headers/transformer
|
|
37
35
|
*/
|
|
38
36
|
|
|
37
|
+
const regexForContentAndAcceptHeaders = /(application\/vnd\.interoperability\.)(\w*)+(\+json\s{0,1};\s{0,1}version=)(.*)/
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @function getResourceInfoFromHeader
|
|
41
|
+
*
|
|
42
|
+
* @description This will parse either a FSPIOP Content-Type or Accept header and return an object containing the resourceType and applicable version
|
|
43
|
+
*
|
|
44
|
+
* @typedef ResourceInfo
|
|
45
|
+
* @type {object}
|
|
46
|
+
* @property {string} resourceType - resource parsed from the headerValue.
|
|
47
|
+
* @property {string} version - version parsed from the headerValue.
|
|
48
|
+
*
|
|
49
|
+
* @param {string} headerValue - the http header from the request, thus must be either an FSPIOP Content-Type or Accept header.
|
|
50
|
+
*
|
|
51
|
+
* @returns {ResourceInfo} Returns resourceInfo object. If the headerValue was not parsed correctly, an empty object {} will be returned.
|
|
52
|
+
*/
|
|
53
|
+
const getResourceInfoFromHeader = (headerValue) => {
|
|
54
|
+
const result = {}
|
|
55
|
+
const regex = regexForContentAndAcceptHeaders.exec(headerValue)
|
|
56
|
+
if (regex) {
|
|
57
|
+
if (regex[2]) result.resourceType = regex[2]
|
|
58
|
+
if (regex[4]) result.version = regex[4]
|
|
59
|
+
}
|
|
60
|
+
return result
|
|
61
|
+
}
|
|
62
|
+
|
|
39
63
|
/**
|
|
40
64
|
* @function transformHeaders
|
|
41
65
|
*
|
|
@@ -45,7 +69,31 @@ const regexForContentAndAcceptHeaders = /(application\/vnd\.interoperability\.)(
|
|
|
45
69
|
*
|
|
46
70
|
* see https://nodejs.org/dist/latest-v10.x/docs/api/http.html#http_message_headers
|
|
47
71
|
*
|
|
72
|
+
* @typedef TransformProtocolVersions
|
|
73
|
+
* @type {object}
|
|
74
|
+
* @property {string} content - protocol version to be used in the ContentType HTTP Header.
|
|
75
|
+
* @property {string} accept - protocol version to be used in the Accept HTTP Header.
|
|
76
|
+
*
|
|
77
|
+
* @typedef TransformHeadersConfig
|
|
78
|
+
* @type {object}
|
|
79
|
+
* @property {string} contentType - HTTP method such as "POST", "PUT", etc.
|
|
80
|
+
* @property {string} accept - Source FSP Identifier.
|
|
81
|
+
* @property {string} destinationFsp - Destination FSP Identifier.
|
|
82
|
+
* @property {TransformProtocolVersions} protocolVersions - Config for Protocol versions to be used.
|
|
83
|
+
*
|
|
84
|
+
* Config supports the following parameters:
|
|
85
|
+
* config: {
|
|
86
|
+
* httpMethod: string,
|
|
87
|
+
* sourceFsp: string,
|
|
88
|
+
* destinationFsp: string,
|
|
89
|
+
* protocolVersions: {
|
|
90
|
+
* content: string,
|
|
91
|
+
* accept: string
|
|
92
|
+
* }
|
|
93
|
+
* }
|
|
94
|
+
*
|
|
48
95
|
* @param {object} headers - the http header from the request
|
|
96
|
+
* @param {TransformHeadersConfig} headers - the http header from the request
|
|
49
97
|
*
|
|
50
98
|
* @returns {object} Returns the normalized headers
|
|
51
99
|
*/
|
|
@@ -62,8 +110,15 @@ const transformHeaders = (headers, config) => {
|
|
|
62
110
|
const normalizedHeaders = {}
|
|
63
111
|
|
|
64
112
|
// resource type for content-type and accept headers
|
|
65
|
-
const getResourceFromHeader = (headerValue) => regexForContentAndAcceptHeaders.exec(headerValue)[2]
|
|
66
113
|
let resourceType
|
|
114
|
+
let acceptVersion
|
|
115
|
+
let contentVersion
|
|
116
|
+
|
|
117
|
+
// Determine the acceptVersion using the injected config
|
|
118
|
+
if (config && config.protocolVersions && config.protocolVersions.accept) acceptVersion = config.protocolVersions.accept
|
|
119
|
+
|
|
120
|
+
// Determine the contentVersion using the injected config
|
|
121
|
+
if (config && config.protocolVersions && config.protocolVersions.content) contentVersion = config.protocolVersions.content
|
|
67
122
|
|
|
68
123
|
// check to see if FSPIOP-Destination header has been left out of the initial request. If so then add it.
|
|
69
124
|
if (!normalizedKeys[ENUM.Headers.FSPIOP.DESTINATION]) {
|
|
@@ -127,16 +182,20 @@ const transformHeaders = (headers, config) => {
|
|
|
127
182
|
normalizedHeaders[headerKey] = headerValue
|
|
128
183
|
break
|
|
129
184
|
}
|
|
130
|
-
if (!resourceType) resourceType =
|
|
131
|
-
|
|
185
|
+
if (!resourceType) resourceType = getResourceInfoFromHeader(headers[headerKey]).resourceType
|
|
186
|
+
// Fall back to using the legacy approach to determine the resourceVersion
|
|
187
|
+
if (resourceType && !acceptVersion) acceptVersion = resourceVersions[resourceType].acceptVersion
|
|
188
|
+
normalizedHeaders[headerKey] = `application/vnd.interoperability.${resourceType}+json;version=${acceptVersion}`
|
|
132
189
|
break
|
|
133
190
|
case (ENUM.Headers.GENERAL.CONTENT_TYPE.value):
|
|
134
191
|
if (!ENUM.Headers.FSPIOP.SWITCH.regex.test(config.sourceFsp)) {
|
|
135
192
|
normalizedHeaders[headerKey] = headerValue
|
|
136
193
|
break
|
|
137
194
|
}
|
|
138
|
-
if (!resourceType) resourceType =
|
|
139
|
-
|
|
195
|
+
if (!resourceType) resourceType = getResourceInfoFromHeader(headers[headerKey]).resourceType
|
|
196
|
+
// Fall back to using the legacy approach to determine the resourceVersion
|
|
197
|
+
if (resourceType && !contentVersion) contentVersion = resourceVersions[resourceType].contentVersion
|
|
198
|
+
normalizedHeaders[headerKey] = `application/vnd.interoperability.${resourceType}+json;version=${contentVersion}`
|
|
140
199
|
break
|
|
141
200
|
default:
|
|
142
201
|
normalizedHeaders[headerKey] = headerValue
|
|
@@ -157,5 +216,6 @@ const transformHeaders = (headers, config) => {
|
|
|
157
216
|
}
|
|
158
217
|
|
|
159
218
|
module.exports = {
|
|
219
|
+
getResourceInfoFromHeader,
|
|
160
220
|
transformHeaders
|
|
161
221
|
}
|
package/src/util/request.js
CHANGED
|
@@ -43,20 +43,26 @@ delete request.defaults.headers.common.Accept
|
|
|
43
43
|
*
|
|
44
44
|
* @description sends a request to url
|
|
45
45
|
*
|
|
46
|
+
* @typedef SendRequestProtocolVersions
|
|
47
|
+
* @type {object}
|
|
48
|
+
* @property {string} content - protocol version to be used in the ContentType HTTP Header.
|
|
49
|
+
* @property {string} accept - protocol version to be used in the Accept HTTP Header.
|
|
50
|
+
*
|
|
46
51
|
* @param {string} url the endpoint for the service you require
|
|
47
52
|
* @param {object} headers the http headers
|
|
48
53
|
* @param {string} method http method being requested i.e. GET, POST, PUT
|
|
49
54
|
* @param {string} source id for which callback is being sent from
|
|
50
55
|
* @param {string} destination id for which callback is being sent
|
|
51
|
-
* @param {object} payload the body of the request being sent
|
|
56
|
+
* @param {object | undefined} payload the body of the request being sent
|
|
52
57
|
* @param {string} responseType the type of the response object
|
|
53
|
-
* @param {object} span a span for event logging if this request is within a span
|
|
54
|
-
* @param {object} jwsSigner the jws signer for signing the requests
|
|
58
|
+
* @param {object | undefined} span a span for event logging if this request is within a span
|
|
59
|
+
* @param {object | undefined} jwsSigner the jws signer for signing the requests
|
|
60
|
+
* @param {SendRequestProtocolVersions | undefined} protocolVersions the config for Protocol versions to be used
|
|
55
61
|
*
|
|
56
|
-
*@return {
|
|
62
|
+
*@return {Promise<any>} The response for the request being sent or error object with response included
|
|
57
63
|
*/
|
|
58
64
|
|
|
59
|
-
const sendRequest = async (url, headers, source, destination, method = enums.Http.RestMethods.GET, payload = undefined, responseType = enums.Http.ResponseTypes.JSON, span = undefined, jwsSigner = undefined) => {
|
|
65
|
+
const sendRequest = async (url, headers, source, destination, method = enums.Http.RestMethods.GET, payload = undefined, responseType = enums.Http.ResponseTypes.JSON, span = undefined, jwsSigner = undefined, protocolVersions = undefined) => {
|
|
60
66
|
const histTimerEnd = !!Metrics.isInitiated() && Metrics.getHistogram(
|
|
61
67
|
'sendRequest',
|
|
62
68
|
`sending ${method} request to: ${url} from: ${source} to: ${destination}`,
|
|
@@ -75,7 +81,8 @@ const sendRequest = async (url, headers, source, destination, method = enums.Htt
|
|
|
75
81
|
const transformedHeaders = Headers.transformHeaders(headers, {
|
|
76
82
|
httpMethod: method,
|
|
77
83
|
sourceFsp: source,
|
|
78
|
-
destinationFsp: destination
|
|
84
|
+
destinationFsp: destination,
|
|
85
|
+
protocolVersions
|
|
79
86
|
})
|
|
80
87
|
requestOptions = {
|
|
81
88
|
url,
|
|
@@ -31,6 +31,7 @@ const Sinon = require('sinon')
|
|
|
31
31
|
const Transformer = require('../../../src/util').Headers
|
|
32
32
|
const Enum = require('../../../src/enums')
|
|
33
33
|
const Util = require('../../../src/util')
|
|
34
|
+
const Helper = require('../../util/helper')
|
|
34
35
|
|
|
35
36
|
const headerConfigExample = {
|
|
36
37
|
httpMethod: 'PUT',
|
|
@@ -67,6 +68,30 @@ Test('Transfer Transformer tests', TransformerTest => {
|
|
|
67
68
|
t.end()
|
|
68
69
|
})
|
|
69
70
|
|
|
71
|
+
TransformerTest.test('Transformer.getResourceInfoFromHeaderTest() should', getResourceInfoFromHeaderTest => {
|
|
72
|
+
getResourceInfoFromHeaderTest.test('parse FSPIOP Content-Type example correctly', async test => {
|
|
73
|
+
const result = Transformer.getResourceInfoFromHeader(headerDataInputExample['Content-Type'])
|
|
74
|
+
test.equal(headerDataInputExample['Content-Type'], Helper.generateProtocolHeader(result.resourceType, result.version))
|
|
75
|
+
test.end()
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
getResourceInfoFromHeaderTest.test('return an empty result with standard application/json', async test => {
|
|
79
|
+
const contentType = 'application/json'
|
|
80
|
+
const result = Transformer.getResourceInfoFromHeader(contentType)
|
|
81
|
+
test.same(result, {})
|
|
82
|
+
test.end()
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
getResourceInfoFromHeaderTest.test('return an empty result with incorrect FSPIOP Content-Type input', async test => {
|
|
86
|
+
const contentType = 'application/vnd.interoperability.transfers+json'
|
|
87
|
+
const result = Transformer.getResourceInfoFromHeader(contentType)
|
|
88
|
+
test.same(result, {})
|
|
89
|
+
test.end()
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
getResourceInfoFromHeaderTest.end()
|
|
93
|
+
})
|
|
94
|
+
|
|
70
95
|
TransformerTest.test('Transformer.transformHeaders() should', transformHeadersTest => {
|
|
71
96
|
transformHeadersTest.test('Remove all unnecessary fields from Header', async test => {
|
|
72
97
|
const headerData = Util.clone(headerDataInputExample)
|
|
@@ -78,6 +103,58 @@ Test('Transfer Transformer tests', TransformerTest => {
|
|
|
78
103
|
test.end()
|
|
79
104
|
})
|
|
80
105
|
|
|
106
|
+
transformHeadersTest.test('Set ContentType && Accept versions via RESOURCE_VERSIONS env variable', async test => {
|
|
107
|
+
const RESOURCE_VERSIONS_BACKUP = process.env.RESOURCE_VERSIONS
|
|
108
|
+
process.env.RESOURCE_VERSIONS = 'transfers=1.1,quotes=1.0'
|
|
109
|
+
|
|
110
|
+
const headerConfig = {
|
|
111
|
+
httpMethod: 'PUT',
|
|
112
|
+
sourceFsp: 'switch',
|
|
113
|
+
destinationFsp: 'FSPDest'
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const headerData = Util.clone(headerDataInputExample)
|
|
117
|
+
headerData.Accept = Helper.generateProtocolHeader('transfers', '1')
|
|
118
|
+
|
|
119
|
+
const transformedHeaderData = Transformer.transformHeaders(headerData, headerConfig)
|
|
120
|
+
|
|
121
|
+
test.deepEqual(headerData['Content-Type'], transformedHeaderData['Content-Type'])
|
|
122
|
+
test.deepEqual(headerData.Accept, transformedHeaderData.Accept)
|
|
123
|
+
test.end()
|
|
124
|
+
process.env.RESOURCE_VERSIONS = RESOURCE_VERSIONS_BACKUP
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
transformHeadersTest.test('Set ContentType && Accept versions via config', async test => {
|
|
128
|
+
const RESOURCE_VERSIONS_BACKUP = process.env.RESOURCE_VERSIONS
|
|
129
|
+
// we keep this here to make sure it does not override the injected protocolVersions config
|
|
130
|
+
process.env.RESOURCE_VERSIONS = 'transfers=1.0,quotes=1.0'
|
|
131
|
+
|
|
132
|
+
const headerConfig = {
|
|
133
|
+
httpMethod: 'PUT',
|
|
134
|
+
sourceFsp: 'switch',
|
|
135
|
+
destinationFsp: 'FSPDest',
|
|
136
|
+
protocolVersions: {
|
|
137
|
+
content: '1.1',
|
|
138
|
+
accept: '1'
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const headerData = Util.clone(headerDataInputExample)
|
|
143
|
+
headerData.Accept = Helper.generateProtocolHeader('transfers', '1.1')
|
|
144
|
+
|
|
145
|
+
const resourceInfoFromHeader = Transformer.getResourceInfoFromHeader(headerData['Content-Type'])
|
|
146
|
+
|
|
147
|
+
const transformedHeaderData = Transformer.transformHeaders(headerData, headerConfig)
|
|
148
|
+
const resourceInfoFromTransformedHeader = Transformer.getResourceInfoFromHeader(transformedHeaderData['Content-Type'])
|
|
149
|
+
|
|
150
|
+
test.equal(resourceInfoFromHeader.resourceType, resourceInfoFromTransformedHeader.resourceType)
|
|
151
|
+
test.equal(resourceInfoFromHeader.version, '1.0')
|
|
152
|
+
test.equal(resourceInfoFromTransformedHeader.version, '1.1')
|
|
153
|
+
test.equal(transformedHeaderData.Accept, Helper.generateProtocolHeader('transfers', headerConfig.protocolVersions.accept))
|
|
154
|
+
test.end()
|
|
155
|
+
process.env.RESOURCE_VERSIONS = RESOURCE_VERSIONS_BACKUP
|
|
156
|
+
})
|
|
157
|
+
|
|
81
158
|
transformHeadersTest.test('Translate Date field into correct format for String value', async test => {
|
|
82
159
|
const key = 'Date'
|
|
83
160
|
const val = '2018-09-13T13:52:15.221Z'
|
|
@@ -9,7 +9,10 @@ const fs = require('fs')
|
|
|
9
9
|
const path = require('path')
|
|
10
10
|
const {
|
|
11
11
|
generateAcceptRegex,
|
|
12
|
-
generateContentTypeRegex
|
|
12
|
+
generateContentTypeRegex,
|
|
13
|
+
convertSupportedVersionToExtensionList,
|
|
14
|
+
parseAcceptHeader,
|
|
15
|
+
protocolVersions
|
|
13
16
|
} = require('../../../../src/util/headerValidation/index')
|
|
14
17
|
const {
|
|
15
18
|
generateAcceptHeader,
|
|
@@ -124,3 +127,91 @@ test('Run positive content-type header fuzz', t => {
|
|
|
124
127
|
}
|
|
125
128
|
t.end()
|
|
126
129
|
})
|
|
130
|
+
|
|
131
|
+
test('Run test-case 1 for convertSupportedVersionToExtensionList', t => {
|
|
132
|
+
const supportedVersionList = [
|
|
133
|
+
'1',
|
|
134
|
+
'1.0',
|
|
135
|
+
'1.1'
|
|
136
|
+
]
|
|
137
|
+
const expectedResult = [
|
|
138
|
+
{ key: '1', value: '0' },
|
|
139
|
+
{ key: '1', value: '1' }
|
|
140
|
+
]
|
|
141
|
+
const result = convertSupportedVersionToExtensionList(supportedVersionList)
|
|
142
|
+
t.deepEqual(result, expectedResult)
|
|
143
|
+
t.end()
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
test('Run test-case 2 for convertSupportedVersionToExtensionList', t => {
|
|
147
|
+
const supportedVersionList = [
|
|
148
|
+
'1.',
|
|
149
|
+
'1.0',
|
|
150
|
+
'1.1'
|
|
151
|
+
]
|
|
152
|
+
const expectedResult = [
|
|
153
|
+
{ key: '1', value: '0' },
|
|
154
|
+
{ key: '1', value: '1' }
|
|
155
|
+
]
|
|
156
|
+
const result = convertSupportedVersionToExtensionList(supportedVersionList)
|
|
157
|
+
t.deepEqual(result, expectedResult)
|
|
158
|
+
t.end()
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
test('Run test-case 3 for convertSupportedVersionToExtensionList', t => {
|
|
162
|
+
const supportedVersionList = []
|
|
163
|
+
const expectedResult = []
|
|
164
|
+
const result = convertSupportedVersionToExtensionList(supportedVersionList)
|
|
165
|
+
t.deepEqual(result, expectedResult)
|
|
166
|
+
t.end()
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
test('Run test-case 4 for convertSupportedVersionToExtensionList', t => {
|
|
170
|
+
const supportedVersionList = [
|
|
171
|
+
2,
|
|
172
|
+
2.0,
|
|
173
|
+
3.1,
|
|
174
|
+
'1.0'
|
|
175
|
+
]
|
|
176
|
+
const expectedResult = [
|
|
177
|
+
{ key: '2', value: '0' },
|
|
178
|
+
{ key: '3', value: '1' },
|
|
179
|
+
{ key: '1', value: '0' }
|
|
180
|
+
]
|
|
181
|
+
const result = convertSupportedVersionToExtensionList(supportedVersionList)
|
|
182
|
+
t.deepEqual(result, expectedResult)
|
|
183
|
+
t.end()
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
test('Run test-case 4 for convertSupportedVersionToExtensionList', t => {
|
|
187
|
+
const supportedVersionList = [
|
|
188
|
+
2,
|
|
189
|
+
2.0,
|
|
190
|
+
3.1,
|
|
191
|
+
'1.0',
|
|
192
|
+
protocolVersions.anyVersion
|
|
193
|
+
]
|
|
194
|
+
const expectedResult = [
|
|
195
|
+
{ key: '2', value: '0' },
|
|
196
|
+
{ key: '3', value: '1' },
|
|
197
|
+
{ key: '1', value: '0' }
|
|
198
|
+
]
|
|
199
|
+
const result = convertSupportedVersionToExtensionList(supportedVersionList)
|
|
200
|
+
t.deepEqual(result, expectedResult)
|
|
201
|
+
t.end()
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
test('Run test-case for parseAcceptHeader', t => {
|
|
205
|
+
const resource = 'participants'
|
|
206
|
+
const acceptHeader = `application/vnd.interoperability.${resource}+json;version=1,application/vnd.interoperability.${resource}+json;version=1.1`
|
|
207
|
+
const expectedResult = {
|
|
208
|
+
valid: true,
|
|
209
|
+
versions: new Set([
|
|
210
|
+
'1',
|
|
211
|
+
'1.1'
|
|
212
|
+
])
|
|
213
|
+
}
|
|
214
|
+
const result = parseAcceptHeader(resource, acceptHeader)
|
|
215
|
+
t.deepEqual(result, expectedResult)
|
|
216
|
+
t.end()
|
|
217
|
+
})
|
|
@@ -112,6 +112,59 @@ Test('ParticipantEndpoint Model Test', modelTest => {
|
|
|
112
112
|
}
|
|
113
113
|
})
|
|
114
114
|
|
|
115
|
+
getEndpointTest.test('handle protocolVersions for config injection', async (test) => {
|
|
116
|
+
const protocolVersions = {
|
|
117
|
+
content: '2.1',
|
|
118
|
+
accept: '2'
|
|
119
|
+
}
|
|
120
|
+
const fsp = 'fsp'
|
|
121
|
+
const requestOptions = {
|
|
122
|
+
url: Mustache.render(Config.ENDPOINT_SOURCE_URL + Enum.EndPoints.FspEndpointTemplates.PARTICIPANT_ENDPOINTS_GET, { fsp }),
|
|
123
|
+
method: 'get'
|
|
124
|
+
}
|
|
125
|
+
const requestFunction = (request) => {
|
|
126
|
+
test.equal(request.headers['content-type'], Helper.generateProtocolHeader('participants', protocolVersions.content))
|
|
127
|
+
test.equal(request.headers.accept, Helper.generateProtocolHeader('participants', protocolVersions.accept))
|
|
128
|
+
return Helper.getEndPointsResponse
|
|
129
|
+
}
|
|
130
|
+
const span = EventSdk.Tracer.createSpan('test-span')
|
|
131
|
+
Model = proxyquire('../../../src/util/request', { axios: requestFunction })
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
const result = await Model.sendRequest(requestOptions.url, Helper.defaultHeaders(Enum.Http.HeaderResources.SWITCH, Enum.Http.HeaderResources.PARTICIPANTS, Enum.Http.HeaderResources.SWITCH), Enum.Http.HeaderResources.SWITCH, Enum.Http.HeaderResources.SWITCH, Enum.Http.RestMethods.GET, undefined, Enum.Http.ResponseTypes.JSON, span, null, protocolVersions)
|
|
135
|
+
test.deepEqual(result, Helper.getEndPointsResponse, 'The results match')
|
|
136
|
+
test.end()
|
|
137
|
+
} catch (err) {
|
|
138
|
+
test.fail('Error thrown', err)
|
|
139
|
+
test.end()
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
getEndpointTest.test('handle protocolVersions without config injection', async (test) => {
|
|
144
|
+
const protocolVersions = null
|
|
145
|
+
const fsp = 'fsp'
|
|
146
|
+
const requestOptions = {
|
|
147
|
+
url: Mustache.render(Config.ENDPOINT_SOURCE_URL + Enum.EndPoints.FspEndpointTemplates.PARTICIPANT_ENDPOINTS_GET, { fsp }),
|
|
148
|
+
method: 'get'
|
|
149
|
+
}
|
|
150
|
+
const requestFunction = (request) => {
|
|
151
|
+
test.equal(request.headers['content-type'], Helper.generateProtocolHeader('participants', '1.0'))
|
|
152
|
+
test.equal(request.headers.accept, Helper.generateProtocolHeader('participants', '1'))
|
|
153
|
+
return Helper.getEndPointsResponse
|
|
154
|
+
}
|
|
155
|
+
const span = EventSdk.Tracer.createSpan('test-span')
|
|
156
|
+
Model = proxyquire('../../../src/util/request', { axios: requestFunction })
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
const result = await Model.sendRequest(requestOptions.url, Helper.defaultHeaders(Enum.Http.HeaderResources.SWITCH, Enum.Http.HeaderResources.PARTICIPANTS, Enum.Http.HeaderResources.SWITCH), Enum.Http.HeaderResources.SWITCH, Enum.Http.HeaderResources.SWITCH, Enum.Http.RestMethods.GET, undefined, Enum.Http.ResponseTypes.JSON, span, null, protocolVersions)
|
|
160
|
+
test.deepEqual(result, Helper.getEndPointsResponse, 'The results match')
|
|
161
|
+
test.end()
|
|
162
|
+
} catch (err) {
|
|
163
|
+
test.fail('Error thrown', err)
|
|
164
|
+
test.end()
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
|
|
115
168
|
getEndpointTest.test('throw error', async (test) => {
|
|
116
169
|
const fsp = 'fsp1'
|
|
117
170
|
|
package/test/util/helper.js
CHANGED
|
@@ -26,13 +26,15 @@
|
|
|
26
26
|
|
|
27
27
|
const Enums = require('../../src/enums')
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
const generateProtocolHeader = (resource, version) => `application/vnd.interoperability.${resource}+json;version=${version}`
|
|
30
|
+
|
|
31
|
+
const defaultHeaders = (destination, resource, source, version = '1.0') => {
|
|
30
32
|
// TODO: See API section 3.2.1; what should we do about X-Forwarded-For? Also, should we
|
|
31
33
|
// add/append to this field in all 'queueResponse' calls?
|
|
32
34
|
return {
|
|
33
|
-
accept:
|
|
35
|
+
accept: generateProtocolHeader(resource, version),
|
|
34
36
|
'fspiop-destination': destination || '',
|
|
35
|
-
'content-type':
|
|
37
|
+
'content-type': generateProtocolHeader(resource, version),
|
|
36
38
|
date: '2019-05-24 08:52:19',
|
|
37
39
|
'fspiop-source': source
|
|
38
40
|
}
|
|
@@ -74,6 +76,7 @@ const getEndpointAndRenderResponse = {
|
|
|
74
76
|
|
|
75
77
|
module.exports = {
|
|
76
78
|
defaultHeaders,
|
|
79
|
+
generateProtocolHeader,
|
|
77
80
|
getEndPointsResponse,
|
|
78
81
|
getEndpointAndRenderResponse
|
|
79
82
|
}
|