@aj-shadow/z-abs-corelayer-server 0.0.0-aj-beta.221

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.
Files changed (87) hide show
  1. package/.gitattributes +26 -0
  2. package/LICENSE.txt +96 -0
  3. package/README.md +5 -0
  4. package/npm-shrinkwrap.json +13 -0
  5. package/package.json +10 -0
  6. package/project/server/_build/Server-CoreLayer-server.bld +12 -0
  7. package/project/server/_build/z-abs-corelayer-server.prj +12 -0
  8. package/project/server/communication/core-protocol/decoder.js +404 -0
  9. package/project/server/communication/core-protocol/encoder.js +503 -0
  10. package/project/server/communication/messages/messages-s-to-c/message-persistent-init-response.js +14 -0
  11. package/project/server/communication/messages/messages-s-to-c/message-persistent-publish.js +16 -0
  12. package/project/server/communication/messages/messages-s-to-c/message-ws-init.js +14 -0
  13. package/project/server/communication/messages/messages-s-to-s/service-init-request.js +17 -0
  14. package/project/server/communication/messages/messages-s-to-s/service-init-response.js +18 -0
  15. package/project/server/communication/messages/messages-s-to-s/service-offer-off.js +15 -0
  16. package/project/server/communication/messages/messages-s-to-s/service-offer-on.js +15 -0
  17. package/project/server/communication/messages/messages-s-to-s/worker-init-request.js +15 -0
  18. package/project/server/data-response.js +588 -0
  19. package/project/server/high-resolution-timestamp.js +36 -0
  20. package/project/server/log/log-config.js +107 -0
  21. package/project/server/log/log-types.js +14 -0
  22. package/project/server/log/logger-console.js +36 -0
  23. package/project/server/log/logger.js +114 -0
  24. package/project/server/node/channel-input.js +65 -0
  25. package/project/server/node/channel-output.js +39 -0
  26. package/project/server/node/clients.js +80 -0
  27. package/project/server/node/connection-address.js +24 -0
  28. package/project/server/node/connection-data-ip.js +82 -0
  29. package/project/server/node/connection-data.js +25 -0
  30. package/project/server/node/const.js +44 -0
  31. package/project/server/node/external-services.js +209 -0
  32. package/project/server/node/http-cache.js +109 -0
  33. package/project/server/node/http-proxy.js +97 -0
  34. package/project/server/node/http-request-handler.js +219 -0
  35. package/project/server/node/http-server.js +36 -0
  36. package/project/server/node/http2-server.js +67 -0
  37. package/project/server/node/https-server.js +63 -0
  38. package/project/server/node/ip-client.js +98 -0
  39. package/project/server/node/ip-server.js +63 -0
  40. package/project/server/node/ip-subscription.js +46 -0
  41. package/project/server/node/message-channel.js +98 -0
  42. package/project/server/node/node-admin.js +513 -0
  43. package/project/server/node/node-data.js +25 -0
  44. package/project/server/node/node-settings.js +352 -0
  45. package/project/server/node/node-worker.js +76 -0
  46. package/project/server/node/node.js +156 -0
  47. package/project/server/node/servers.js +168 -0
  48. package/project/server/node/ws-client.js +12 -0
  49. package/project/server/node/ws-server.js +20 -0
  50. package/project/server/node/ws-web-server.js +52 -0
  51. package/project/server/node/wss-server.js +20 -0
  52. package/project/server/node/wss-web-server.js +82 -0
  53. package/project/server/path/actor-path-build.js +29 -0
  54. package/project/server/path/actor-path-content.js +51 -0
  55. package/project/server/path/actor-path-creator.js +90 -0
  56. package/project/server/path/actor-path-data.js +487 -0
  57. package/project/server/path/actor-path-dist.js +132 -0
  58. package/project/server/path/actor-path-generated.js +202 -0
  59. package/project/server/path/actor-path-project.js +181 -0
  60. package/project/server/path/actor-path.js +57 -0
  61. package/project/server/path/paths/actor-content-paths.js +34 -0
  62. package/project/server/path/paths/actor-data-paths.js +302 -0
  63. package/project/server/path/paths/actor-generated-paths.js +99 -0
  64. package/project/server/path/paths/actor-paths.js +22 -0
  65. package/project/server/plugin-base-multi.js +484 -0
  66. package/project/server/plugin-base.js +233 -0
  67. package/project/server/plugin-component.js +92 -0
  68. package/project/server/plugin-data/client/plugin_data_ClientGet.js +18 -0
  69. package/project/server/plugin-data/dialog-file/plugin_data_DialogFileGet.js +197 -0
  70. package/project/server/plugin-data/platform/plugin_data_PlatformPing.js +19 -0
  71. package/project/server/plugin-factor-protocol.js +35 -0
  72. package/project/server/plugin-factory.js +127 -0
  73. package/project/server/plugin-lock.js +164 -0
  74. package/project/server/response-queue.js +46 -0
  75. package/project/server/responses.js +20 -0
  76. package/project/server/service/plugin-service.js +264 -0
  77. package/project/server/service/service-export.js +47 -0
  78. package/project/server/service/service-manager.js +270 -0
  79. package/project/server/service/service-requests.js +49 -0
  80. package/project/server/session-cache.js +39 -0
  81. package/project/server/session.js +23 -0
  82. package/project/server/worker/worker-channel.js +175 -0
  83. package/project/server/worker/worker-core.js +58 -0
  84. package/project/server/worker/worker-main.js +165 -0
  85. package/project/server/worker/worker-pool.js +94 -0
  86. package/project/server/worker/worker-thread.js +128 -0
  87. package/project/z-abs-corelayer-server.tree +99 -0
