soajs.controller 4.3.0 → 4.3.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.
@@ -9,8 +9,131 @@
9
9
  */
10
10
 
11
11
  const { httpRequest } = require("../../lib/request.js");
12
+ const { pathToRegexp } = require("path-to-regexp");
12
13
  const get = (p, o) => p.reduce((xs, x) => (xs && xs[x]) ? xs[x] : null, o);
13
14
 
15
+ // Cache compiled RegExp objects for route pattern matching
16
+ const regexpCache = new Map();
17
+ const MAX_REGEXP_CACHE_SIZE = 100;
18
+
19
+ /**
20
+ * Check if a route pattern contains path parameters
21
+ * @param {string} route - The route pattern
22
+ * @returns {boolean}
23
+ */
24
+ function hasPathParams(route) {
25
+ return route.includes("/:");
26
+ }
27
+
28
+ /**
29
+ * Get or create a cached RegExp for a route pattern
30
+ * @param {string} route - The route pattern
31
+ * @returns {RegExp}
32
+ */
33
+ function getRouteRegExp(route) {
34
+ if (regexpCache.has(route)) {
35
+ return regexpCache.get(route);
36
+ }
37
+
38
+ let out = pathToRegexp(route, { sensitive: true });
39
+ let regexp = out.regexp || out;
40
+
41
+ // Simple LRU: clear oldest entries when cache is full
42
+ if (regexpCache.size >= MAX_REGEXP_CACHE_SIZE) {
43
+ const keysToDelete = Array.from(regexpCache.keys()).slice(0, Math.floor(MAX_REGEXP_CACHE_SIZE * 0.25));
44
+ keysToDelete.forEach(key => regexpCache.delete(key));
45
+ }
46
+
47
+ regexpCache.set(route, regexp);
48
+ return regexp;
49
+ }
50
+
51
+ /**
52
+ * Check if the current request should trigger lastSeen
53
+ * @param {Object} include - The include whitelist configuration
54
+ * @param {string} serviceName - The current service name
55
+ * @param {string} apiPath - The current API path
56
+ * @param {string} method - The HTTP method (GET, POST, etc.)
57
+ * @returns {boolean} - true if lastSeen should be triggered
58
+ */
59
+ function shouldTriggerLastSeen(include, serviceName, apiPath, method) {
60
+ // No include filter = trigger for all (backward compatible)
61
+ if (!include) {
62
+ return true;
63
+ }
64
+
65
+ // Service not in whitelist
66
+ if (!include[serviceName]) {
67
+ return false;
68
+ }
69
+
70
+ const serviceConfig = include[serviceName];
71
+
72
+ // Service-level match (all APIs, all methods)
73
+ if (serviceConfig === true) {
74
+ return true;
75
+ }
76
+
77
+ // API-level match
78
+ if (typeof serviceConfig === 'object' && serviceConfig.apis) {
79
+ return isApiMethodMatch(serviceConfig.apis, apiPath, method);
80
+ }
81
+
82
+ return false;
83
+ }
84
+
85
+ /**
86
+ * Check if API path and method match the apis configuration
87
+ * @param {Object} apis - The apis configuration object
88
+ * @param {string} apiPath - The current API path
89
+ * @param {string} method - The HTTP method
90
+ * @returns {boolean}
91
+ */
92
+ function isApiMethodMatch(apis, apiPath, method) {
93
+ // Check for wildcard first
94
+ if (apis["*"]) {
95
+ return isMethodMatch(apis["*"], method);
96
+ }
97
+
98
+ // Check exact match first
99
+ if (apis[apiPath]) {
100
+ return isMethodMatch(apis[apiPath], method);
101
+ }
102
+
103
+ // Check pattern matching for routes with path params
104
+ for (const routePattern of Object.keys(apis)) {
105
+ if (hasPathParams(routePattern)) {
106
+ const regexp = getRouteRegExp(routePattern);
107
+ if (regexp.test(apiPath)) {
108
+ return isMethodMatch(apis[routePattern], method);
109
+ }
110
+ }
111
+ }
112
+
113
+ return false;
114
+ }
115
+
116
+ /**
117
+ * Check if method matches the method configuration
118
+ * @param {boolean|Array} methodConfig - true for all methods, or array of methods
119
+ * @param {string} method - The HTTP method
120
+ * @returns {boolean}
121
+ */
122
+ function isMethodMatch(methodConfig, method) {
123
+ // true = all methods
124
+ if (methodConfig === true) {
125
+ return true;
126
+ }
127
+
128
+ // Array of methods (case-insensitive)
129
+ if (Array.isArray(methodConfig)) {
130
+ const lowerMethod = method.toLowerCase();
131
+ return methodConfig.some(m => m.toLowerCase() === lowerMethod);
132
+ }
133
+
134
+ return false;
135
+ }
136
+
14
137
  /**
15
138
  *
16
139
  * @param configuration
@@ -25,6 +148,16 @@ module.exports = () => {
25
148
  let lastSeen = get(["soajs", "registry", "custom", "gateway", "value", "lastSeen"], req);
26
149
  if (lastSeen && lastSeen.active) {
27
150
 
151
+ // Check include filter
152
+ let currentService = get(["soajs", "controller", "serviceParams", "name"], req);
153
+ let currentApi = get(["soajs", "controller", "serviceParams", "parsedUrl", "pathname"], req);
154
+ let currentMethod = req.method;
155
+
156
+ if (!shouldTriggerLastSeen(lastSeen.include, currentService, currentApi, currentMethod)) {
157
+ req.soajs.log.debug("lastSeen skipped for [" + currentService + " " + currentMethod + " " + currentApi + "]");
158
+ return;
159
+ }
160
+
28
161
  const item = {
29
162
  "name": lastSeen.serviceName || "urac",
30
163
  "version": lastSeen.serviceVersion || "3",
@@ -62,49 +195,7 @@ module.exports = () => {
62
195
  } else {
63
196
  req.soajs.log.debug("lastSeen ", body);
64
197
  }
65
- // else if (!body.result) {
66
- // let errorMsg = "";
67
- // if (body.errors && body.errors && body.errors.details && body.errors.details.length > 0) {
68
- // body.errors.details.forEach((detail) => {
69
- // if (errorMsg === "") {
70
- // errorMsg += detail.message;
71
- // }
72
- // else {
73
- // errorMsg += " - " + detail.message;
74
- // }
75
- // });
76
- // }
77
- // req.soajs.log.debug("lastSeen", errorMsg);
78
- // }
79
198
  });
80
-
81
- // let options = {
82
- // method: "post",
83
- // uri: "http://" + item.host + ":" + item.port + item.api,
84
- // json: true
85
- // };
86
- // if (req.headers && req.headers.soajsinjectobj) {
87
- // options.headers = { "soajsinjectobj": req.headers.soajsinjectobj };
88
- // }
89
- // request(options, (error, response, body) => {
90
- // if (error) {
91
- // req.soajs.log.debug("lastSeen failed for [" + item.name + "@" + item.version + " " + item.api + "]");
92
- // req.soajs.log.debug("lastSeen " + error.message);
93
- // } else if (!body.result) {
94
- // let errorMsg = "";
95
- // if (body.errors && body.errors && body.errors.details && body.errors.details.length > 0) {
96
- // body.errors.details.forEach((detail) => {
97
- // if (errorMsg === "") {
98
- // errorMsg += detail.message;
99
- // }
100
- // else {
101
- // errorMsg += " - " + detail.message;
102
- // }
103
- // });
104
- // }
105
- // req.soajs.log.debug("lastSeen", errorMsg);
106
- // }
107
- // });
108
199
  } else {
109
200
  req.soajs.log.debug("lastSeen failed with no host for [" + item.name + "@" + item.version + " " + item.api + "]");
110
201
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "soajs.controller",
3
3
  "description": "soajs multi tenant API gateway",
4
- "version": "4.3.0",
4
+ "version": "4.3.1",
5
5
  "author": {
6
6
  "name": "soajs team",
7
7
  "email": "team@soajs.org"
@@ -3,7 +3,7 @@
3
3
  const helper = require("../../../helper.js");
4
4
  const mw = helper.requireModule('./mw/lastSeen/index');
5
5
  const assert = require('assert');
6
- const nock = require('nock')
6
+ const nock = require('nock');
7
7
 
8
8
  describe("Unit test for: mw - lastSeen", () => {
9
9
 
@@ -11,7 +11,7 @@ describe("Unit test for: mw - lastSeen", () => {
11
11
  let res = {};
12
12
  let req = {
13
13
  getClientIP: () => {
14
- return "127.0.0.1"
14
+ return "127.0.0.1";
15
15
  },
16
16
  soajs: {
17
17
  log: {
@@ -65,4 +65,948 @@ describe("Unit test for: mw - lastSeen", () => {
65
65
  });
66
66
  });
67
67
 
68
+ describe("include filter tests", () => {
69
+
70
+ it("no include filter - backward compatibility - should trigger", (done) => {
71
+ let res = {};
72
+ let req = {
73
+ method: "GET",
74
+ getClientIP: () => {
75
+ return "127.0.0.1";
76
+ },
77
+ soajs: {
78
+ log: {
79
+ debug: (a) => {
80
+ console.log(a);
81
+ },
82
+ error: (a) => {
83
+ console.log(a);
84
+ }
85
+ },
86
+ controller: {
87
+ serviceParams: {
88
+ name: "dashboard",
89
+ parsedUrl: {
90
+ pathname: "/some/api"
91
+ }
92
+ }
93
+ },
94
+ uracDriver: {
95
+ getProfile: () => {
96
+ return { _id: "1111111111" };
97
+ }
98
+ },
99
+ awareness: {
100
+ getHost: (name, version, cb) => {
101
+ return cb("urac.fake");
102
+ }
103
+ },
104
+ registry: {
105
+ services: {
106
+ urac: {
107
+ port: 4001
108
+ }
109
+ },
110
+ custom: {
111
+ gateway: {
112
+ value: {
113
+ lastSeen: {
114
+ active: true,
115
+ network: "YAYA"
116
+ // No include filter
117
+ }
118
+ }
119
+ }
120
+ }
121
+ }
122
+ }
123
+ };
124
+ const scope = nock('http://urac.fake:4001')
125
+ .post('/user/last/seen', "{\"network\":\"YAYA\"}")
126
+ .reply(200, {
127
+ result: true,
128
+ data: true
129
+ });
130
+ let functionMw = mw({});
131
+ functionMw(req, res, (error) => {
132
+ assert.ifError(error);
133
+ done();
134
+ });
135
+ });
136
+
137
+ it("include filter with service true - should trigger for any API/method", (done) => {
138
+ let res = {};
139
+ let req = {
140
+ method: "POST",
141
+ getClientIP: () => {
142
+ return "127.0.0.1";
143
+ },
144
+ soajs: {
145
+ log: {
146
+ debug: (a) => {
147
+ console.log(a);
148
+ },
149
+ error: (a) => {
150
+ console.log(a);
151
+ }
152
+ },
153
+ controller: {
154
+ serviceParams: {
155
+ name: "dashboard",
156
+ parsedUrl: {
157
+ pathname: "/any/api/path"
158
+ }
159
+ }
160
+ },
161
+ uracDriver: {
162
+ getProfile: () => {
163
+ return { _id: "1111111111" };
164
+ }
165
+ },
166
+ awareness: {
167
+ getHost: (name, version, cb) => {
168
+ return cb("urac.fake");
169
+ }
170
+ },
171
+ registry: {
172
+ services: {
173
+ urac: {
174
+ port: 4001
175
+ }
176
+ },
177
+ custom: {
178
+ gateway: {
179
+ value: {
180
+ lastSeen: {
181
+ active: true,
182
+ network: "YAYA",
183
+ include: {
184
+ "dashboard": true
185
+ }
186
+ }
187
+ }
188
+ }
189
+ }
190
+ }
191
+ }
192
+ };
193
+ const scope = nock('http://urac.fake:4001')
194
+ .post('/user/last/seen', "{\"network\":\"YAYA\"}")
195
+ .reply(200, {
196
+ result: true,
197
+ data: true
198
+ });
199
+ let functionMw = mw({});
200
+ functionMw(req, res, (error) => {
201
+ assert.ifError(error);
202
+ done();
203
+ });
204
+ });
205
+
206
+ it("include filter with service NOT in whitelist - should NOT trigger", (done) => {
207
+ let lastSeenSkipped = false;
208
+ let res = {};
209
+ let req = {
210
+ method: "GET",
211
+ getClientIP: () => {
212
+ return "127.0.0.1";
213
+ },
214
+ soajs: {
215
+ log: {
216
+ debug: (a) => {
217
+ console.log(a);
218
+ if (a && a.includes && a.includes("lastSeen skipped")) {
219
+ lastSeenSkipped = true;
220
+ }
221
+ },
222
+ error: (a) => {
223
+ console.log(a);
224
+ }
225
+ },
226
+ controller: {
227
+ serviceParams: {
228
+ name: "other-service",
229
+ parsedUrl: {
230
+ pathname: "/some/api"
231
+ }
232
+ }
233
+ },
234
+ uracDriver: {
235
+ getProfile: () => {
236
+ return { _id: "1111111111" };
237
+ }
238
+ },
239
+ awareness: {
240
+ getHost: (name, version, cb) => {
241
+ return cb("urac.fake");
242
+ }
243
+ },
244
+ registry: {
245
+ services: {
246
+ urac: {
247
+ port: 4001
248
+ }
249
+ },
250
+ custom: {
251
+ gateway: {
252
+ value: {
253
+ lastSeen: {
254
+ active: true,
255
+ network: "YAYA",
256
+ include: {
257
+ "dashboard": true
258
+ }
259
+ }
260
+ }
261
+ }
262
+ }
263
+ }
264
+ }
265
+ };
266
+ let functionMw = mw({});
267
+ functionMw(req, res, (error) => {
268
+ assert.ifError(error);
269
+ setTimeout(() => {
270
+ assert.ok(lastSeenSkipped, "lastSeen should have been skipped");
271
+ done();
272
+ }, 50);
273
+ });
274
+ });
275
+
276
+ it("include filter with specific API and method match - should trigger", (done) => {
277
+ let res = {};
278
+ let req = {
279
+ method: "POST",
280
+ getClientIP: () => {
281
+ return "127.0.0.1";
282
+ },
283
+ soajs: {
284
+ log: {
285
+ debug: (a) => {
286
+ console.log(a);
287
+ },
288
+ error: (a) => {
289
+ console.log(a);
290
+ }
291
+ },
292
+ controller: {
293
+ serviceParams: {
294
+ name: "urac",
295
+ parsedUrl: {
296
+ pathname: "/user/profile"
297
+ }
298
+ }
299
+ },
300
+ uracDriver: {
301
+ getProfile: () => {
302
+ return { _id: "1111111111" };
303
+ }
304
+ },
305
+ awareness: {
306
+ getHost: (name, version, cb) => {
307
+ return cb("urac.fake");
308
+ }
309
+ },
310
+ registry: {
311
+ services: {
312
+ urac: {
313
+ port: 4001
314
+ }
315
+ },
316
+ custom: {
317
+ gateway: {
318
+ value: {
319
+ lastSeen: {
320
+ active: true,
321
+ network: "YAYA",
322
+ include: {
323
+ "urac": {
324
+ "apis": {
325
+ "/user/profile": ["get", "post"]
326
+ }
327
+ }
328
+ }
329
+ }
330
+ }
331
+ }
332
+ }
333
+ }
334
+ }
335
+ };
336
+ const scope = nock('http://urac.fake:4001')
337
+ .post('/user/last/seen', "{\"network\":\"YAYA\"}")
338
+ .reply(200, {
339
+ result: true,
340
+ data: true
341
+ });
342
+ let functionMw = mw({});
343
+ functionMw(req, res, (error) => {
344
+ assert.ifError(error);
345
+ done();
346
+ });
347
+ });
348
+
349
+ it("include filter with specific API but method NOT match - should NOT trigger", (done) => {
350
+ let lastSeenSkipped = false;
351
+ let res = {};
352
+ let req = {
353
+ method: "DELETE",
354
+ getClientIP: () => {
355
+ return "127.0.0.1";
356
+ },
357
+ soajs: {
358
+ log: {
359
+ debug: (a) => {
360
+ console.log(a);
361
+ if (a && a.includes && a.includes("lastSeen skipped")) {
362
+ lastSeenSkipped = true;
363
+ }
364
+ },
365
+ error: (a) => {
366
+ console.log(a);
367
+ }
368
+ },
369
+ controller: {
370
+ serviceParams: {
371
+ name: "urac",
372
+ parsedUrl: {
373
+ pathname: "/user/profile"
374
+ }
375
+ }
376
+ },
377
+ uracDriver: {
378
+ getProfile: () => {
379
+ return { _id: "1111111111" };
380
+ }
381
+ },
382
+ awareness: {
383
+ getHost: (name, version, cb) => {
384
+ return cb("urac.fake");
385
+ }
386
+ },
387
+ registry: {
388
+ services: {
389
+ urac: {
390
+ port: 4001
391
+ }
392
+ },
393
+ custom: {
394
+ gateway: {
395
+ value: {
396
+ lastSeen: {
397
+ active: true,
398
+ network: "YAYA",
399
+ include: {
400
+ "urac": {
401
+ "apis": {
402
+ "/user/profile": ["get", "post"]
403
+ }
404
+ }
405
+ }
406
+ }
407
+ }
408
+ }
409
+ }
410
+ }
411
+ }
412
+ };
413
+ let functionMw = mw({});
414
+ functionMw(req, res, (error) => {
415
+ assert.ifError(error);
416
+ setTimeout(() => {
417
+ assert.ok(lastSeenSkipped, "lastSeen should have been skipped");
418
+ done();
419
+ }, 50);
420
+ });
421
+ });
422
+
423
+ it("include filter with API true - all methods - should trigger", (done) => {
424
+ let res = {};
425
+ let req = {
426
+ method: "PUT",
427
+ getClientIP: () => {
428
+ return "127.0.0.1";
429
+ },
430
+ soajs: {
431
+ log: {
432
+ debug: (a) => {
433
+ console.log(a);
434
+ },
435
+ error: (a) => {
436
+ console.log(a);
437
+ }
438
+ },
439
+ controller: {
440
+ serviceParams: {
441
+ name: "urac",
442
+ parsedUrl: {
443
+ pathname: "/user/login"
444
+ }
445
+ }
446
+ },
447
+ uracDriver: {
448
+ getProfile: () => {
449
+ return { _id: "1111111111" };
450
+ }
451
+ },
452
+ awareness: {
453
+ getHost: (name, version, cb) => {
454
+ return cb("urac.fake");
455
+ }
456
+ },
457
+ registry: {
458
+ services: {
459
+ urac: {
460
+ port: 4001
461
+ }
462
+ },
463
+ custom: {
464
+ gateway: {
465
+ value: {
466
+ lastSeen: {
467
+ active: true,
468
+ network: "YAYA",
469
+ include: {
470
+ "urac": {
471
+ "apis": {
472
+ "/user/login": true
473
+ }
474
+ }
475
+ }
476
+ }
477
+ }
478
+ }
479
+ }
480
+ }
481
+ }
482
+ };
483
+ const scope = nock('http://urac.fake:4001')
484
+ .post('/user/last/seen', "{\"network\":\"YAYA\"}")
485
+ .reply(200, {
486
+ result: true,
487
+ data: true
488
+ });
489
+ let functionMw = mw({});
490
+ functionMw(req, res, (error) => {
491
+ assert.ifError(error);
492
+ done();
493
+ });
494
+ });
495
+
496
+ it("include filter with wildcard '*': true - should trigger for all APIs", (done) => {
497
+ let res = {};
498
+ let req = {
499
+ method: "GET",
500
+ getClientIP: () => {
501
+ return "127.0.0.1";
502
+ },
503
+ soajs: {
504
+ log: {
505
+ debug: (a) => {
506
+ console.log(a);
507
+ },
508
+ error: (a) => {
509
+ console.log(a);
510
+ }
511
+ },
512
+ controller: {
513
+ serviceParams: {
514
+ name: "multitenant",
515
+ parsedUrl: {
516
+ pathname: "/any/random/api"
517
+ }
518
+ }
519
+ },
520
+ uracDriver: {
521
+ getProfile: () => {
522
+ return { _id: "1111111111" };
523
+ }
524
+ },
525
+ awareness: {
526
+ getHost: (name, version, cb) => {
527
+ return cb("urac.fake");
528
+ }
529
+ },
530
+ registry: {
531
+ services: {
532
+ urac: {
533
+ port: 4001
534
+ }
535
+ },
536
+ custom: {
537
+ gateway: {
538
+ value: {
539
+ lastSeen: {
540
+ active: true,
541
+ network: "YAYA",
542
+ include: {
543
+ "multitenant": {
544
+ "apis": {
545
+ "*": true
546
+ }
547
+ }
548
+ }
549
+ }
550
+ }
551
+ }
552
+ }
553
+ }
554
+ }
555
+ };
556
+ const scope = nock('http://urac.fake:4001')
557
+ .post('/user/last/seen', "{\"network\":\"YAYA\"}")
558
+ .reply(200, {
559
+ result: true,
560
+ data: true
561
+ });
562
+ let functionMw = mw({});
563
+ functionMw(req, res, (error) => {
564
+ assert.ifError(error);
565
+ done();
566
+ });
567
+ });
568
+
569
+ it("include filter with wildcard '*' and method array - should trigger for matching method", (done) => {
570
+ let res = {};
571
+ let req = {
572
+ method: "POST",
573
+ getClientIP: () => {
574
+ return "127.0.0.1";
575
+ },
576
+ soajs: {
577
+ log: {
578
+ debug: (a) => {
579
+ console.log(a);
580
+ },
581
+ error: (a) => {
582
+ console.log(a);
583
+ }
584
+ },
585
+ controller: {
586
+ serviceParams: {
587
+ name: "multitenant",
588
+ parsedUrl: {
589
+ pathname: "/any/random/api"
590
+ }
591
+ }
592
+ },
593
+ uracDriver: {
594
+ getProfile: () => {
595
+ return { _id: "1111111111" };
596
+ }
597
+ },
598
+ awareness: {
599
+ getHost: (name, version, cb) => {
600
+ return cb("urac.fake");
601
+ }
602
+ },
603
+ registry: {
604
+ services: {
605
+ urac: {
606
+ port: 4001
607
+ }
608
+ },
609
+ custom: {
610
+ gateway: {
611
+ value: {
612
+ lastSeen: {
613
+ active: true,
614
+ network: "YAYA",
615
+ include: {
616
+ "multitenant": {
617
+ "apis": {
618
+ "*": ["post", "put"]
619
+ }
620
+ }
621
+ }
622
+ }
623
+ }
624
+ }
625
+ }
626
+ }
627
+ }
628
+ };
629
+ const scope = nock('http://urac.fake:4001')
630
+ .post('/user/last/seen', "{\"network\":\"YAYA\"}")
631
+ .reply(200, {
632
+ result: true,
633
+ data: true
634
+ });
635
+ let functionMw = mw({});
636
+ functionMw(req, res, (error) => {
637
+ assert.ifError(error);
638
+ done();
639
+ });
640
+ });
641
+
642
+ it("include filter with wildcard '*' and method array - should NOT trigger for non-matching method", (done) => {
643
+ let lastSeenSkipped = false;
644
+ let res = {};
645
+ let req = {
646
+ method: "GET",
647
+ getClientIP: () => {
648
+ return "127.0.0.1";
649
+ },
650
+ soajs: {
651
+ log: {
652
+ debug: (a) => {
653
+ console.log(a);
654
+ if (a && a.includes && a.includes("lastSeen skipped")) {
655
+ lastSeenSkipped = true;
656
+ }
657
+ },
658
+ error: (a) => {
659
+ console.log(a);
660
+ }
661
+ },
662
+ controller: {
663
+ serviceParams: {
664
+ name: "multitenant",
665
+ parsedUrl: {
666
+ pathname: "/any/random/api"
667
+ }
668
+ }
669
+ },
670
+ uracDriver: {
671
+ getProfile: () => {
672
+ return { _id: "1111111111" };
673
+ }
674
+ },
675
+ awareness: {
676
+ getHost: (name, version, cb) => {
677
+ return cb("urac.fake");
678
+ }
679
+ },
680
+ registry: {
681
+ services: {
682
+ urac: {
683
+ port: 4001
684
+ }
685
+ },
686
+ custom: {
687
+ gateway: {
688
+ value: {
689
+ lastSeen: {
690
+ active: true,
691
+ network: "YAYA",
692
+ include: {
693
+ "multitenant": {
694
+ "apis": {
695
+ "*": ["post", "put"]
696
+ }
697
+ }
698
+ }
699
+ }
700
+ }
701
+ }
702
+ }
703
+ }
704
+ }
705
+ };
706
+ let functionMw = mw({});
707
+ functionMw(req, res, (error) => {
708
+ assert.ifError(error);
709
+ setTimeout(() => {
710
+ assert.ok(lastSeenSkipped, "lastSeen should have been skipped");
711
+ done();
712
+ }, 50);
713
+ });
714
+ });
715
+
716
+ it("include filter with API not in whitelist - should NOT trigger", (done) => {
717
+ let lastSeenSkipped = false;
718
+ let res = {};
719
+ let req = {
720
+ method: "GET",
721
+ getClientIP: () => {
722
+ return "127.0.0.1";
723
+ },
724
+ soajs: {
725
+ log: {
726
+ debug: (a) => {
727
+ console.log(a);
728
+ if (a && a.includes && a.includes("lastSeen skipped")) {
729
+ lastSeenSkipped = true;
730
+ }
731
+ },
732
+ error: (a) => {
733
+ console.log(a);
734
+ }
735
+ },
736
+ controller: {
737
+ serviceParams: {
738
+ name: "urac",
739
+ parsedUrl: {
740
+ pathname: "/user/other-api"
741
+ }
742
+ }
743
+ },
744
+ uracDriver: {
745
+ getProfile: () => {
746
+ return { _id: "1111111111" };
747
+ }
748
+ },
749
+ awareness: {
750
+ getHost: (name, version, cb) => {
751
+ return cb("urac.fake");
752
+ }
753
+ },
754
+ registry: {
755
+ services: {
756
+ urac: {
757
+ port: 4001
758
+ }
759
+ },
760
+ custom: {
761
+ gateway: {
762
+ value: {
763
+ lastSeen: {
764
+ active: true,
765
+ network: "YAYA",
766
+ include: {
767
+ "urac": {
768
+ "apis": {
769
+ "/user/profile": ["get", "post"]
770
+ }
771
+ }
772
+ }
773
+ }
774
+ }
775
+ }
776
+ }
777
+ }
778
+ }
779
+ };
780
+ let functionMw = mw({});
781
+ functionMw(req, res, (error) => {
782
+ assert.ifError(error);
783
+ setTimeout(() => {
784
+ assert.ok(lastSeenSkipped, "lastSeen should have been skipped");
785
+ done();
786
+ }, 50);
787
+ });
788
+ });
789
+
790
+ it("include filter with path params - should trigger for matching URL", (done) => {
791
+ let res = {};
792
+ let req = {
793
+ method: "POST",
794
+ getClientIP: () => {
795
+ return "127.0.0.1";
796
+ },
797
+ soajs: {
798
+ log: {
799
+ debug: (a) => {
800
+ console.log(a);
801
+ },
802
+ error: (a) => {
803
+ console.log(a);
804
+ }
805
+ },
806
+ controller: {
807
+ serviceParams: {
808
+ name: "av",
809
+ parsedUrl: {
810
+ pathname: "/get/calls/room/abc123"
811
+ }
812
+ }
813
+ },
814
+ uracDriver: {
815
+ getProfile: () => {
816
+ return { _id: "1111111111" };
817
+ }
818
+ },
819
+ awareness: {
820
+ getHost: (name, version, cb) => {
821
+ return cb("urac.fake");
822
+ }
823
+ },
824
+ registry: {
825
+ services: {
826
+ urac: {
827
+ port: 4001
828
+ }
829
+ },
830
+ custom: {
831
+ gateway: {
832
+ value: {
833
+ lastSeen: {
834
+ active: true,
835
+ network: "YAYA",
836
+ include: {
837
+ "av": {
838
+ "apis": {
839
+ "/get/calls/room/:roomId": ["post"]
840
+ }
841
+ }
842
+ }
843
+ }
844
+ }
845
+ }
846
+ }
847
+ }
848
+ }
849
+ };
850
+ const scope = nock('http://urac.fake:4001')
851
+ .post('/user/last/seen', "{\"network\":\"YAYA\"}")
852
+ .reply(200, {
853
+ result: true,
854
+ data: true
855
+ });
856
+ let functionMw = mw({});
857
+ functionMw(req, res, (error) => {
858
+ assert.ifError(error);
859
+ done();
860
+ });
861
+ });
862
+
863
+ it("include filter with path params - should NOT trigger for non-matching URL", (done) => {
864
+ let lastSeenSkipped = false;
865
+ let res = {};
866
+ let req = {
867
+ method: "POST",
868
+ getClientIP: () => {
869
+ return "127.0.0.1";
870
+ },
871
+ soajs: {
872
+ log: {
873
+ debug: (a) => {
874
+ console.log(a);
875
+ if (a && a.includes && a.includes("lastSeen skipped")) {
876
+ lastSeenSkipped = true;
877
+ }
878
+ },
879
+ error: (a) => {
880
+ console.log(a);
881
+ }
882
+ },
883
+ controller: {
884
+ serviceParams: {
885
+ name: "av",
886
+ parsedUrl: {
887
+ pathname: "/get/calls/other/abc123"
888
+ }
889
+ }
890
+ },
891
+ uracDriver: {
892
+ getProfile: () => {
893
+ return { _id: "1111111111" };
894
+ }
895
+ },
896
+ awareness: {
897
+ getHost: (name, version, cb) => {
898
+ return cb("urac.fake");
899
+ }
900
+ },
901
+ registry: {
902
+ services: {
903
+ urac: {
904
+ port: 4001
905
+ }
906
+ },
907
+ custom: {
908
+ gateway: {
909
+ value: {
910
+ lastSeen: {
911
+ active: true,
912
+ network: "YAYA",
913
+ include: {
914
+ "av": {
915
+ "apis": {
916
+ "/get/calls/room/:roomId": ["post"]
917
+ }
918
+ }
919
+ }
920
+ }
921
+ }
922
+ }
923
+ }
924
+ }
925
+ }
926
+ };
927
+ let functionMw = mw({});
928
+ functionMw(req, res, (error) => {
929
+ assert.ifError(error);
930
+ setTimeout(() => {
931
+ assert.ok(lastSeenSkipped, "lastSeen should have been skipped");
932
+ done();
933
+ }, 50);
934
+ });
935
+ });
936
+
937
+ it("include filter with multiple path params - should trigger", (done) => {
938
+ let res = {};
939
+ let req = {
940
+ method: "GET",
941
+ getClientIP: () => {
942
+ return "127.0.0.1";
943
+ },
944
+ soajs: {
945
+ log: {
946
+ debug: (a) => {
947
+ console.log(a);
948
+ },
949
+ error: (a) => {
950
+ console.log(a);
951
+ }
952
+ },
953
+ controller: {
954
+ serviceParams: {
955
+ name: "api",
956
+ parsedUrl: {
957
+ pathname: "/users/user123/posts/post456"
958
+ }
959
+ }
960
+ },
961
+ uracDriver: {
962
+ getProfile: () => {
963
+ return { _id: "1111111111" };
964
+ }
965
+ },
966
+ awareness: {
967
+ getHost: (name, version, cb) => {
968
+ return cb("urac.fake");
969
+ }
970
+ },
971
+ registry: {
972
+ services: {
973
+ urac: {
974
+ port: 4001
975
+ }
976
+ },
977
+ custom: {
978
+ gateway: {
979
+ value: {
980
+ lastSeen: {
981
+ active: true,
982
+ network: "YAYA",
983
+ include: {
984
+ "api": {
985
+ "apis": {
986
+ "/users/:userId/posts/:postId": true
987
+ }
988
+ }
989
+ }
990
+ }
991
+ }
992
+ }
993
+ }
994
+ }
995
+ }
996
+ };
997
+ const scope = nock('http://urac.fake:4001')
998
+ .post('/user/last/seen', "{\"network\":\"YAYA\"}")
999
+ .reply(200, {
1000
+ result: true,
1001
+ data: true
1002
+ });
1003
+ let functionMw = mw({});
1004
+ functionMw(req, res, (error) => {
1005
+ assert.ifError(error);
1006
+ done();
1007
+ });
1008
+ });
1009
+
1010
+ });
1011
+
68
1012
  });