@mojaloop/central-services-shared 18.6.0-snapshot.3 → 18.6.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/.nycrc.yml +1 -2
- package/CHANGELOG.md +7 -0
- package/package.json +4 -1
- package/src/enums/endpoints.js +0 -1
- package/src/enums/http.js +0 -1
- package/src/index.d.ts +5 -17
- package/src/util/endpoints.js +44 -5
- package/src/util/index.js +0 -2
- package/src/util/request.js +0 -3
- package/test/unit/util/endpoints.test.js +72 -1
- package/src/util/proxies.js +0 -182
- package/test/unit/request.test.js +0 -48
package/.nycrc.yml
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
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
|
+
## [18.6.0](https://github.com/mojaloop/central-services-shared/compare/v18.5.2...v18.6.0) (2024-07-05)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* proxy calling ([#389](https://github.com/mojaloop/central-services-shared/issues/389)) ([b7a1615](https://github.com/mojaloop/central-services-shared/commit/b7a1615116214466a240d244376a8aaaa165951d))
|
|
11
|
+
|
|
5
12
|
### [18.5.2](https://github.com/mojaloop/central-services-shared/compare/v18.5.1...v18.5.2) (2024-07-04)
|
|
6
13
|
|
|
7
14
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mojaloop/central-services-shared",
|
|
3
|
-
"version": "18.6.0
|
|
3
|
+
"version": "18.6.0",
|
|
4
4
|
"description": "Shared code for mojaloop central services",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "ModusBox",
|
|
@@ -44,6 +44,8 @@
|
|
|
44
44
|
"test:xunit": "npx tape 'test/unit/**/**.test.js' | tap-xunit > ./test/results/xunit.xml",
|
|
45
45
|
"test:coverage": "npx nyc --reporter=lcov --reporter=text-summary tapes -- 'test/unit/**/**.test.js'",
|
|
46
46
|
"test:coverage-check": "npm run test:coverage && nyc check-coverage",
|
|
47
|
+
"test:functional": "true",
|
|
48
|
+
"test:integration": "true",
|
|
47
49
|
"audit:fix": "npm audit fix",
|
|
48
50
|
"audit:check": "npx audit-ci --config ./audit-ci.jsonc",
|
|
49
51
|
"dep:check": "npx ncu -e 2",
|
|
@@ -54,6 +56,7 @@
|
|
|
54
56
|
"dependencies": {
|
|
55
57
|
"@hapi/catbox": "12.1.1",
|
|
56
58
|
"@hapi/catbox-memory": "5.0.1",
|
|
59
|
+
"@mojaloop/inter-scheme-proxy-cache-lib": "1.2.0",
|
|
57
60
|
"axios": "1.7.2",
|
|
58
61
|
"clone": "2.1.2",
|
|
59
62
|
"dotenv": "16.4.5",
|
package/src/enums/endpoints.js
CHANGED
|
@@ -105,7 +105,6 @@ const FspEndpointTemplates = {
|
|
|
105
105
|
TRANSACTION_REQUEST_GET: '/transactionRequests/{{ID}}',
|
|
106
106
|
TRANSACTION_REQUEST_PUT_ERROR: '/transactionRequests/{{ID}}/error',
|
|
107
107
|
PARTICIPANT_ENDPOINTS_GET: '/participants/{{fsp}}/endpoints',
|
|
108
|
-
PARTICIPANTS_GET_ALL: '/participants',
|
|
109
108
|
PARTICIPANTS_GET: '/participants/{{fsp}}',
|
|
110
109
|
PARTICIPANTS_POST: '/participants',
|
|
111
110
|
PARTIES_GET: '/parties/{{fsp}}',
|
package/src/enums/http.js
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -9,7 +9,6 @@ declare namespace CentralServicesShared {
|
|
|
9
9
|
FSPIOP: {
|
|
10
10
|
SOURCE: string;
|
|
11
11
|
DESTINATION: string;
|
|
12
|
-
PROXY: string;
|
|
13
12
|
HTTP_METHOD: string;
|
|
14
13
|
SIGNATURE: string;
|
|
15
14
|
URI: string;
|
|
@@ -598,26 +597,16 @@ declare namespace CentralServicesShared {
|
|
|
598
597
|
};
|
|
599
598
|
};
|
|
600
599
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
initializeCache(policyOptions: object, config: { hubName: string, hubNameRegex: RegExp }): Promise<boolean>
|
|
604
|
-
stopCache(): Promise<void>
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
interface Endpoints extends Cacheable {
|
|
600
|
+
interface Endpoints {
|
|
601
|
+
fetchEndpoints(fspId: string): Promise<any>
|
|
608
602
|
getEndpoint(switchUrl: string, fsp: string, endpointType: FspEndpointTypesEnum, options?: any): Promise<string>
|
|
603
|
+
initializeCache(policyOptions: object, config: { hubName: string, hubNameRegex: RegExp }): Promise<boolean>
|
|
609
604
|
getEndpointAndRender(switchUrl: string, fsp: string, endpointType: FspEndpointTypesEnum, path: string, options?: any): Promise<string>
|
|
610
605
|
}
|
|
611
606
|
|
|
612
|
-
interface Participants
|
|
607
|
+
interface Participants {
|
|
613
608
|
getParticipant(switchUrl: string, fsp: string): Promise<object>
|
|
614
|
-
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
type ProxyNames = string[]
|
|
618
|
-
interface Proxies extends Cacheable {
|
|
619
|
-
getAllProxiesNames(switchUrl: string): Promise<ProxyNames>
|
|
620
|
-
invalidateProxiesCache(): Promise<void>
|
|
609
|
+
initializeCache(policyOptions: object, config: { hubName: string, hubNameRegex: RegExp }): Promise<boolean>
|
|
621
610
|
}
|
|
622
611
|
|
|
623
612
|
interface ProtocolVersionsType {
|
|
@@ -652,7 +641,6 @@ declare namespace CentralServicesShared {
|
|
|
652
641
|
interface Util {
|
|
653
642
|
Endpoints: Endpoints;
|
|
654
643
|
Participants: Participants;
|
|
655
|
-
proxies: Proxies;
|
|
656
644
|
Hapi: any;
|
|
657
645
|
Kafka: Kafka;
|
|
658
646
|
OpenapiBackend: any;
|
package/src/util/endpoints.js
CHANGED
|
@@ -37,12 +37,14 @@ const partition = 'endpoint-cache'
|
|
|
37
37
|
const clientOptions = { partition }
|
|
38
38
|
const Mustache = require('mustache')
|
|
39
39
|
const Metrics = require('@mojaloop/central-services-metrics')
|
|
40
|
+
const proxyLib = require('@mojaloop/inter-scheme-proxy-cache-lib')
|
|
40
41
|
|
|
41
42
|
let client
|
|
42
43
|
let policy
|
|
43
44
|
let switchEndpoint
|
|
44
45
|
let hubName
|
|
45
46
|
let hubNameRegex
|
|
47
|
+
let proxy
|
|
46
48
|
|
|
47
49
|
/**
|
|
48
50
|
* @function fetchEndpoints
|
|
@@ -137,7 +139,7 @@ exports.initializeCache = async (policyOptions, config) => {
|
|
|
137
139
|
*
|
|
138
140
|
* @returns {string} - Returns the endpoint, throws error if failure occurs
|
|
139
141
|
*/
|
|
140
|
-
exports.getEndpoint = async (switchUrl, fsp, endpointType, options = {}, renderOptions = {}) => {
|
|
142
|
+
exports.getEndpoint = async (switchUrl, fsp, endpointType, options = {}, renderOptions = {}, proxyConfig = undefined) => {
|
|
141
143
|
const histTimer = Metrics.getHistogram(
|
|
142
144
|
'getEndpoint',
|
|
143
145
|
'getEndpoint - Metrics for getEndpoint with cache hit rate',
|
|
@@ -145,11 +147,23 @@ exports.getEndpoint = async (switchUrl, fsp, endpointType, options = {}, renderO
|
|
|
145
147
|
).startTimer()
|
|
146
148
|
switchEndpoint = switchUrl
|
|
147
149
|
Logger.isDebugEnabled && Logger.debug(`participantEndpointCache::getEndpoint::endpointType - ${endpointType}`)
|
|
150
|
+
let proxyId
|
|
151
|
+
const result = url => proxyConfig ? { url, proxyId } : url
|
|
148
152
|
try {
|
|
149
153
|
// If a service passes in `getDecoratedValue` as true, then an object
|
|
150
154
|
// { value, cached, report } is returned, where value is the cached value,
|
|
151
155
|
// cached is null on a cache miss.
|
|
152
|
-
|
|
156
|
+
let endpoints = await policy.get(fsp)
|
|
157
|
+
if (!endpoints && proxyConfig) {
|
|
158
|
+
if (!proxy) {
|
|
159
|
+
const { type, ...config } = proxyConfig
|
|
160
|
+
proxy = proxyLib.createProxyCache(type, config)
|
|
161
|
+
await proxy.connect()
|
|
162
|
+
}
|
|
163
|
+
proxyId = await proxy.lookupProxyByDfspId(fsp)
|
|
164
|
+
endpoints = proxyId && await policy.get(proxyId)
|
|
165
|
+
}
|
|
166
|
+
if (!endpoints) throw ErrorHandler.CreateFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_NOT_FOUND)
|
|
153
167
|
if ('value' in endpoints && 'cached' in endpoints) {
|
|
154
168
|
if (endpoints.cached === null) {
|
|
155
169
|
histTimer({ success: true, hit: false })
|
|
@@ -159,16 +173,16 @@ exports.getEndpoint = async (switchUrl, fsp, endpointType, options = {}, renderO
|
|
|
159
173
|
const endpoint = new Map(endpoints.value).get(endpointType)
|
|
160
174
|
if (renderOptions.path) {
|
|
161
175
|
const renderedEndpoint = (endpoint === undefined) ? endpoint : endpoint + renderOptions.path
|
|
162
|
-
return Mustache.render(renderedEndpoint, options)
|
|
176
|
+
return result(Mustache.render(renderedEndpoint, options))
|
|
163
177
|
}
|
|
164
|
-
return Mustache.render(endpoint, options)
|
|
178
|
+
return result(Mustache.render(endpoint, options))
|
|
165
179
|
}
|
|
166
180
|
let endpoint = new Map(endpoints).get(endpointType)
|
|
167
181
|
if (renderOptions.path) {
|
|
168
182
|
endpoint = (endpoint === undefined) ? endpoint : endpoint + renderOptions.path
|
|
169
183
|
}
|
|
170
184
|
histTimer({ success: true, hit: false })
|
|
171
|
-
return Mustache.render(endpoint, options)
|
|
185
|
+
return result(Mustache.render(endpoint, options))
|
|
172
186
|
} catch (err) {
|
|
173
187
|
histTimer({ success: false, hit: false })
|
|
174
188
|
Logger.isErrorEnabled && Logger.error(`participantEndpointCache::getEndpoint:: ERROR:'${err}'`)
|
|
@@ -222,3 +236,28 @@ exports.stopCache = async () => {
|
|
|
222
236
|
return client.stop()
|
|
223
237
|
}
|
|
224
238
|
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* @function stopProxy
|
|
242
|
+
*
|
|
243
|
+
* @description It stops the proxy client
|
|
244
|
+
*
|
|
245
|
+
* @returns {Promise<void>}
|
|
246
|
+
*/
|
|
247
|
+
exports.stopProxy = async () => {
|
|
248
|
+
const result = await proxy?.disconnect()
|
|
249
|
+
proxy = undefined
|
|
250
|
+
return result
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* @function healthCheckProxy
|
|
255
|
+
*
|
|
256
|
+
* @description It checks the health of the proxy client
|
|
257
|
+
*
|
|
258
|
+
* @returns {Promise<boolean>}
|
|
259
|
+
*/
|
|
260
|
+
|
|
261
|
+
exports.healthCheckProxy = async () => {
|
|
262
|
+
return proxy ? proxy.healthCheck() : true
|
|
263
|
+
}
|
package/src/util/index.js
CHANGED
|
@@ -30,7 +30,6 @@ const _ = require('lodash')
|
|
|
30
30
|
const Kafka = require('./kafka')
|
|
31
31
|
const Endpoints = require('./endpoints')
|
|
32
32
|
const Participants = require('./participants')
|
|
33
|
-
const proxies = require('./proxies')
|
|
34
33
|
const Request = require('./request')
|
|
35
34
|
const Http = require('./http')
|
|
36
35
|
const Hapi = require('./hapi')
|
|
@@ -239,7 +238,6 @@ module.exports = {
|
|
|
239
238
|
filterExtensions,
|
|
240
239
|
Kafka,
|
|
241
240
|
Participants,
|
|
242
|
-
proxies,
|
|
243
241
|
Endpoints,
|
|
244
242
|
Request,
|
|
245
243
|
Http,
|
package/src/util/request.js
CHANGED
|
@@ -59,7 +59,6 @@ request.defaults.httpAgent.toJSON = () => ({})
|
|
|
59
59
|
* @param {string} source id for which callback is being sent from
|
|
60
60
|
* @param {string} destination id for which callback is being sent
|
|
61
61
|
* @param {object | undefined} payload the body of the request being sent
|
|
62
|
-
* @param {object | null} params URL parameters to be sent with the request. Must be a plain object, URLSearchParams object or null/undefined
|
|
63
62
|
* @param {string} responseType the type of the response object
|
|
64
63
|
* @param {object | undefined} span a span for event logging if this request is within a span
|
|
65
64
|
* @param {object | undefined} jwsSigner the jws signer for signing the requests
|
|
@@ -76,7 +75,6 @@ const sendRequest = async ({
|
|
|
76
75
|
destination,
|
|
77
76
|
method = enums.Http.RestMethods.GET,
|
|
78
77
|
payload = undefined,
|
|
79
|
-
params,
|
|
80
78
|
responseType = enums.Http.ResponseTypes.JSON,
|
|
81
79
|
span = undefined,
|
|
82
80
|
jwsSigner = undefined,
|
|
@@ -111,7 +109,6 @@ const sendRequest = async ({
|
|
|
111
109
|
method,
|
|
112
110
|
headers: transformedHeaders,
|
|
113
111
|
data: payload,
|
|
114
|
-
params,
|
|
115
112
|
responseType,
|
|
116
113
|
httpAgent: new http.Agent({ keepAlive: true }),
|
|
117
114
|
...axiosRequestOptionsOverride
|
|
@@ -5,9 +5,27 @@ const Mustache = require('mustache')
|
|
|
5
5
|
const Catbox = require('@hapi/catbox')
|
|
6
6
|
const Logger = require('@mojaloop/central-services-logger')
|
|
7
7
|
const Sinon = require('sinon')
|
|
8
|
+
const Proxyquire = require('proxyquire')
|
|
8
9
|
|
|
9
10
|
const src = '../../../src'
|
|
10
|
-
const Cache =
|
|
11
|
+
const Cache = Proxyquire(`${src}/util/endpoints`, {
|
|
12
|
+
'@mojaloop/inter-scheme-proxy-cache-lib': {
|
|
13
|
+
createProxyCache () {
|
|
14
|
+
return {
|
|
15
|
+
async connect () {},
|
|
16
|
+
lookupProxyByDfspId () {
|
|
17
|
+
return 'fsp'
|
|
18
|
+
},
|
|
19
|
+
async healthCheck () {
|
|
20
|
+
return true
|
|
21
|
+
},
|
|
22
|
+
async disconnect () {
|
|
23
|
+
return true
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
})
|
|
11
29
|
const request = require(`${src}/util/request`)
|
|
12
30
|
const Config = require('../../util/config')
|
|
13
31
|
const Http = require(`${src}/util`).Http
|
|
@@ -96,6 +114,59 @@ Test('Cache Test', (cacheTest) => {
|
|
|
96
114
|
}
|
|
97
115
|
})
|
|
98
116
|
|
|
117
|
+
getEndpointTest.test('return the endpoint using proxy', async (test) => {
|
|
118
|
+
const fsp = 'fsp'
|
|
119
|
+
const proxiedFsp = 'proxied'
|
|
120
|
+
const url = Mustache.render(
|
|
121
|
+
Config.ENDPOINT_SOURCE_URL +
|
|
122
|
+
Enum.EndPoints.FspEndpointTemplates.PARTICIPANT_ENDPOINTS_GET,
|
|
123
|
+
{ fsp }
|
|
124
|
+
)
|
|
125
|
+
const proxiedUrl = Mustache.render(
|
|
126
|
+
Config.ENDPOINT_SOURCE_URL +
|
|
127
|
+
Enum.EndPoints.FspEndpointTemplates.PARTICIPANT_ENDPOINTS_GET,
|
|
128
|
+
{ fsp: proxiedFsp }
|
|
129
|
+
)
|
|
130
|
+
const endpointType = FSPIOP_CALLBACK_URL_TRANSFER_PUT
|
|
131
|
+
const expected = {
|
|
132
|
+
url: 'http://localhost:1080/transfers/97b01bd3-b223-415b-b37b-ab5bef9bdbed',
|
|
133
|
+
proxyId: 'fsp'
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
await Cache.initializeCache(Config.ENDPOINT_CACHE_CONFIG, {
|
|
137
|
+
hubName, hubNameRegex
|
|
138
|
+
})
|
|
139
|
+
request.sendRequest
|
|
140
|
+
.withArgs({ url, headers: Helper.defaultHeaders(), source: hubName, destination: hubName, hubNameRegex })
|
|
141
|
+
.returns(Promise.resolve(Helper.getEndPointsResponse))
|
|
142
|
+
request.sendRequest
|
|
143
|
+
.withArgs({ url: proxiedUrl, headers: Helper.defaultHeaders(), source: hubName, destination: hubName, hubNameRegex })
|
|
144
|
+
.rejects(new Error('Not found'))
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
test.equal(await Cache.healthCheckProxy(), true, 'Health check proxy if not created')
|
|
148
|
+
test.equal(await Cache.stopProxy(), undefined, 'Stop proxy if not created')
|
|
149
|
+
|
|
150
|
+
const result = await Cache.getEndpoint(
|
|
151
|
+
Config.ENDPOINT_SOURCE_URL,
|
|
152
|
+
proxiedFsp,
|
|
153
|
+
endpointType,
|
|
154
|
+
{ transferId: '97b01bd3-b223-415b-b37b-ab5bef9bdbed' },
|
|
155
|
+
undefined,
|
|
156
|
+
{}
|
|
157
|
+
)
|
|
158
|
+
test.deepEqual(result, expected, 'The results match')
|
|
159
|
+
test.equal(await Cache.healthCheckProxy(), true, 'Health check proxy')
|
|
160
|
+
test.equal(await Cache.stopProxy(), true, 'Stop proxy')
|
|
161
|
+
|
|
162
|
+
await Cache.stopCache()
|
|
163
|
+
test.end()
|
|
164
|
+
} catch (err) {
|
|
165
|
+
test.fail('Error thrown', err)
|
|
166
|
+
test.end()
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
|
|
99
170
|
getEndpointTest.test(
|
|
100
171
|
'return the endpoint if catbox returns decoratedValue object',
|
|
101
172
|
async (test) => {
|
package/src/util/proxies.js
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
/*****
|
|
2
|
-
License
|
|
3
|
-
--------------
|
|
4
|
-
Copyright © 2017 Bill & Melinda Gates Foundation
|
|
5
|
-
The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
|
|
6
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
-
Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
8
|
-
|
|
9
|
-
Contributors
|
|
10
|
-
--------------
|
|
11
|
-
This is the official list of the Mojaloop project contributors for this file.
|
|
12
|
-
Names of the original copyright holders (individuals or organizations)
|
|
13
|
-
should be listed with a '*' in the first column. People who have
|
|
14
|
-
contributed from an organization can be listed under the organization
|
|
15
|
-
that actually holds the copyright for their contributions (see the
|
|
16
|
-
Gates Foundation organization for an example). Those individuals should have
|
|
17
|
-
their names indented and be marked with a '-'. Email address can be added
|
|
18
|
-
optionally within square brackets <email>.
|
|
19
|
-
* Gates Foundation
|
|
20
|
-
- Name Surname <name.surname@gatesfoundation.com>
|
|
21
|
-
|
|
22
|
-
* Eugen Klymniuk <eugen.klymniuk@infitx.com>
|
|
23
|
-
--------------
|
|
24
|
-
**********/
|
|
25
|
-
|
|
26
|
-
const Mustache = require('mustache')
|
|
27
|
-
const Catbox = require('@hapi/catbox')
|
|
28
|
-
const CatboxMemory = require('@hapi/catbox-memory')
|
|
29
|
-
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
|
30
|
-
const Logger = require('@mojaloop/central-services-logger')
|
|
31
|
-
const Metrics = require('@mojaloop/central-services-metrics')
|
|
32
|
-
|
|
33
|
-
const Enum = require('../enums')
|
|
34
|
-
const Http = require('./http')
|
|
35
|
-
const request = require('./request')
|
|
36
|
-
|
|
37
|
-
const partition = 'proxies-cache'
|
|
38
|
-
const clientOptions = { partition }
|
|
39
|
-
const cacheKey = 'allProxies'
|
|
40
|
-
|
|
41
|
-
let client
|
|
42
|
-
let policy
|
|
43
|
-
let switchEndpoint
|
|
44
|
-
let hubName
|
|
45
|
-
let hubNameRegex
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* @function fetchProxies
|
|
49
|
-
* @description This populates the cache of proxies
|
|
50
|
-
* @returns {array} proxies Returns the list containing proxies
|
|
51
|
-
*/
|
|
52
|
-
const fetchProxies = async () => {
|
|
53
|
-
const histTimer = Metrics.getHistogram(
|
|
54
|
-
'fetchProxies',
|
|
55
|
-
'fetchProxies - Metrics for fetchProxies',
|
|
56
|
-
['success']
|
|
57
|
-
).startTimer()
|
|
58
|
-
try {
|
|
59
|
-
Logger.isDebugEnabled && Logger.debug('proxiesCache::fetchProxies := Refreshing proxies cache')
|
|
60
|
-
if (!hubName || !hubNameRegex) {
|
|
61
|
-
throw Error('No hubName or hubNameRegex! Initialize the cache first.')
|
|
62
|
-
}
|
|
63
|
-
const defaultHeaders = Http.SwitchDefaultHeaders(hubName, Enum.Http.HeaderResources.PARTICIPANTS, hubName)
|
|
64
|
-
const url = Mustache.render(switchEndpoint + Enum.EndPoints.FspEndpointTemplates.PARTICIPANTS_GET_ALL)
|
|
65
|
-
const params = { isProxy: true }
|
|
66
|
-
Logger.isDebugEnabled && Logger.debug(`proxiesCache::fetchProxies := URL: ${url} QS: ${JSON.stringify(params)}`)
|
|
67
|
-
const response = await request.sendRequest({
|
|
68
|
-
url,
|
|
69
|
-
headers: defaultHeaders,
|
|
70
|
-
source: hubName,
|
|
71
|
-
destination: hubName,
|
|
72
|
-
params,
|
|
73
|
-
hubNameRegex
|
|
74
|
-
})
|
|
75
|
-
const proxies = response.data
|
|
76
|
-
histTimer({ success: true })
|
|
77
|
-
return proxies
|
|
78
|
-
} catch (e) {
|
|
79
|
-
histTimer({ success: false })
|
|
80
|
-
Logger.isErrorEnabled && Logger.error(`proxiesCache::fetchProxies:: ERROR:'${e}'`)
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* @function initializeCache
|
|
86
|
-
*
|
|
87
|
-
* @description This initializes the cache for allProxies
|
|
88
|
-
* @param {object} policyOptions The Endpoint_Cache_Config for the Cache being stored https://hapi.dev/module/catbox/api/?v=12.1.1#policy
|
|
89
|
-
* @param {object} config The config object containing paramters used for the request function
|
|
90
|
-
* @returns {boolean} Returns true on successful initialization of the cache, throws error on failures
|
|
91
|
-
*/
|
|
92
|
-
exports.initializeCache = async (policyOptions, config) => {
|
|
93
|
-
try {
|
|
94
|
-
Logger.isDebugEnabled && Logger.debug(`proxiesCache::initializeCache::start::clientOptions - ${JSON.stringify(clientOptions)}`)
|
|
95
|
-
client = new Catbox.Client(CatboxMemory, clientOptions)
|
|
96
|
-
await client.start()
|
|
97
|
-
policyOptions.generateFunc = fetchProxies
|
|
98
|
-
Logger.isDebugEnabled && Logger.debug(`proxiesCache::initializeCache::start::policyOptions - ${JSON.stringify(policyOptions)}`)
|
|
99
|
-
policy = new Catbox.Policy(policyOptions, client, partition)
|
|
100
|
-
Logger.isDebugEnabled && Logger.debug('proxiesCache::initializeCache::Cache initialized successfully')
|
|
101
|
-
hubName = config.hubName
|
|
102
|
-
hubNameRegex = config.hubNameRegex
|
|
103
|
-
return true
|
|
104
|
-
} catch (err) {
|
|
105
|
-
Logger.isErrorEnabled && Logger.error(`proxiesCache::Cache error:: ERROR:'${err}'`)
|
|
106
|
-
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* @function getAllProxiesNames
|
|
112
|
-
* @description It returns a list of allProxies names from the cache if the cache is still valid, otherwise it will refresh the cache and return the value
|
|
113
|
-
*
|
|
114
|
-
* @param {string} switchUrl the endpoint for the switch
|
|
115
|
-
*
|
|
116
|
-
* @returns {string[]} - Returns list of allProxies names, throws error if failure occurs
|
|
117
|
-
*/
|
|
118
|
-
exports.getAllProxiesNames = async (switchUrl) => {
|
|
119
|
-
const histTimer = Metrics.getHistogram(
|
|
120
|
-
'getAllProxiesNames',
|
|
121
|
-
'getAllProxiesNames - Metrics for getAllProxies with cache hit rate',
|
|
122
|
-
['success', 'hit']
|
|
123
|
-
).startTimer()
|
|
124
|
-
switchEndpoint = switchUrl
|
|
125
|
-
Logger.isDebugEnabled && Logger.debug('proxiesCache::getAllProxiesNames')
|
|
126
|
-
try {
|
|
127
|
-
// If a service passes in `getDecoratedValue` as true, then an object
|
|
128
|
-
// { value, cached, report } is returned, where value is the cached value,
|
|
129
|
-
// cached is null on a cache miss.
|
|
130
|
-
let proxies = await policy.get(cacheKey)
|
|
131
|
-
|
|
132
|
-
if ('value' in proxies && 'cached' in proxies) {
|
|
133
|
-
if (proxies.cached === null) {
|
|
134
|
-
histTimer({ success: true, hit: false })
|
|
135
|
-
} else {
|
|
136
|
-
histTimer({ success: true, hit: true })
|
|
137
|
-
}
|
|
138
|
-
proxies = proxies.value
|
|
139
|
-
} else {
|
|
140
|
-
histTimer({ success: true, hit: false })
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (proxies.errorInformation) {
|
|
144
|
-
// Drop error from cache
|
|
145
|
-
await policy.drop(cacheKey)
|
|
146
|
-
throw ErrorHandler.Factory.createFSPIOPErrorFromErrorInformation(proxies.errorInformation)
|
|
147
|
-
}
|
|
148
|
-
return proxies.map(p => p.name)
|
|
149
|
-
} catch (err) {
|
|
150
|
-
histTimer({ success: false, hit: false })
|
|
151
|
-
Logger.isErrorEnabled && Logger.error(`proxiesCache::getAllProxiesNames:: ERROR:'${err}'`)
|
|
152
|
-
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* @function invalidateProxiesCache
|
|
158
|
-
*
|
|
159
|
-
* @description It drops the cache for all proxies
|
|
160
|
-
*
|
|
161
|
-
* @returns {void}
|
|
162
|
-
*/
|
|
163
|
-
exports.invalidateProxiesCache = async () => {
|
|
164
|
-
Logger.isDebugEnabled && Logger.debug('proxiesCache::invalidateProxiesCache::Invalidating the cache')
|
|
165
|
-
if (policy) {
|
|
166
|
-
return policy.drop(cacheKey)
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* @function stopCache
|
|
172
|
-
*
|
|
173
|
-
* @description It stops the cache client
|
|
174
|
-
*
|
|
175
|
-
* @returns {boolean} - Returns the status
|
|
176
|
-
*/
|
|
177
|
-
exports.stopCache = async () => {
|
|
178
|
-
Logger.isDebugEnabled && Logger.debug('proxiesCache::stopCache::Stopping the cache')
|
|
179
|
-
if (client) {
|
|
180
|
-
return client.stop()
|
|
181
|
-
}
|
|
182
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
const Test = require('tapes')(require('tape'))
|
|
2
|
-
const sinon = require('sinon')
|
|
3
|
-
const proxyquire = require('proxyquire')
|
|
4
|
-
const { Http } = require('../../src/enums')
|
|
5
|
-
|
|
6
|
-
Test('sendRequest Tests -->', test => {
|
|
7
|
-
let sandbox
|
|
8
|
-
let axios
|
|
9
|
-
let request
|
|
10
|
-
|
|
11
|
-
test.beforeEach(t => {
|
|
12
|
-
sandbox = sinon.createSandbox()
|
|
13
|
-
axios = sandbox.stub()
|
|
14
|
-
request = proxyquire('../../src/util/request', { axios })
|
|
15
|
-
// sinon can't mock such way of using axios: axios(requestOptions)
|
|
16
|
-
t.end()
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
test.afterEach(t => {
|
|
20
|
-
sandbox.restore()
|
|
21
|
-
t.end()
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
test.test('should add fspiop-signature header if jwsSigner is passed ', async test => {
|
|
25
|
-
const signature = 'signature'
|
|
26
|
-
const jwsSigner = {
|
|
27
|
-
getSignature: sandbox.stub().callsFake(() => signature)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
await request.sendRequest({
|
|
31
|
-
url: 'http://localhost:1234',
|
|
32
|
-
jwsSigner,
|
|
33
|
-
headers: {
|
|
34
|
-
[Http.Headers.FSPIOP.SOURCE]: 'source'
|
|
35
|
-
},
|
|
36
|
-
source: 'source',
|
|
37
|
-
destination: 'destination',
|
|
38
|
-
hubNameRegex: 'hubNameRegex'
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
test.ok(axios.calledOnce)
|
|
42
|
-
const { headers } = axios.lastCall.args[0]
|
|
43
|
-
test.equal(headers['fspiop-signature'], signature)
|
|
44
|
-
test.end()
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
test.end()
|
|
48
|
-
})
|