@@ -0,0 +1,209 @@
1
+
2
+ 'use strict';
3
+
4
+ const Const = require('./const');
5
+
6
+
7
+ class ExternalServices {
8
+ static emptyMap = new Map();
9
+ static NODE = ddb.cyan('Node: ');
10
+
11
+ constructor() {
12
+ this.nodes = new Map();
13
+ this.services = new Map();
14
+ this.dependencyNodeNames = new Set();
15
+ this.eventListeners = new Map();
16
+ }
17
+
18
+ addDependencyNodeNames(dependencyNodeNames) {
19
+ this.dependencyNodeNames = new Set([...dependencyNodeNames]);
20
+ }
21
+
22
+ _hasNode(nodeName) {
23
+ for(let [symbol, node] of this.nodes) {
24
+ if(nodeName === node.nodeName) {
25
+ return true;
26
+ }
27
+ }
28
+ return false;
29
+ }
30
+
31
+ getOfferData(nodeName, nodeSymbol) {
32
+ let offer = true;
33
+ let isDependent = this.dependencyNodeNames.has(nodeName);
34
+ const dependencies = this.dependencyNodeNames.size;
35
+ let connectedDependencies = 0;
36
+ if(isDependent) {
37
+ this.dependencyNodeNames.forEach((dependencyNodeName) => {
38
+ if(this._hasNode(dependencyNodeName)) {
39
+ ++connectedDependencies;
40
+ }
41
+ else {
42
+ offer = false;
43
+ }
44
+ });
45
+ }
46
+ return {
47
+ offer: offer || !isDependent,
48
+ isDependent,
49
+ dependencies,
50
+ connectedDependencies
51
+ };
52
+ }
53
+
54
+ addNode(connectionData) {
55
+ const externalNode = {
56
+ nodeSymbol: connectionData.nodeSymbol,
57
+ nodeName: connectionData.nodeName,
58
+ nodeType: connectionData.nodeType,
59
+ connectionData: connectionData,
60
+ isDependent: this.dependencyNodeNames.has(connectionData.nodeName),
61
+ offered: false,
62
+ serviceExport: null
63
+ };
64
+ this.nodes.set(connectionData.nodeSymbol, externalNode);
65
+ ddb.writelnTime(ExternalServices.NODE, connectionData.nodeName, ddb.yellow('::'), connectionData.nodeId, ddb.green(' connected'));
66
+ return externalNode;
67
+ }
68
+
69
+ deleteNode(connectionData) {
70
+ if(this.nodes.delete(connectionData.nodeSymbol)) {
71
+ ddb.writelnTime(ExternalServices.NODE, connectionData.nodeName, ddb.yellow('::'), connectionData.nodeId, ddb.red(' disconnected'));
72
+ }
73
+ this.offerOff(connectionData);
74
+ }
75
+
76
+ getNodeData(connectionData) {
77
+ return this.nodes.get(connectionData.nodeSymbol);
78
+ }
79
+
80
+ setNodeOffer(connectionData, serviceExport) {
81
+ const nodeData = this.nodes.get(connectionData.nodeSymbol);
82
+ nodeData.serviceExport = serviceExport;
83
+ }
84
+
85
+ offerOn(connectionData, serviceExport) {
86
+ serviceExport.frontendServices.forEach((serviceName) => {
87
+ this._offerOn(serviceName, Const.OFFER_FRONTEND, connectionData);
88
+ });
89
+ serviceExport.backendServices.forEach((serviceName) => {
90
+ this._offerOn(serviceName, Const.OFFER_BACKEND, connectionData);
91
+ });
92
+ serviceExport.surveillanceServices.forEach((serviceName) => {
93
+ this._offerOn(serviceName, Const.OFFER_SURVEILLANCE, connectionData);
94
+ });
95
+ }
96
+
97
+ offerOff(connectionData) {
98
+ connectionData.frontendServices.forEach((serviceName) => {
99
+ this._offerOff(serviceName, connectionData);
100
+ });
101
+ connectionData.backendServices.forEach((serviceName) => {
102
+ this._offerOff(serviceName, connectionData);
103
+ });
104
+ connectionData.surveillanceServices.forEach((serviceName) => {
105
+ this._offerOff(serviceName, connectionData);
106
+ });
107
+ }
108
+
109
+ _offerOn(serviceName, offerType, connectionData) {
110
+ const externalService = this.services.get(serviceName);
111
+ if(!externalService) {
112
+ connectionData.addService(serviceName, offerType);
113
+ this.services.set(serviceName, new Map([[connectionData.id, {connectionData , instances: 1}]]));
114
+ ddb.writelnTime(ExternalServices.NODE, connectionData.nodeName, ddb.yellow('::'), connectionData.nodeId, ddb.yellow(' offer '), ddb.cyan(serviceName), ddb.green(' on'), ddb.yellow(' id: '), connectionData.id, ', instances: ', ddb.yellow(1));
115
+ }
116
+ else {
117
+ let externalConnectionData = null;
118
+ if(externalService.has(connectionData.id)) {
119
+ externalConnectionData = externalService.get(connectionData.id);
120
+ ++externalConnectionData.instances;
121
+ }
122
+ else {
123
+ connectionData.addService(serviceName, offerType);
124
+ externalConnectionData = {connectionData , instances: 1};
125
+ externalService.set(connectionData.id, externalConnectionData);
126
+ }
127
+ ddb.writelnTime(ExternalServices.NODE, connectionData.nodeName, ddb.yellow('::'), connectionData.nodeId, ddb.yellow(' offer '), ddb.cyan(serviceName), ddb.green(' on'), ddb.yellow(' id: '), connectionData.id, ', instances: ', ddb.yellow(externalConnectionData.instances));
128
+ }
129
+ const serviceListeners = this.eventListeners.get(serviceName);
130
+ if(serviceListeners) {
131
+ serviceListeners.forEach((cb) => {
132
+ process.nextTick(cb, connectionData, true);
133
+ });
134
+ }
135
+ }
136
+
137
+ _offerOff(serviceName, connectionData) {
138
+ const externalService = this.services.get(serviceName);
139
+ if(externalService) {
140
+ const externalConnectionData = externalService.get(connectionData.id);
141
+ if(externalConnectionData) {
142
+ if(0 === --externalConnectionData.instances) {
143
+ connectionData.deleteService(serviceName);
144
+ externalService.delete(connectionData.id);
145
+ if(0 === externalService.size) {
146
+ this.services.delete(serviceName, connectionData.nodeType);
147
+ }
148
+ const serviceListeners = this.eventListeners.get(serviceName);
149
+ if(serviceListeners) {
150
+ serviceListeners.forEach((cb) => {
151
+ process.nextTick(cb, connectionData, false);
152
+ });
153
+ }
154
+ }
155
+ ddb.writelnTime(ExternalServices.NODE, connectionData.nodeName, ddb.yellow('::'), connectionData.nodeId, ddb.yellow(' offer '), ddb.cyan(serviceName), ddb.red(' off'), ddb.yellow(' id: '), connectionData.id, ', instances: ', ddb.yellow(externalConnectionData.instances));
156
+ }
157
+ else {
158
+ ddb.writelnTime(ExternalServices.NODE, connectionData.nodeName, ddb.yellow('::'), connectionData.nodeId, ddb.red(' Service: '), ddb.cyan(serviceName), ddb.yellow(' id: '), connectionData.id, ddb.red(' not removed, it does not exist!'));
159
+ }
160
+ }
161
+ else {
162
+ ddb.writelnTime(ExternalServices.NODE, connectionData.nodeName, ddb.yellow('::'), connectionData.nodeId, ddb.red(' Service: '), ddb.cyan(serviceName), ddb.yellow(' not removed, it does not exist!'));
163
+ }
164
+ }
165
+
166
+ getServices() {
167
+ if(0 !== this.services.size) {
168
+ return [...this.services.keys()];
169
+ }
170
+ else {
171
+ return [];
172
+ }
173
+ }
174
+
175
+ /*has(serviceName) {
176
+ return this.services.has(serviceName);
177
+ }*/
178
+
179
+ getConnectionData(serviceName) {
180
+ const externalService = this.services.get(serviceName);
181
+ if(externalService) {
182
+ // ROUND - ROBIN
183
+ const externalConnectionData = externalService.entries().next().value[1];
184
+ if(1 <= externalService.size) {
185
+ externalService.delete(externalConnectionData.connectionData.id);
186
+ externalService.set(externalConnectionData.connectionData.id, externalConnectionData);
187
+ }
188
+ return externalConnectionData.connectionData;
189
+ }
190
+ else {
191
+ return null;
192
+ }
193
+ }
194
+
195
+ on(serviceName, pluginService, cb) {
196
+ let serviceListeners = this.eventListeners.get(serviceName);
197
+ if(!serviceListeners) {
198
+ serviceListeners = new Map();
199
+ this.eventListeners.set(serviceName, serviceListeners);
200
+ }
201
+ serviceListeners.set(pluginService, cb);
202
+ if(this.services.has(serviceName)) {
203
+ cb();
204
+ }
205
+ }
206
+ }
207
+
208
+
209
+ module.exports = ExternalServices;
@@ -0,0 +1,109 @@
1
+
2
+ 'use strict';
3
+
4
+ const GuidGenerator = require('z-abs-corelayer-cs/clientServer/guid-generator');
5
+ const MimeTypes = require('mime-types');
6
+ const Fs = require('fs');
7
+ const Path = require('path');
8
+
9
+
10
+ class HttpCache {
11
+ constructor() {
12
+ this.pathsArray = [];
13
+ this.cacheContent = new Map();
14
+ this.watchPaths = new Set();
15
+ }
16
+
17
+ setPaths(watchPaths) {
18
+ this.pathsArray.push(watchPaths);
19
+ watchPaths.forEach((watchPath) => {
20
+ if(!this.watchPaths.has(watchPath)) {
21
+ Fs.watch(watchPath, {persistent: false, recursive: true}, (eventType, filename) => {
22
+ if(filename && 'change' === eventType) {
23
+ const file = `${watchPath}/${filename.replace(/\\/g, '/')}`;
24
+ this.cacheContent.delete(file);
25
+ }
26
+ });
27
+ this.watchPaths.add(watchPath);
28
+ }
29
+ });
30
+ return this.pathsArray.length - 1;
31
+ }
32
+
33
+ get(pathIndex, req, file, compressed, cb) {
34
+ const paths = this.pathsArray[pathIndex];
35
+ if(0 == paths.length) {
36
+ cb(false, null);
37
+ }
38
+ else {
39
+ const pragma = req.headers['pragma'];
40
+ if('no-cache' === pragma) {
41
+ this.cacheContent.delete(file);
42
+ }
43
+ this._getContent(req, file, paths, compressed, (data) => {
44
+ if(!data) {
45
+ cb(true, null);
46
+ return;
47
+ }
48
+ const ifNoneMatch = req.headers['if-none-match'];
49
+ if(ifNoneMatch === data.eTag) {
50
+ cb(false, data);
51
+ return;
52
+ }
53
+ const ifModifiedSince = req.headers['if-modified-since'];
54
+ if(ifModifiedSince === data.lastModified) {
55
+ cb(false, data);
56
+ return;
57
+ }
58
+ cb(true, data);
59
+ });
60
+ }
61
+ }
62
+
63
+ _readFile(file, paths, compressed, cb) {
64
+ let found = false;
65
+ let index = 0;
66
+ let pendings = paths.length;
67
+ while(!found && index < paths.length) {
68
+ const fileAndPath = `${paths[index++]}${file}${compressed ? '.gzip' : ''}`;
69
+ Fs.readFile(fileAndPath, (err, data) => {
70
+ if(!err) {
71
+ if(!found) {
72
+ found = true;
73
+ const foundContent = {
74
+ content: data,
75
+ contentLength: Buffer.byteLength(data),
76
+ mimeType: MimeTypes.lookup(file),
77
+ lastModified: new Date().toUTCString(),
78
+ eTag: `W/"${GuidGenerator.create()}"`
79
+ };
80
+ this.cacheContent.set(file, foundContent);
81
+ cb(foundContent);
82
+ }
83
+ --pendings;
84
+ }
85
+ else {
86
+ if(0 === --pendings) {
87
+ if(!found) {
88
+ cb(null);
89
+ }
90
+ }
91
+ }
92
+ });
93
+ }
94
+ }
95
+
96
+ _getContent(req, file, paths, compressed, cb) {
97
+ const range = req.headers['range'];
98
+ const content = this.cacheContent.get(file);
99
+ if(content) {
100
+ cb(content);
101
+ }
102
+ else {
103
+ this._readFile(file, paths, compressed, cb);
104
+ }
105
+ }
106
+ }
107
+
108
+
109
+ module.exports = HttpCache;
@@ -0,0 +1,97 @@
1
+
2
+ 'use strict';
3
+
4
+ const http = require('http');
5
+
6
+ class HttpProxy {
7
+ constructor() {
8
+
9
+ }
10
+
11
+ init(httpData, tls) {}
12
+
13
+ handle(req, res) {
14
+ let reqUrl = '';
15
+ if(req.url.startsWith('/http')) {
16
+ reqUrl = req.url.substring(1).replaceAll('%3A', ':');
17
+ reqUrl = reqUrl.replaceAll('%2E', '.');
18
+ }
19
+ else {
20
+ reqUrl = req.url;
21
+ }
22
+ console.log('reqUrl:', reqUrl);
23
+ const url = new URL(reqUrl);
24
+ const httpAgent = new http.Agent({keepAlive:true});
25
+ const options = {
26
+ hostname: url.hostname,
27
+ port: url.port,
28
+ path: req.path,
29
+ method: req.method,
30
+ headers: {...req.headers, connection:'keep-alive'}//,
31
+ // agent: httpAgent
32
+ };
33
+ Reflect.set(options.headers, 'host', url.hostname);
34
+ // Reflect.set(options.headers, 'referer', `http://${url.hostname}`);
35
+
36
+ this.sendRequest(req, res, options);
37
+ }
38
+
39
+ sendRequest(req, res, options) {
40
+ console.log('****', options.hostname);
41
+ console.log('****', options.port);
42
+ console.log('****', options.path);
43
+ console.log('****', options.method);
44
+ console.log('****', options.headers);
45
+ const proxy = http.request(options, (proxyRes) => {
46
+ //console.log(proxyRes);
47
+ /*const headers = { ...proxyRes.headers, connection: 'keep-alive' };
48
+ res.writeHead(proxyRes.statusCode, headers);
49
+ //proxyRes.pipe(res, { end: true });*/
50
+ let body = '';
51
+
52
+ // Collect the response data
53
+ proxyRes.on('data', (chunk) => {
54
+ console.log('************************************************** data');
55
+ body += chunk;
56
+ console.log(chunk.toString());
57
+ });
58
+
59
+ // Modify the response data and send it back to the client
60
+ proxyRes.on('end', () => {
61
+ console.log('************************************************** end');
62
+ // Modify the body here
63
+ // body = body.replace('original text', 'modified text');
64
+ console.log(body.toString());
65
+ // Modify response headers if necessary
66
+ const headers = { ...proxyRes.headers, connection: 'keep-alive' }; // Set keep-alive header
67
+ console.log('#####', proxyRes.statusCode)
68
+ if(200 === proxyRes.statusCode) {
69
+ res.writeHead(proxyRes.statusCode, headers);
70
+ res.end(body);
71
+ }
72
+ else if(302 === proxyRes.statusCode) {
73
+ // console.log(proxyRes.headers);
74
+ // console.log(proxyRes.rawHeaders);
75
+ options.path = headers.location;
76
+ this.sendRequest(req, res, options);
77
+ }
78
+ else {
79
+ res.writeHead(proxyRes.statusCode, headers);
80
+ res.end(body);
81
+ }
82
+ });
83
+ });
84
+
85
+ proxy.on('error', (err) => {
86
+ console.log('************************************************** error');
87
+ console.error('Error with proxy:', err);
88
+ res.writeHead(502, { 'Content-Type': 'text/plain' });
89
+ res.end('Bad Gateway');
90
+ });
91
+
92
+ req.pipe(proxy, { end: true });
93
+ }
94
+ }
95
+
96
+
97
+ module.exports = HttpProxy;
@@ -0,0 +1,219 @@
1
+
2
+ 'use strict';
3
+
4
+
5
+ class HttpRequestHandler {
6
+ constructor(httpCache, dataResponse, defaultSite) {
7
+ this.httpCache = httpCache;
8
+ this.dataResponse = dataResponse;
9
+ this.defaultSite = defaultSite.startsWith('/') ? defaultSite : `/${defaultSite}`;
10
+ this.baseUrl = '';
11
+ this.pathId = -1;
12
+ this.authenticationToken = `token-${this.dataResponse.appName}=`
13
+ this.production = 'production' === process.env.NODE_ENV;
14
+ this.content = [
15
+ {
16
+ search: '/assets/',
17
+ route: '',
18
+ remove: ''
19
+ },
20
+ {
21
+ search: '/fonts/',
22
+ route: '',
23
+ remove: '/fonts'
24
+ }
25
+ ];
26
+ }
27
+
28
+ _getToken(cookie) {
29
+ let token = '';
30
+ if(cookie) {
31
+ let startIndex = cookie.indexOf(this.authenticationToken);
32
+ if(-1 !== startIndex) {
33
+ startIndex += this.authenticationToken.length;
34
+ const stopIndex = cookie.indexOf(';', startIndex);
35
+ token = cookie.substring(startIndex, -1 !== stopIndex ? stopIndex : undefined);
36
+ }
37
+ }
38
+ }
39
+
40
+ handle(req, res) {
41
+ //console.log('############################################');
42
+ //console.log(req.url, {...req.headers});
43
+ //console.log('############################################');
44
+ const myURL = new URL(req.url, this.baseUrl);
45
+ //console.log(req.url);
46
+ // console.log(req.headers);
47
+ if(myURL.pathname.startsWith('/abs-data/')) {
48
+ try {
49
+ if(req.method == 'POST') {
50
+ const rawBody = [];
51
+ req.on('data', (chunk) => {
52
+ rawBody.push(chunk);
53
+ });
54
+ req.on('end', () => {
55
+ const token = this._getToken(req.headers.cookie);
56
+ const requestObject = this._safeJsonParse(Buffer.concat(rawBody).toString());
57
+ if(null !== requestObject) {
58
+ this.dataResponse.handleRequests(requestObject, token, null, (response, dataBuffers, debug, token) => {
59
+ if(!token) {
60
+ this.jsonResponseHttp(res, JSON.stringify(response));
61
+ }
62
+ else {
63
+ this.jsonLoginResponseHttp(res, token, JSON.stringify(response));
64
+ }
65
+ }, (message) => {
66
+ ddb.warning('DROPPED MSG:');
67
+ });
68
+ }
69
+ else {
70
+ ddb.error('BAD REQ:');
71
+ res.writeHead(400, 'Bad Request', {'Content-Length': '0'});
72
+ res.end();
73
+ }
74
+ });
75
+ return;
76
+ }
77
+ }
78
+ catch(err) {
79
+ ddb.error(err);
80
+ this.notFound(res);
81
+ return;
82
+ }
83
+ this.notImplementedServerError(res);
84
+ }
85
+ else if(myURL.pathname.startsWith('/abs-scripts/')) {
86
+ this.contentResponse(req, res, `/${myURL.pathname.substring('/abs-scripts/'.length)}`, true);
87
+ }
88
+ else if(myURL.pathname.startsWith('/abs-css/')) {
89
+ this.contentResponse(req, res, `/${myURL.pathname.substring('/abs-css/'.length)}`, true);
90
+ }
91
+ else if(myURL.pathname.startsWith('/abs-images/')) {
92
+ this.contentResponse(req, res, `/${myURL.pathname.substring('/abs-images/'.length)}`);
93
+ }
94
+ else {
95
+ const foundIndex = this.content.findIndex((content) => (-1 != myURL.pathname.indexOf(content.search)));
96
+ if(-1 !== foundIndex) {
97
+ const content = this.content[foundIndex];
98
+ const url = `${content.route}${myURL.pathname.substring(myURL.pathname.indexOf(content.search) + content.remove.length)}`;
99
+ this.contentResponse(req, res, url);
100
+ }
101
+ else if(myURL.pathname === '/favicon.ico') {
102
+ this.contentResponse(req, res, '/svg/ActorJsA.svg');
103
+ }
104
+ else if(myURL.pathname === '/') {
105
+ this.redirect(res, this.defaultSite);
106
+ }
107
+ else if(myURL.pathname.startsWith('/abs-api/')) {
108
+ const rawBody = [];
109
+ req.on('data', (chunk) => {
110
+ rawBody.push(chunk);
111
+ });
112
+ req.on('end', () => {
113
+ const token = this._getToken(req.headers.cookie);
114
+ this.dataResponse._handleRest(req.method, myURL.pathname, req.headers['content-type'], rawBody, token, (statusCode, reasonPhrase, contentType, content) => {
115
+ this.restResponse(res, statusCode, reasonPhrase, contentType, content)
116
+ });
117
+ });
118
+ }
119
+ else {
120
+ this.contentResponse(req, res, '/index.html', false, true);
121
+ }
122
+ }
123
+ }
124
+
125
+ init(data, tls) {
126
+ this.baseUrl = `http${tls ? 's' : ''}://${data.host}:${data.port}`;
127
+ this.domain = data.host;
128
+ this.pathId = this.httpCache.setPaths(data.directories);
129
+ }
130
+
131
+ contentResponse(req, res, file, compressed, forced) {
132
+ const useCompressed = !!compressed && this.production;
133
+ this.httpCache.get(this.pathId, req, file, useCompressed, (modified, data) => {
134
+ if(data) {
135
+ if(modified || forced) {
136
+ res.setHeader('Accept-Ranges', 'bytes');
137
+ res.setHeader('Cache-Control', 'public, max-age=604800');
138
+ res.setHeader('ETag', data.eTag);
139
+ res.setHeader('Content-Type', data.mimeType + '; charset=utf-8');
140
+ res.setHeader('Date', new Date().toUTCString());
141
+ if(useCompressed) {
142
+ res.setHeader('Content-Encoding', 'gzip');
143
+ }
144
+ res.write(data.content);
145
+ res.end();
146
+ }
147
+ else {
148
+ res.writeHead(304, 'Not Modified', {
149
+ 'Cache-Control': 'public, max-age=604800',
150
+ 'ETag': data.eTag,
151
+ 'Date': new Date().toUTCString()
152
+ });
153
+ res.end();
154
+ }
155
+ }
156
+ else {
157
+ ddb.error('not found:', file);
158
+ this.notFound(res);
159
+ }
160
+ });
161
+ }
162
+
163
+ jsonResponseHttp(res, data) {
164
+ res.setHeader('Content-Type', 'application/json; charset=utf-8');
165
+ res.write(data);
166
+ res.end();
167
+ }
168
+
169
+ jsonLoginResponseHttp(res, token, data) {
170
+ res.setHeader('Content-Type', 'application/json; charset=utf-8');
171
+ res.setHeader('Set-Cookie', `${this.authenticationToken}${'-1' === token ? '' : token}; Domain=${this.domain}; Max-Age=${'-1' === token ? '0' : '604800'}; HttpOnly`);
172
+ res.write(data);
173
+ res.end();
174
+ }
175
+
176
+ restResponse(res, statusCode, reasonPhrase, contentType, content) {
177
+ res.writeHead(statusCode, reasonPhrase);
178
+ if(content) {
179
+ res.setHeader('Content-Type', contentType + '; charset=utf-8');
180
+ if('application/json' === contentType) {
181
+ res.write(JSON.stringify(content, null, 2));
182
+ }
183
+ else {
184
+ res.write(content);
185
+ }
186
+ }
187
+ res.end();
188
+ }
189
+
190
+ redirect(res, to) {
191
+ res.writeHead(302, {'Location': to});
192
+ res.end();
193
+ }
194
+
195
+ notImplementedServerError(res) {
196
+ res.writeHead(501, "Not implemented", {'Content-Type': 'text/html; charset=utf-8'});
197
+ res.end(this.errorHtml('501 - Not implemented', '<h1>Not implemented!</h1>'));
198
+ }
199
+
200
+ notFound(res) {
201
+ res.writeHead(404, 'Not Found', {"Content-Type": "text/html; charset=utf-8"});
202
+ res.end(this.errorHtml('404 - Not Found', '<h1>Not Found!</h1>'));
203
+ }
204
+
205
+ errorHtml(title, bodyText) {
206
+ return '<!DOCTYPE html><html lang="en-US"><head><title>' + title + '</title><meta charset="UTF-8"></head><body>' + bodyText + '</body></html>';
207
+ }
208
+
209
+ _safeJsonParse(string) {
210
+ try {
211
+ return JSON.parse(string);
212
+ }
213
+ catch(err) {
214
+ return null;
215
+ }
216
+ }
217
+ }
218
+
219
+ module.exports = HttpRequestHandler;
@@ -0,0 +1,36 @@
1
+
2
+ 'use strict';
3
+
4
+ const HttpProxy = require('./http-proxy');
5
+ const HttpRequestHandler = require('./http-request-handler');
6
+ const Http = require('http');
7
+
8
+
9
+ class HttpServer {
10
+ constructor(serverData, nodeName, nodeId, httpCache, dataResponse, defaultSite) {
11
+ this.serverData = serverData;
12
+ this.nodeName = nodeName;
13
+ this.nodeId = nodeId;
14
+ this.httpRequestHandler = 'web & rest' === serverData.type ? new HttpRequestHandler(httpCache, dataResponse, defaultSite) : new HttpProxy();
15
+ this.pathsId = -1;
16
+ }
17
+
18
+ start(httpData, cb) {
19
+ this.httpRequestHandler.init(httpData, false);
20
+ const server = Http.createServer((req, res) => {
21
+ this.httpRequestHandler.handle(req, res);
22
+ });
23
+ server.on('listening', () => {
24
+ ddb.writelnTime(ddb.cyan('Server: '), `${this.nodeName}-${httpData.name} `, ddb.green('started at '), `http://${httpData.host}:${httpData.port}`);
25
+ cb();
26
+ });
27
+ server.on('error', (err) => {
28
+ ddb.writelnTimeError(err, ddb.red('Server: '), `'${this.nodeName}-${httpData.name}' `, ddb.red('did not start at '), `http://${httpData.host}:${httpData.port }`, ddb.red(',error: '), err.message);
29
+ cb(err);
30
+ });
31
+ server.listen(httpData.port, httpData.host);
32
+ }
33
+ }
34
+
35
+
36
+ module.exports = HttpServer;