soajs.controller 4.2.19 → 4.2.30

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.
@@ -10,7 +10,7 @@
10
10
 
11
11
  const get = (p, o) => p.reduce((xs, x) => (xs && xs[x]) ? xs[x] : null, o);
12
12
 
13
- const request = require('request');
13
+ const { httpRequestLight, proxyRequestMonitor } = require("../../lib/request.js");
14
14
 
15
15
  module.exports = (configuration) => {
16
16
 
@@ -26,177 +26,163 @@ module.exports = (configuration) => {
26
26
  */
27
27
  return (req, res) => {
28
28
  preRedirect(req, res, core, function (obj) {
29
- let requestOptions = {
30
- 'method': req.method,
31
- 'uri': obj.uri,
32
- //'timeout': obj.requestTO * 1000,
33
- 'headers': req.headers,
34
- 'jar': false
35
- };
36
- if (obj.config.authorization) {
37
- isRequestAuthorized(req, core, requestOptions);
38
- }
39
-
40
- let restServiceParams = req.soajs.controller.serviceParams;
41
- try {
42
- let log_monitor = (doc) => {
43
- let soamonitor = "soamonitor";
44
- let port = get(["registry", "services", "soamonitor", "port"], req.soajs);
45
- if (!port) {
46
- port = "4050";
47
- }
48
- let api = "/monitor/item";
29
+ let log_monitor_triggered = false;
30
+ let log_monitor = (doc) => {
31
+ if (log_monitor_triggered) {
32
+ return;
33
+ }
34
+ log_monitor_triggered = true;
35
+ let soamonitor = "soamonitor";
36
+ let soamonitorVersion = "1";
37
+ let port = get(["registry", "services", "soamonitor", "port"], req.soajs);
38
+ if (!port) {
39
+ port = "4050";
40
+ }
41
+ let api = "/monitor/item";
49
42
 
50
- req.soajs.awareness.getHost(soamonitor, function (host) {
51
- if (!host) {
52
- req.soajs.log.error('Unable to find any healthy host for service ' + soamonitor);
53
- } else {
54
- if (doc && doc.body) {
55
- doc.body = doc.body.toString();
56
- }
57
- if (doc && doc.response) {
58
- doc.response = doc.response.toString();
59
- }
60
- let uri = 'http://' + host + ':' + port + api;
61
- let requestOptions = {
62
- 'uri': uri,
63
- "body": doc,
64
- "json": true
65
- };
66
- if (req.headers && req.headers.soajsinjectobj) {
67
- requestOptions.headers = { "soajsinjectobj": req.headers.soajsinjectobj };
68
- }
69
- request.post(requestOptions, (error, response, body) => {
70
- if (error) {
71
- req.soajs.log.error('Unable register monitor: ' + error.message);
72
- }
43
+ req.soajs.awareness.getHost(soamonitor, soamonitorVersion, function (host) {
44
+ if (!host) {
45
+ req.soajs.log.debug('Unable to find any healthy host for service ' + soamonitor);
46
+ } else {
47
+ if (doc && doc.body) {
48
+ doc.body = doc.body.toString();
49
+ }
50
+ if (doc && doc.response) {
51
+ doc.response = doc.response.toString();
52
+ }
53
+ let uri = "http://" + host + ":" + port + api;
54
+ let options = {
55
+ "method": "POST",
56
+ "uri": uri,
57
+ "data": doc,
58
+ "json": true
59
+ };
60
+ if (req.headers && req.headers.soajsinjectobj) {
61
+ options.headers = { "soajsinjectobj": req.headers.soajsinjectobj };
62
+ }
63
+ httpRequestLight(options)
64
+ .then((body) => {
73
65
  if (body && !body.result) {
74
- req.soajs.log.error(body);
66
+ req.soajs.log.debug(body);
75
67
  }
68
+ })
69
+ .catch((error) => {
70
+ req.soajs.log.debug('Unable register monitor: ' + error.message);
76
71
  });
77
- }
78
- });
79
- };
80
- let monitor = get(["registry", "custom", "gateway", "value", "gotoService", "monitor"], req.soajs);
81
- let monitoObj = {
82
- "time": {}
83
- };
84
- let monitor_service_blacklist = false;
85
- if (monitor && monitor.blacklist) {
86
- if (Array.isArray(monitor.blacklist) && monitor.blacklist.length > 0) {
87
- if (monitor.blacklist.includes(req.soajs.controller.serviceParams.name)) {
88
- monitor_service_blacklist = true;
89
- }
90
72
  }
91
- }
92
- if (monitor && monitor.whitelist) {
93
- if (Array.isArray(monitor.whitelist) && monitor.whitelist.length > 0) {
73
+ });
74
+ };
75
+
76
+ let monitor = get(["registry", "custom", "gateway", "value", "gotoService", "monitor"], req.soajs);
77
+ let monitoObj = {
78
+ "time": {}
79
+ };
80
+ let monitor_service_blacklist = false;
81
+ if (monitor && monitor.blacklist) {
82
+ if (Array.isArray(monitor.blacklist) && monitor.blacklist.length > 0) {
83
+ if (monitor.blacklist.includes(req.soajs.controller.serviceParams.name)) {
94
84
  monitor_service_blacklist = true;
95
- if (monitor.whitelist.includes(req.soajs.controller.serviceParams.name)) {
96
- monitor_service_blacklist = false;
97
- }
98
85
  }
99
86
  }
100
- if (monitor && !monitor_service_blacklist) {
101
- monitoObj.name = req.soajs.controller.serviceParams.name;
102
- monitoObj.version = req.soajs.controller.serviceParams.version;
103
- monitoObj.api = req.soajs.controller.serviceParams.parsedUrl.pathname;
104
- monitoObj.method = req.method;
105
- monitoObj.time.req_start = new Date().getTime();
106
- }
107
- if (monitor && !monitor_service_blacklist && monitor.req_info) {
108
- monitoObj.port = req.soajs.controller.serviceParams.registry.port;
109
- monitoObj.url = req.soajs.controller.serviceParams.url;
110
- monitoObj.host = req.host;
111
- }
112
- if (monitor && !monitor_service_blacklist && monitor.req_header) {
113
- monitoObj.headers = req.headers;
114
- }
115
- if (monitor && !monitor_service_blacklist && monitor.req_query) {
116
- monitoObj.query = req.query;
87
+ }
88
+ if (monitor && monitor.whitelist) {
89
+ if (Array.isArray(monitor.whitelist) && monitor.whitelist.length > 0) {
90
+ monitor_service_blacklist = true;
91
+ if (monitor.whitelist.includes(req.soajs.controller.serviceParams.name)) {
92
+ monitor_service_blacklist = false;
93
+ }
117
94
  }
95
+ }
96
+ if (monitor && !monitor_service_blacklist) {
97
+ monitoObj.name = req.soajs.controller.serviceParams.name;
98
+ monitoObj.version = req.soajs.controller.serviceParams.version;
99
+ monitoObj.api = req.soajs.controller.serviceParams.parsedUrl.pathname;
100
+ monitoObj.method = req.method;
101
+ monitoObj.time.req_start = new Date().getTime();
102
+ }
103
+ if (monitor && !monitor_service_blacklist && monitor.req_info) {
104
+ monitoObj.port = req.soajs.controller.serviceParams.registry.port;
105
+ monitoObj.url = req.soajs.controller.serviceParams.url;
106
+ monitoObj.host = req.host;
107
+ }
108
+ if (monitor && !monitor_service_blacklist && monitor.req_header) {
109
+ monitoObj.headers = req.headers;
110
+ }
111
+ if (monitor && !monitor_service_blacklist && monitor.req_query) {
112
+ monitoObj.query = req.query;
113
+ }
118
114
 
119
- // Trigger request
120
- req.soajs.controller.redirectedRequest = request(requestOptions);
121
-
122
- // Handle error event for both with monitor and without monitor
123
- req.soajs.controller.redirectedRequest.on('error', (err) => {
124
- req.soajs.log.error(err.message + ' with [' + restServiceParams.name + (restServiceParams.version ? ('@' + restServiceParams.version) : '') + ']');
125
- if (req.soajs.controller.redirectedRequest) {
126
- req.soajs.controller.redirectedRequest.destroy();
127
- req.soajs.controller.redirectedRequest = null;
128
- }
129
- if (!req.soajs.controller.monitorEndingReq) {
130
- req.soajs.controllerResponse(core.error.getError(135));
115
+ if (monitor && !monitor_service_blacklist && monitor.req_body &&
116
+ (req.method === 'POST' || req.method === 'PUT' || req.method === 'PATCH' || req.method === 'DELETE')) {
117
+ let allowedContentType = false;
118
+ let isStream = false;
119
+ req.on("data", (chunk) => {
120
+ let resContentType = req.headers['content-type'];
121
+ if (resContentType) {
122
+ if (!allowedContentType) {
123
+ allowedContentType = resContentType.match(/application\/json|text\/plain/i);
124
+ }
125
+ if (!isStream) {
126
+ isStream = resContentType.match(/stream/i);
127
+ }
131
128
  }
132
- if (monitor && !monitor_service_blacklist && monitor.req_response) {
133
- monitoObj.time.res_end = new Date().getTime();
134
- log_monitor(monitoObj);
129
+ if (!isStream && allowedContentType) {
130
+ if (!monitoObj.body) {
131
+ monitoObj.time.req_body_start = new Date().getTime();
132
+ monitoObj.body = chunk;
133
+ } else {
134
+ monitoObj.body += chunk;
135
+ }
136
+ } else {
137
+ monitoObj.body = "{\"contentType\": \"is stream or not allowed\", \"value': \"" + resContentType + "\"}";
135
138
  }
136
139
  });
137
- //Handle body
138
- if (req.method === 'POST' || req.method === 'PUT' || req.method === 'PATCH' || req.method === 'DELETE') {
139
- if (monitor && !monitor_service_blacklist && monitor.req_body) {
140
- let allowedContentType = false;
141
- let isStream = false;
142
- req.on("data", (chunk) => {
143
- req.soajs.controller.redirectedRequest.write(chunk);
144
- let resContentType = req.headers['content-type'];
145
- if (resContentType) {
146
- if (!allowedContentType) {
147
- allowedContentType = resContentType.match(/application\/json|text\/plain/i);
148
- }
149
- if (!isStream) {
150
- isStream = resContentType.match(/stream/i);
151
- }
152
- }
153
- if (!isStream && allowedContentType) {
154
- if (!monitoObj.body) {
155
- monitoObj.time.req_body_start = new Date().getTime();
156
- monitoObj.body = chunk;
157
- } else {
158
- monitoObj.body += chunk;
159
- }
160
- } else {
161
- monitoObj.body = "{\"contentType\": \"is stream or not allowed\", \"value': \"" + resContentType + "\"}";
162
- }
163
- });
164
- req.on("end", () => {
165
- let resContentType = req.headers['content-length'];
166
- if (resContentType) {
167
- if (!allowedContentType) {
168
- allowedContentType = resContentType.match(/application\/json|text\/plain/i);
169
- }
170
- if (!isStream) {
171
- isStream = resContentType.match(/stream/i);
172
- }
173
- }
174
- if (!isStream) {
175
- if (req.soajs.controller.redirectedRequest) {
176
- req.soajs.controller.redirectedRequest.end();
177
- }
178
- }
179
- if (!isStream && allowedContentType) {
180
- monitoObj.time.req_body_end = new Date().getTime();
181
- }
182
- });
183
- } else {
184
- req.pipe(req.soajs.controller.redirectedRequest);
140
+ req.on("end", () => {
141
+ let resContentType = req.headers['content-length'];
142
+ if (resContentType) {
143
+ if (!allowedContentType) {
144
+ allowedContentType = resContentType.match(/application\/json|text\/plain/i);
145
+ }
146
+ if (!isStream) {
147
+ isStream = resContentType.match(/stream/i);
148
+ }
185
149
  }
150
+ if (!isStream && allowedContentType) {
151
+ monitoObj.time.req_body_end = new Date().getTime();
152
+ }
153
+ });
154
+ }
155
+
156
+ let restServiceParams = req.soajs.controller.serviceParams;
157
+ let requestOptions = {};
158
+ try {
159
+ const urlObj = new URL(obj.uri);
160
+ requestOptions = {
161
+ "hostname": urlObj.hostname,
162
+ "port": urlObj.port,
163
+ "path": urlObj.pathname + urlObj.search,
164
+ "method": req.method.toUpperCase(),
165
+ 'headers': req.headers
166
+ };
167
+ if (obj.config.authorization) {
168
+ isRequestAuthorized(req, core, requestOptions);
186
169
  }
187
- // Handle response
188
- if (monitor && !monitor_service_blacklist && monitor.req_response) {
189
- let allowedContentType = false;
190
- let isStream = false;
191
- req.soajs.controller.redirectedRequest.on("response", (response) => {
192
- if (!res.headersSent) {
193
- res.writeHeader(response.statusCode, response.headers);
194
- }
195
- monitoObj.time.res_start = new Date().getTime();
196
- });
197
- req.soajs.controller.redirectedRequest.on("data", (chunk) => {
198
- res.write(chunk);
199
- let resContentType = res.getHeader('content-type');
170
+ } catch (e) {
171
+ req.soajs.log.error(e.message + ' @catch with [' + restServiceParams.name + (restServiceParams.version ? ('@' + restServiceParams.version) : '') + ']');
172
+ if (!req.soajs.controller.monitorEndingReq) {
173
+ return req.soajs.controllerResponse(core.error.getError(135));
174
+ }
175
+ }
176
+
177
+ let allowedContentType = false;
178
+ let isStream = false;
179
+ let resContentType = "";
180
+ const extraOptions = {};
181
+
182
+ if (monitor && !monitor_service_blacklist && monitor.req_response) {
183
+ extraOptions.events = {
184
+ "response": (_resContentType) => {
185
+ resContentType = _resContentType;
200
186
  if (resContentType) {
201
187
  if (!allowedContentType) {
202
188
  allowedContentType = resContentType.match(/application\/json|text\/plain/i);
@@ -205,6 +191,9 @@ module.exports = (configuration) => {
205
191
  isStream = resContentType.match(/stream/i);
206
192
  }
207
193
  }
194
+ monitoObj.time.res_start = new Date().getTime();
195
+ },
196
+ "data": (chunk) => {
208
197
  if (!isStream && allowedContentType) {
209
198
  if (!monitoObj.response) {
210
199
  monitoObj.response = chunk;
@@ -214,41 +203,34 @@ module.exports = (configuration) => {
214
203
  } else {
215
204
  monitoObj.response = "{\"contentType\": \"is stream or not allowed\", \"value': \"" + resContentType + "\"}";
216
205
  }
217
- });
218
- req.soajs.controller.redirectedRequest.on("end", () => {
219
- let resContentType = res.getHeader('content-type');
220
- if (resContentType) {
221
- if (!isStream) {
222
- isStream = resContentType.match(/stream/i);
223
- }
224
- }
225
- if (!isStream) {
226
- res.end();
227
- }
206
+ },
207
+ "fetchProxReq": (proxyReq) => {
208
+ req.soajs.controller.redirectedRequest = proxyReq;
209
+ }
210
+ };
211
+ }
212
+
213
+ proxyRequestMonitor(req, res, requestOptions, extraOptions)
214
+ .then(() => {
215
+ if (monitor && !monitor_service_blacklist && monitor.req_response) {
228
216
  monitoObj.time.res_end = new Date().getTime();
229
217
  log_monitor(monitoObj);
230
- });
231
- req.soajs.controller.redirectedRequest.on("abort", () => {
232
- if (!req.soajs.controller.monitorEndingReq) {
233
- req.soajs.controllerResponse(core.error.getError(135));
234
- }
218
+ }
219
+ })
220
+ .catch((err) => {
221
+ req.soajs.log.error(err.message + ' with [' + restServiceParams.name + (restServiceParams.version ? ('@' + restServiceParams.version) : '') + ']');
222
+ // if (req.soajs.controller.redirectedRequest) {
223
+ // req.soajs.controller.redirectedRequest.destroy();
224
+ // req.soajs.controller.redirectedRequest = null;
225
+ // }
226
+ if (!req.soajs.controller.monitorEndingReq) {
227
+ req.soajs.controllerResponse(core.error.getError(135));
228
+ }
229
+ if (monitor && !monitor_service_blacklist && monitor.req_response) {
235
230
  monitoObj.time.res_end = new Date().getTime();
236
231
  log_monitor(monitoObj);
237
- });
238
- } else {
239
- req.soajs.controller.redirectedRequest.pipe(res);
240
- }
241
-
242
- } catch (e) {
243
- req.soajs.log.error(e.message + ' @catch with [' + restServiceParams.name + (restServiceParams.version ? ('@' + restServiceParams.version) : '') + ']');
244
- if (req.soajs.controller.redirectedRequest) {
245
- req.soajs.controller.redirectedRequest.destroy();
246
- req.soajs.controller.redirectedRequest = null;
247
- }
248
- if (!req.soajs.controller.monitorEndingReq) {
249
- return req.soajs.controllerResponse(core.error.getError(135));
250
- }
251
- }
232
+ }
233
+ });
252
234
  });
253
235
  };
254
236
  };
@@ -8,15 +8,16 @@
8
8
  * found in the LICENSE file at the root of this repository
9
9
  */
10
10
 
11
- const url = require('url');
12
- let http = require('http');
11
+ // const url = require('url');
12
+ // let http = require('http');
13
+ const { proxyRequest } = require("../../lib/request.js");
13
14
 
14
15
  module.exports = (configuration) => {
15
-
16
+
16
17
  let core = configuration.core;
17
18
  let isRequestAuthorized = require("./lib/isRequestAuthorized.js");
18
19
  let preRedirect = require("./lib/preRedirect.js");
19
-
20
+
20
21
  /**
21
22
  *
22
23
  * @param req
@@ -25,48 +26,48 @@ module.exports = (configuration) => {
25
26
  */
26
27
  return (req, res) => {
27
28
  preRedirect(req, res, core, function (obj) {
28
- // req.pause();
29
-
30
- let requestOptions = url.parse(obj.uri);
31
- requestOptions.headers = req.headers;
32
- requestOptions.method = req.method;
33
- requestOptions.agent = false;
34
- requestOptions.headers.host = requestOptions.host;
35
-
36
- if (obj.config.authorization) {
37
- isRequestAuthorized(req, core, requestOptions);
38
- }
29
+ let requestConfig = {};
39
30
  try {
40
- req.soajs.controller.redirectedRequest = http.request(requestOptions, function (serverResponse) {
41
- serverResponse.pause();
42
- serverResponse.headers['access-control-allow-origin'] = '*';
43
-
44
- res.writeHeader(serverResponse.statusCode, serverResponse.headers);
45
- serverResponse.pipe(res, {end: true});
46
- serverResponse.resume();
47
- });
48
- req.soajs.controller.redirectedRequest.on('error', function (err) {
49
- req.soajs.log.error(err.code, err.message);
50
- if (req.soajs.controller.redirectedRequest) {
51
- req.soajs.controller.redirectedRequest.destroy();
52
- req.soajs.controller.redirectedRequest = null;
53
- }
54
- if (!req.soajs.controller.monitorEndingReq) {
55
- return req.soajs.controllerResponse(core.error.getError(135));
56
- }
57
- });
58
- req.pipe(req.soajs.controller.redirectedRequest, {end: true});
59
- // req.resume();
31
+ const urlObj = new URL(obj.uri);
32
+ requestConfig = {
33
+ "hostname": urlObj.hostname,
34
+ "port": urlObj.port,
35
+ "path": urlObj.pathname + urlObj.search,
36
+ "method": req.method.toUpperCase(),
37
+ 'headers': req.headers
38
+ };
39
+ requestConfig.headers.host = urlObj.hostname;
40
+ if (obj.config.authorization) {
41
+ isRequestAuthorized(req, core, requestConfig);
42
+ }
60
43
  } catch (e) {
61
44
  req.soajs.log.error(e.message + " @catch");
62
- if (req.soajs.controller.redirectedRequest) {
63
- req.soajs.controller.redirectedRequest.destroy();
64
- req.soajs.controller.redirectedRequest = null;
65
- }
66
45
  if (!req.soajs.controller.monitorEndingReq) {
67
46
  return req.soajs.controllerResponse(core.error.getError(135));
68
47
  }
69
48
  }
49
+ const extraOptions = {
50
+ "resHEaders": {
51
+ "access-control-allow-origin": "*"
52
+ },
53
+ "fetchProxReq": (proxyReq) => {
54
+ req.soajs.controller.redirectedRequest = proxyReq;
55
+ }
56
+ };
57
+
58
+ proxyRequest(req, res, requestConfig, extraOptions)
59
+ .then(() => {
60
+ })
61
+ .catch((err) => {
62
+ req.soajs.log.error(err.code, err.message);
63
+ // if (req.soajs.controller.redirectedRequest) {
64
+ // req.soajs.controller.redirectedRequest.destroy();
65
+ // req.soajs.controller.redirectedRequest = null;
66
+ // }
67
+ if (!req.soajs.controller.monitorEndingReq) {
68
+ return req.soajs.controllerResponse(core.error.getError(135));
69
+ }
70
+ });
70
71
  });
71
72
  };
72
73
  };
@@ -8,7 +8,7 @@
8
8
  * found in the LICENSE file at the root of this repository
9
9
  */
10
10
 
11
- const request = require("request");
11
+ const { httpRequest } = require("../../lib/request.js");
12
12
  const get = (p, o) => p.reduce((xs, x) => (xs && xs[x]) ? xs[x] : null, o);
13
13
 
14
14
  /**
@@ -45,32 +45,62 @@ module.exports = () => {
45
45
  item.port = req.soajs.registry.services[item.name].port;
46
46
 
47
47
  let options = {
48
- method: "post",
49
- uri: "http://" + item.host + ":" + item.port + item.api,
50
- json: true
48
+ "uri": "http://" + item.host + ":" + item.port + item.api,
49
+ "json": true,
50
+ "method": "POST"
51
51
  };
52
52
  if (req.headers && req.headers.soajsinjectobj) {
53
53
  options.headers = { "soajsinjectobj": req.headers.soajsinjectobj };
54
54
  }
55
- request(options, (error, response, body) => {
56
- if (error) {
57
- req.soajs.log.debug("lastSeen failed for [" + item.name + "@" + item.version + " " + item.api + "]");
58
- req.soajs.log.error("lastSeen " + error.message);
59
- } else if (!body.result) {
60
- let errorMsg = "";
61
- if (body.errors && body.errors && body.errors.details && body.errors.details.length > 0) {
62
- body.errors.details.forEach((detail) => {
63
- if (errorMsg === "") {
64
- errorMsg += detail.message;
65
- }
66
- else {
67
- errorMsg += " - " + detail.message;
68
- }
69
- });
55
+ httpRequest(options)
56
+ .then(() => { })
57
+ .catch(({ error, body }) => {
58
+ if (error) {
59
+ req.soajs.log.debug("lastSeen failed for [" + item.name + "@" + item.version + " " + item.api + "]");
60
+ req.soajs.log.debug("lastSeen " + error.message);
61
+ } else if (!body.result) {
62
+ let errorMsg = "";
63
+ if (body.errors && body.errors && body.errors.details && body.errors.details.length > 0) {
64
+ body.errors.details.forEach((detail) => {
65
+ if (errorMsg === "") {
66
+ errorMsg += detail.message;
67
+ }
68
+ else {
69
+ errorMsg += " - " + detail.message;
70
+ }
71
+ });
72
+ }
73
+ req.soajs.log.debug("lastSeen", errorMsg);
70
74
  }
71
- req.soajs.log.error("lastSeen", errorMsg);
72
- }
73
- });
75
+ });
76
+
77
+ // let options = {
78
+ // method: "post",
79
+ // uri: "http://" + item.host + ":" + item.port + item.api,
80
+ // json: true
81
+ // };
82
+ // if (req.headers && req.headers.soajsinjectobj) {
83
+ // options.headers = { "soajsinjectobj": req.headers.soajsinjectobj };
84
+ // }
85
+ // request(options, (error, response, body) => {
86
+ // if (error) {
87
+ // req.soajs.log.debug("lastSeen failed for [" + item.name + "@" + item.version + " " + item.api + "]");
88
+ // req.soajs.log.debug("lastSeen " + error.message);
89
+ // } else if (!body.result) {
90
+ // let errorMsg = "";
91
+ // if (body.errors && body.errors && body.errors.details && body.errors.details.length > 0) {
92
+ // body.errors.details.forEach((detail) => {
93
+ // if (errorMsg === "") {
94
+ // errorMsg += detail.message;
95
+ // }
96
+ // else {
97
+ // errorMsg += " - " + detail.message;
98
+ // }
99
+ // });
100
+ // }
101
+ // req.soajs.log.debug("lastSeen", errorMsg);
102
+ // }
103
+ // });
74
104
  } else {
75
105
  req.soajs.log.debug("lastSeen failed with no host for [" + item.name + "@" + item.version + " " + item.api + "]");
76
106
  }