cloudcms-server 4.0.0-beta.5 → 4.0.0-beta.7

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.
@@ -3,6 +3,7 @@
3
3
  <component name="NewModuleRootManager" inherit-compiler-output="true">
4
4
  <exclude-output />
5
5
  <content url="file://$MODULE_DIR$" />
6
+ <orderEntry type="inheritedJdk" />
6
7
  <orderEntry type="sourceFolder" forTests="false" />
7
8
  </component>
8
9
  </module>
@@ -16,7 +16,8 @@ exports = module.exports = function()
16
16
 
17
17
  var pluginPaths = [
18
18
  "./plugins/editorial",
19
- "./plugins/resources"
19
+ "./plugins/resources",
20
+ "./plugins/api_event"
20
21
  ];
21
22
  var plugins = {};
22
23
 
@@ -149,21 +150,21 @@ exports = module.exports = function()
149
150
  var r = {};
150
151
 
151
152
  // allow plugins to bind on("connection") handlers
152
- r.bindOnSocketConnection = function(socket, provider, callback)
153
+ r.bindOnSocketConnection = function(socket, provider, io, callback)
153
154
  {
154
155
  var fns = [];
155
156
  for (var pluginPath in plugins)
156
157
  {
157
158
  var plugin = plugins[pluginPath];
158
159
 
159
- var fn = function(pluginPath, plugin, socket) {
160
+ var fn = function(pluginPath, plugin, socket, io) {
160
161
  return function(done) {
161
-
162
- plugin.bindSocket(socket, provider);
162
+
163
+ plugin.bindSocket(socket, provider, io);
163
164
 
164
165
  done();
165
166
  }
166
- }(pluginPath, plugin, socket);
167
+ }(pluginPath, plugin, socket, io);
167
168
  fns.push(fn);
168
169
  }
169
170
 
@@ -309,7 +310,7 @@ exports = module.exports = function()
309
310
  });
310
311
 
311
312
  // allow plugins to register more on() handlers if they wish
312
- pluginProxy.bindOnSocketConnection(socket, provider, function() {
313
+ pluginProxy.bindOnSocketConnection(socket, provider, io, function() {
313
314
  // done
314
315
  });
315
316
 
@@ -0,0 +1,105 @@
1
+ /*
2
+
3
+ this awareness plugin adds support for general purpose API events
4
+ the API in 4.0 supports passing API events forward via the message queue to the app server
5
+ the app server then converts these into notifications
6
+
7
+ the UI can register and event listener via socket.io ("onApiEvent").
8
+ a listener binds to an event type + an optional reference
9
+
10
+ when an event is received by the API, it triggers to socket.io emits (one for the general event and the other for the
11
+ event + the reference being acted upon)
12
+ */
13
+ exports = module.exports = {};
14
+
15
+ var util = require("../../../util/util");
16
+ var socketUtil = require("../../../util/socket");
17
+
18
+ var subscriptionsBound = false;
19
+
20
+ var bindSubscriptions = function(io)
21
+ {
22
+ if (subscriptionsBound) {
23
+ return;
24
+ }
25
+
26
+ subscriptionsBound = true;
27
+
28
+ // LISTEN: "api_event"
29
+ process.broadcast.subscribe("api_event", function (message, channel, done) {
30
+
31
+ if (!done) {
32
+ done = function () {};
33
+ }
34
+
35
+ // the message
36
+ // {
37
+ // "applicationId": applicationId,
38
+ // "deploymentKey": deploymentKey,
39
+ // "host": host,
40
+ // "eventType": eventType,
41
+ // "eventId": eventId,
42
+ // "objectType": objectType,
43
+ // "objectId": objectId,
44
+ // "objectRef": objectRef,
45
+ // "object": object.object
46
+ // };
47
+
48
+ var apiEvent = {};
49
+ apiEvent.type = message.eventType;
50
+ apiEvent.id = message.eventId;
51
+ apiEvent.objectType = message.objectType;
52
+ apiEvent.objectId = message.objectId;
53
+ apiEvent.objectRef = message.objectRef;
54
+ apiEvent.object = message.object;
55
+
56
+ // dispatch for event + reference
57
+ if (apiEvent.objectRef)
58
+ {
59
+ try {
60
+ apiEvent.channelId = "apiEvent-" + apiEvent.type + "_" + apiEvent.objectRef;
61
+ //console.log("api_event -> " + apiEvent.channelId);
62
+ io.to(apiEvent.channelId).emit("apiEvent", apiEvent);
63
+ } catch (e) {
64
+ console.log(e);
65
+ }
66
+ }
67
+
68
+ // dispatch for event
69
+ try {
70
+ apiEvent.channelId = "apiEvent-" + apiEvent.type;
71
+ //console.log("apiEvent -> " + apiEvent.channelId);
72
+ io.to(apiEvent.channelId).emit("apiEvent", apiEvent);
73
+ } catch (e) {
74
+ console.log(e);
75
+ }
76
+
77
+ done();
78
+ });
79
+ };
80
+
81
+ exports.bindSocket = function(socket, provider, io)
82
+ {
83
+ bindSubscriptions(io);
84
+
85
+ socketUtil.bindGitana(socket, function() {
86
+
87
+ socket.on("onApiEvent", function(eventName, reference, callback) {
88
+
89
+ if (eventName)
90
+ {
91
+ var channelId = "apiEvent-" + eventName;
92
+
93
+ if (reference)
94
+ {
95
+ channelId = eventName + "-" + reference;
96
+ }
97
+
98
+ // join room for this event
99
+ socket.join(channelId);
100
+ }
101
+
102
+ callback();
103
+ });
104
+ });
105
+ };
@@ -5,7 +5,7 @@ var socketUtil = require("../../../util/socket");
5
5
 
6
6
  var request = require("../../../util/request");
7
7
 
8
- exports.bindSocket = function(socket, provider)
8
+ exports.bindSocket = function(socket, provider, io)
9
9
  {
10
10
  socketUtil.bindGitana(socket, function() {
11
11
 
@@ -231,10 +231,11 @@ exports.bindSocket = function(socket, provider)
231
231
  var x1 = cookieValue.indexOf("GITANA_TICKET=");
232
232
  if (x1 > -1)
233
233
  {
234
- var x2 = cookieValue.indexOf(";", x1 + 14);
234
+ ticket = cookieValue.substring(x1 + 14);
235
+ var x2 = ticket.indexOf(";");
235
236
  if (x2 > -1)
236
237
  {
237
- ticket = cookieValue.substring(x1 + 14, x2);
238
+ ticket = ticket.substring(0, x2);
238
239
  }
239
240
  }
240
241
  }
@@ -5,7 +5,7 @@ var socketUtil = require("../../../util/socket");
5
5
 
6
6
  var subscriptionsBound = false;
7
7
 
8
- var bindSubscriptions = function()
8
+ var bindSubscriptions = function(io)
9
9
  {
10
10
  if (subscriptionsBound) {
11
11
  return;
@@ -45,14 +45,14 @@ var bindSubscriptions = function()
45
45
  // fire to reference
46
46
  try {
47
47
  if (reference) {
48
- process.IO.to(reference).emit("watchResource", reference, watchObject);
48
+ io.to(reference).emit("watchResource", reference, watchObject);
49
49
  }
50
50
  } catch (e) { }
51
51
 
52
52
  // fire to head reference
53
53
  try {
54
54
  if (headReference) {
55
- process.IO.to(headReference).emit("watchResource", headReference, watchObject);
55
+ io.to(headReference).emit("watchResource", headReference, watchObject);
56
56
  }
57
57
  } catch (e) { }
58
58
  }
@@ -61,9 +61,9 @@ var bindSubscriptions = function()
61
61
  });
62
62
  };
63
63
 
64
- exports.bindSocket = function(socket, provider)
64
+ exports.bindSocket = function(socket, provider, io)
65
65
  {
66
- bindSubscriptions();
66
+ bindSubscriptions(io);
67
67
 
68
68
  socketUtil.bindGitana(socket, function() {
69
69
 
@@ -1,10 +1,4 @@
1
- var path = require('path');
2
- var http = require('http');
3
- var request = require('request');
4
1
  var util = require("../../util/util");
5
- var Gitana = require("gitana");
6
-
7
- var fs = require("fs");
8
2
 
9
3
  /**
10
4
  * Retrieves local driver configuration for hosts from Cloud CMS.
@@ -55,14 +55,20 @@ exports = module.exports = function()
55
55
  });
56
56
  }
57
57
 
58
- if (!moduleConfig.source)
58
+ var source = moduleConfig.source40;
59
+ if (!source)
60
+ {
61
+ source = moduleConfig.source;
62
+ }
63
+
64
+ if (!source)
59
65
  {
60
66
  return callback({
61
67
  "message": "Missing module config source settings"
62
68
  });
63
69
  }
64
70
 
65
- var sourceType = moduleConfig.source.type;
71
+ var sourceType = source.type;
66
72
  if (!sourceType)
67
73
  {
68
74
  return callback({
@@ -70,7 +76,7 @@ exports = module.exports = function()
70
76
  });
71
77
  }
72
78
 
73
- var sourceUrl = moduleConfig.source.uri;
79
+ var sourceUrl = source.uri;
74
80
  if (!sourceUrl)
75
81
  {
76
82
  return callback({
@@ -78,12 +84,12 @@ exports = module.exports = function()
78
84
  });
79
85
  }
80
86
 
81
- var sourcePath = moduleConfig.source.path;
87
+ var sourcePath = source.path;
82
88
  if (!sourcePath) {
83
89
  sourcePath = "/";
84
90
  }
85
91
 
86
- var sourceBranch = moduleConfig.source.branch;
92
+ var sourceBranch = source.branch;
87
93
  if (!sourceBranch) {
88
94
  sourceBranch = "master";
89
95
  }
@@ -1,4 +1,3 @@
1
- var request = require('request');
2
1
  var path = require('path');
3
2
 
4
3
  var util = require("../../util/util");
@@ -520,7 +520,7 @@ exports = module.exports = function()
520
520
  callback();
521
521
  });
522
522
  };
523
-
523
+
524
524
  process.cache.read("module-descriptors-" + host, function(err, moduleDescriptors) {
525
525
 
526
526
  moduleDescriptors = null;
@@ -1,6 +1,3 @@
1
- //var path = require('path');
2
- //var http = require('http');
3
- //var request = require('request');
4
1
  var util = require("../../util/util");
5
2
 
6
3
  /**
@@ -1,6 +1,3 @@
1
- var path = require('path');
2
- var http = require('http');
3
- var request = require('request');
4
1
  var util = require("../../util/util");
5
2
 
6
3
  /**
@@ -1,7 +1,4 @@
1
1
  var path = require('path');
2
- var fs = require('fs');
3
- var http = require('http');
4
- var request = require('request');
5
2
  var util = require("../../util/util");
6
3
 
7
4
  /**
@@ -72,11 +72,11 @@ var handleNotificationMessages = function(items, callback) {
72
72
  var fns = [];
73
73
  for (var i = 0; i < items.length; i++)
74
74
  {
75
- var fn = function(item, i) {
75
+ var fn = function(item, index) {
76
76
  return function(done) {
77
77
 
78
78
  //logFn("WORKING ON ITEM: " + i + ", item: " + JSON.stringify(item, null, " "));
79
- console.log("WORKING ON ITEM: " + i + ", item: " + JSON.stringify(item, null, " "));
79
+ console.log("WORKING ON ITEM: " + index + ", item: " + JSON.stringify(item, null, " "));
80
80
 
81
81
  var operation = item.operation;
82
82
 
@@ -540,6 +540,8 @@ var handleNotificationMessages = function(items, callback) {
540
540
 
541
541
  var host = determineHost(item);
542
542
 
543
+ var _fns = [];
544
+
543
545
  var deployments = item.deployments;
544
546
  if (deployments && deployments.length > 0)
545
547
  {
@@ -554,17 +556,77 @@ var handleNotificationMessages = function(items, callback) {
554
556
  "host": host,
555
557
  "deployment": deployment
556
558
  };
557
-
558
- // broadcast event
559
- process.broadcast.publish("deployment_synced", message, function(err) {
560
- if (err) {
561
- logInfo("published deployment_synced message. err:" + err + "\nmessage: " + JSON.stringify(message,null,2));
559
+
560
+ var _fn = function(message) {
561
+ return function(d) {
562
+ // broadcast event
563
+ process.broadcast.publish("deployment_synced", message, function(err) {
564
+ if (err) {
565
+ logInfo("published deployment_synced message. err:" + err + "\nmessage: " + JSON.stringify(message,null,2));
566
+ }
567
+ return done(err);
568
+ });
562
569
  }
563
- return done(err);
564
- });
565
-
570
+ }(message);
571
+ _fns.push(_fn);
566
572
  }
567
573
  }
574
+
575
+ async.parallelLimit(_fns, 4, function(err) {
576
+ done(err);
577
+ });
578
+ }
579
+ else if (operation === "api_event")
580
+ {
581
+ var eventType = item.type;
582
+ var eventId = item.id;
583
+ var objects = item.objects;
584
+
585
+ var host = determineHost(item);
586
+
587
+ var _fns = [];
588
+ if (objects && objects.length > 0)
589
+ {
590
+ for (var z = 0; z < objects.length; z++)
591
+ {
592
+ var object = objects[z];
593
+
594
+ var applicationId = object.applicationId;
595
+ var deploymentKey = item.deploymentKey;
596
+
597
+ var objectType = object.type; // sidekickMessage
598
+ var objectId = object.id;
599
+ var objectRef = object.ref;
600
+
601
+ var publishMessage = {
602
+ "applicationId": applicationId,
603
+ "deploymentKey": deploymentKey,
604
+ "host": host,
605
+ "eventType": eventType,
606
+ "eventId": eventId,
607
+ "objectType": objectType,
608
+ "objectId": objectId,
609
+ "objectRef": objectRef,
610
+ "object": object.object
611
+ };
612
+
613
+ var _fn = function(publishMessage) {
614
+ return function(d) {
615
+ // broadcast event
616
+ process.broadcast.publish("api_event", publishMessage, function(err) {
617
+ if (err) {
618
+ logInfo("published api_event message. err:" + err + "\nmessage: " + JSON.stringify(publishMessage,null,2));
619
+ }
620
+ return d(err);
621
+ });
622
+ }
623
+ }(publishMessage);
624
+ _fns.push(_fn);
625
+ }
626
+ }
627
+ async.parallelLimit(_fns, 4, function(err) {
628
+ done(err);
629
+ });
568
630
  }
569
631
  else
570
632
  {
@@ -0,0 +1,182 @@
1
+ const { Kafka } = require("kafkajs");
2
+ const util = require("../../util/util");
3
+
4
+ var holder = {};
5
+
6
+ module.exports = {};
7
+ module.exports.start = function(configuration, callback)
8
+ {
9
+ // clientId
10
+ if (!configuration.clientId)
11
+ {
12
+ if (process.env.CLOUDCMS_NOTIFICATIONS_KAFKA_CLIENT_ID)
13
+ {
14
+ configuration.clientId = process.env.CLOUDCMS_NOTIFICATIONS_KAFKA_CLIENT_ID;
15
+ }
16
+ }
17
+ if (!configuration.clientId)
18
+ {
19
+ configuration.clientId = "cloudcms-ui-kafka-notifications-client";
20
+ }
21
+
22
+ // topic
23
+ if (!configuration.topic)
24
+ {
25
+ if (process.env.CLOUDCMS_NOTIFICATIONS_KAFKA_TOPIC)
26
+ {
27
+ configuration.topic = process.env.CLOUDCMS_NOTIFICATIONS_KAFKA_TOPIC;
28
+ }
29
+ }
30
+ if (!configuration.topic)
31
+ {
32
+ configuration.topic = "cloudcms.ui.topic";
33
+ }
34
+
35
+ // group
36
+ if (!configuration.group)
37
+ {
38
+ if (process.env.CLOUDCMS_NOTIFICATIONS_KAFKA_GROUP)
39
+ {
40
+ configuration.group = process.env.CLOUDCMS_NOTIFICATIONS_KAFKA_GROUP;
41
+ }
42
+ }
43
+ if (!configuration.group) {
44
+ configuration.group = "cloudcms-ui-kafka-notifications-group";
45
+ }
46
+
47
+ // brokers
48
+ if (!configuration.brokers)
49
+ {
50
+ if (process.env.CLOUDCMS_NOTIFICATIONS_KAFKA_BROKERS)
51
+ {
52
+ configuration.brokers = process.env.CLOUDCMS_NOTIFICATIONS_KAFKA_BROKERS;
53
+ }
54
+ }
55
+
56
+ var clientId = configuration.clientId;
57
+ var brokers = configuration.brokers.split(",");
58
+ var topic = configuration.topic;
59
+ var group = configuration.group;
60
+
61
+ process.log("Connecting to kafka, client ID: " + clientId + ", brokers: " + brokers + ", topic: " + topic + ", group: " + group);
62
+
63
+ if (holder.consumer)
64
+ {
65
+ return callback();
66
+ }
67
+
68
+ // console.log("a1");
69
+ var kafka = new Kafka({
70
+ clientId: clientId,
71
+ brokers: brokers
72
+ });
73
+ // console.log("a2: " + kafka);
74
+ // console.log("a3: " + kafka.consumer);
75
+
76
+ var consumer = holder.consumer = kafka.consumer({ groupId: group });
77
+
78
+ // connect
79
+ (async function() {
80
+ await consumer.connect()
81
+ }());
82
+
83
+ (async function() {
84
+ await consumer.subscribe({topic: topic, fromBeginning: true})
85
+ }());
86
+
87
+ callback();
88
+ };
89
+
90
+ module.exports.process = function(callback)
91
+ {
92
+ var consumer = holder.consumer;
93
+ if (!consumer)
94
+ {
95
+ return callback();
96
+ }
97
+
98
+ (async function() {
99
+ await consumer.run({
100
+ eachMessage: async ({ topic, partition, message, heartbeat, pause }) => {
101
+ handleMessage(topic, partition, message, heartbeat, pause, callback);
102
+ }
103
+ });
104
+ }());
105
+ };
106
+
107
+ var handleMessage = function(topic, partition, messageObject, heartbeat, pause, callback)
108
+ {
109
+ // console.log("Topic: " + topic);
110
+ // console.log("Partition: " + partition);
111
+ // console.log("Message: " + JSON.stringify(messageObject, null, 2));
112
+
113
+ if (!messageObject || !messageObject.value)
114
+ {
115
+ return;
116
+ }
117
+
118
+ //var key = message.key.toString();
119
+ var valueString = messageObject.value.toString();
120
+ var headers = messageObject.headers || {};
121
+
122
+ var json = null;
123
+ if (valueString) {
124
+ json = JSON.parse("" + valueString);
125
+ }
126
+
127
+ // console.log("b1: " + valueString);
128
+ // console.log("b2: " + data);
129
+
130
+ if (json)
131
+ {
132
+ console.log("JSON: " + JSON.stringify(json));
133
+ console.log("HEADERS: " + JSON.stringify(headers));
134
+
135
+ /**
136
+ * kafka1-ui-1 | VAL: {"subject":"invalidate_objects:aea334cb8accb0bd698e","message":"","data":"{\"operation\":\"invalidate_objects\",\"invalidations\":[{\"applicationId\":\"1785c4b13f74b3aa4b31\",\"ref\":\"application://826a3ebefe4c1e006a60/1785c4b13f74b3aa4b31\",\"id\":\"1785c4b13f74b3aa4b31\",\"type\":\"application\",\"stackId\":\"a17879ca0923f6d9696b\",\"stackMembers\":{\"archives\":{\"typeId\":\"vault\",\"id\":\"385e37eb07bc3d16dca1\"},\"console\":{\"typeId\":\"application\",\"id\":\"1785c4b13f74b3aa4b31\"},\"content\":{\"typeId\":\"repository\",\"id\":\"9904550a6b2a2a71f015\"},\"hosting\":{\"typeId\":\"webhost\",\"id\":\"5d2db66ced26608dc355\"},\"oneteam\":{\"typeId\":\"application\",\"id\":\"8d5ba57420ce31a3172c\"},\"principals\":{\"typeId\":\"domain\",\"id\":\"32cbffafe9f2de4d1b9a\"},\"root\":{\"typeId\":\"directory\",\"id\":\"6db38348323d001c2c10\"}}}]}"}
137
+ * kafka1-ui-1 | HEADERS: [object Object]
138
+ * @type {*[]}
139
+ */
140
+
141
+ var subject = json.subject;
142
+ var message = json.message;
143
+
144
+ // build out the notification message items
145
+ var items = [];
146
+
147
+ if (json.data)
148
+ {
149
+ var data = JSON.parse("" + json.data);
150
+
151
+ // timestamp from headers
152
+ //var timestamp = parseInt(headers.timestamp);
153
+ var timestamp = new Date().getTime();
154
+
155
+ // copy data as item
156
+ var item = util.clone(data, true);
157
+ if (!item)
158
+ {
159
+ item = {};
160
+ }
161
+
162
+ // other properties
163
+ item.timestamp = timestamp;
164
+ item.sentTimestamp = timestamp;
165
+ item.subject = subject;
166
+
167
+ // raw message
168
+ item.rawMessage = json.data; // string
169
+
170
+ items.push(item);
171
+
172
+ //console.log("ITEM: " + JSON.stringify(item));
173
+ }
174
+ }
175
+
176
+ // call back to notifications engine to process these items
177
+ // when they're done processing, our callback is fired so that we can handle deletes and things
178
+ // we call the done() method when we're finished
179
+ callback(null, items, function(err, items, done) {
180
+ done(err, items, items);
181
+ });
182
+ };
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "name": "cloudcms-server",
8
8
  "description": "Cloud CMS Application Server Module",
9
- "version": "4.0.0-beta.5",
9
+ "version": "4.0.0-beta.7",
10
10
  "repository": {
11
11
  "type": "git",
12
12
  "url": "git://github.com/gitana/cloudcms-server.git"
@@ -16,13 +16,13 @@
16
16
  "@socket.io/redis-adapter": "^7.2.0",
17
17
  "@socket.io/sticky": "^1.0.1",
18
18
  "accepts": "^1.3.8",
19
- "agentkeepalive": "^4.2.1",
19
+ "agentkeepalive": "^4.5.0",
20
20
  "alpaca": "^1.5.27",
21
21
  "archiver": "^5.1.0",
22
22
  "async": "^3.2.3",
23
23
  "async-lock": "^1.3.2",
24
24
  "aws-sdk": "^2.1208.0",
25
- "axios": "^0.21.0",
25
+ "axios": "^1.5.0",
26
26
  "basic-auth": "^2.0.1",
27
27
  "body-parser": "^1.20.0",
28
28
  "bytes": "^3.1.0",
@@ -37,22 +37,21 @@
37
37
  "dustjs-helpers": "^1.7.4",
38
38
  "dustjs-linkedin": "^3.0.1",
39
39
  "errorhandler": "^1.5.1",
40
- "express": "^4.18.1",
40
+ "express": "^4.18.2",
41
41
  "express-session": "^1.17.3",
42
42
  "express-useragent": "^1.0.15",
43
43
  "extend-with-super": "^2.0.0",
44
- "finalhandler": "^1.2.0",
45
- "form-data": "^2.3.3",
46
- "gitana": "^1.0.323",
44
+ "fast-proxy": "^2.2.0",
45
+ "gitana": "^1.0.324",
47
46
  "handlebars": "^4.7.6",
48
47
  "hbs": "^4.1.1",
49
48
  "helmet": "^4.6.0",
50
- "http2-proxy": "^5.0.53",
51
49
  "ioredis": "4.28.5",
52
50
  "json5": "^2.1.3",
53
- "jsonwebtoken": "^8.5.1",
51
+ "jsonwebtoken": "^9.0.2",
52
+ "kafkajs": "^2.2.4",
54
53
  "klaw": "^3.0.0",
55
- "lru-cache": "^6.0.0",
54
+ "lru-cache": "^7.14.0",
56
55
  "marked": "^4.0.14",
57
56
  "memored": "^1.1.1",
58
57
  "memorystore": "^1.6.4",
@@ -1,15 +1,13 @@
1
- var http = require("http");
2
- var https = require("https");
1
+ // var http = require("http");
2
+ // var https = require("https");
3
3
  var path = require("path");
4
4
 
5
5
  var auth = require("./auth");
6
- var util = require("./util");
6
+ // var util = require("./util");
7
7
 
8
8
  var oauth2 = require("./oauth2")();
9
9
 
10
- var urlTool = require("url");
11
-
12
- var LRUCache = require("lru-cache");
10
+ var LRU = require("lru-cache");
13
11
 
14
12
  var exports = module.exports;
15
13
 
@@ -19,9 +17,9 @@ var _LOCK = function(lockIdentifiers, workFunction)
19
17
  process.locks.lock(name, workFunction);
20
18
  };
21
19
 
22
- var NAMED_PROXY_HANDLERS_CACHE = new LRUCache({
20
+ var NAMED_PROXY_HANDLERS_CACHE = new LRU({
23
21
  max: 200,
24
- maxAge: 1000 * 60 * 60 // 60 minutes
22
+ ttl: 1000 * 60 * 60 // 60 minutes
25
23
  });
26
24
 
27
25
  var acquireProxyHandler = exports.acquireProxyHandler = function(proxyTarget, pathPrefix, callback)
@@ -35,36 +33,40 @@ var acquireProxyHandler = exports.acquireProxyHandler = function(proxyTarget, pa
35
33
  {
36
34
  return callback(null, _cachedHandler);
37
35
  }
38
-
39
- // take out a thread lock
40
- _LOCK(["acquireProxyHandler", name], function(err, releaseLockFn) {
41
-
42
- if (err)
43
- {
44
- console.log("Failed to acquire proxy handler: " + name + ", err: ", err);
45
-
46
- // failed to acquire lock
47
- return callback(err);
48
- }
49
-
50
- // second check to make sure another thread didn't create the handler in the meantime
51
- _cachedHandler = NAMED_PROXY_HANDLERS_CACHE[name];
52
- if (_cachedHandler)
53
- {
54
- releaseLockFn();
55
- return callback(null, _cachedHandler);
56
- }
57
-
58
- // create the proxy handler and cache it into LRU cache
59
- //console.log("Acquiring proxy handler: " + name + ", for target: " + proxyTarget + " and prefix: " + pathPrefix);
60
- _cachedHandler = createProxyHandler(proxyTarget, pathPrefix);
61
-
62
- // store back into LRU cache
63
- NAMED_PROXY_HANDLERS_CACHE[name] = _cachedHandler;
64
36
 
65
- releaseLockFn();
66
- callback(null, _cachedHandler);
67
- });
37
+ // // take out a thread lock
38
+ // _LOCK(["acquireProxyHandler", name], function(err, releaseLockFn) {
39
+ //
40
+ // if (err)
41
+ // {
42
+ // console.log("Failed to acquire proxy handler: " + name + ", err: ", err);
43
+ //
44
+ // // failed to acquire lock
45
+ // return callback(err);
46
+ // }
47
+ //
48
+ // // second check to make sure another thread didn't create the handler in the meantime
49
+ // _cachedHandler = NAMED_PROXY_HANDLERS_CACHE[name];
50
+ // if (_cachedHandler)
51
+ // {
52
+ // releaseLockFn();
53
+ // return callback(null, _cachedHandler);
54
+ // }
55
+ //
56
+ // // create the proxy handler and cache it into LRU cache
57
+ // //console.log("Acquiring proxy handler: " + name + ", for target: " + proxyTarget + " and prefix: " + pathPrefix);
58
+ // _cachedHandler = createProxyHandler(proxyTarget, pathPrefix);
59
+ //
60
+ // // store back into LRU cache
61
+ // NAMED_PROXY_HANDLERS_CACHE[name] = _cachedHandler;
62
+ //
63
+ // releaseLockFn();
64
+ // callback(null, _cachedHandler);
65
+ // });
66
+
67
+ _cachedHandler = NAMED_PROXY_HANDLERS_CACHE[name] = createProxyHandler(proxyTarget, pathPrefix);
68
+
69
+ callback(null, _cachedHandler);
68
70
  };
69
71
 
70
72
 
@@ -72,70 +74,106 @@ var acquireProxyHandler = exports.acquireProxyHandler = function(proxyTarget, pa
72
74
 
73
75
  var createProxyHandler = function(proxyTarget, pathPrefix)
74
76
  {
75
- const proxy = require("http2-proxy");
76
- const finalhandler = require('finalhandler')
77
-
78
- const defaultWebHandler = function(err, req, res) {
79
- if (err)
77
+ const { proxy, close } = require('fast-proxy')({
78
+ base: proxyTarget,
79
+ cacheURLs: 0,
80
+ //http2: true,
81
+ //undici: true
82
+ });
83
+
84
+ var proxyOptions = {};
85
+ proxyOptions.onResponse = function(req, res, stream) {
86
+
87
+ if (req.gitana_user)
80
88
  {
81
- console.log("A web proxy error was caught, path: " + req.path + ", err: ", err);
82
- try { res.status(500); } catch (e) { }
83
- try { res.end('Something went wrong while proxying the request.'); } catch (e) { }
84
- }
85
-
86
- finalhandler(req, res)(err);
87
- };
88
-
89
- // const defaultWsHandler = function(err, req, socket, head) {
90
- // if (err) {
91
- // console.error('proxy error (ws)', err);
92
- // socket.destroy();
93
- // }
94
- // };
95
-
96
- //console.log("Proxy Target: " + proxyTarget);
97
-
98
- var hostname = urlTool.parse(proxyTarget).hostname;
99
- var port = urlTool.parse(proxyTarget).port;
100
- var protocol = urlTool.parse(proxyTarget).protocol;
101
-
102
- // web
103
- var webConfig = {};
104
- webConfig.hostname = hostname;
105
- webConfig.port = port;
106
- webConfig.protocol = protocol;
107
- //webConfig.path = null;
108
- webConfig.timeout = 120000;
109
- webConfig.proxyTimeout = 120000;
110
- webConfig.proxyName = "Cloud CMS UI Proxy";
111
- webConfig.onReq = function(req, options) {
112
-
113
- if (!options.headers) {
114
- options.headers = {};
115
- }
116
- var headers = options.headers;
89
+ var chunks = [];
90
+
91
+ // triggers on data receive
92
+ stream.on('data', function(chunk) {
93
+ console.log("DATA!");
94
+ // add received chunk to chunks array
95
+ chunks.push(chunk);
96
+ });
97
+
98
+ stream.on("end", function () {
99
+
100
+ if (stream.statusCode === 401)
101
+ {
102
+ var text = "" + Buffer.concat(chunks);
103
+ if (text && (text.indexOf("invalid_token") > -1) || (text.indexOf("invalid_grant") > -1))
104
+ {
105
+ var identifier = req.identity_properties.provider_id + "/" + req.identity_properties.user_identifier;
106
+
107
+ _LOCK([identifier], function(err, releaseLockFn) {
108
+
109
+ if (err)
110
+ {
111
+ // failed to acquire lock
112
+ console.log("FAILED TO ACQUIRE LOCK", err);
113
+ req.log("FAILED TO ACQUIRE LOCK", err);
114
+ try { releaseLockFn(); } catch (e) { }
115
+ return;
116
+ }
117
+
118
+ var cleanup = function (full)
119
+ {
120
+ delete Gitana.APPS[req.identity_properties.token];
121
+ delete Gitana.PLATFORM_CACHE[req.identity_properties.token];
122
+
123
+ if (full) {
124
+ auth.removeUserCacheEntry(identifier);
125
+ }
126
+ };
127
+
128
+ // null out the access token
129
+ // this will force the refresh token to be used to get a new one on the next request
130
+ req.gitana_user.getDriver().http.refresh(function (err) {
131
+
132
+ if (err) {
133
+ cleanup(true);
134
+ req.log("Invalidated auth state for gitana user: " + req.identity_properties.token);
135
+ return releaseLockFn();
136
+ }
117
137
 
118
- if (options.path && options.path.startsWith("/proxy")) {
119
- options.path = options.path.substring(6);
138
+ req.gitana_user.getDriver().reloadAuthInfo(function () {
139
+ cleanup(true);
140
+ req.log("Refreshed token for gitana user: " + req.identity_properties.token);
141
+ releaseLockFn();
142
+ });
143
+ });
144
+ });
145
+ }
146
+
147
+ }
148
+ });
120
149
  }
121
-
122
- if (pathPrefix) {
123
- options.path = path.join(pathPrefix, options.path);
150
+
151
+ //res.setHeader('x-powered-by', 'cloudcms');
152
+ if (stream.statusCode && stream.headers) {
153
+ res.writeHead(stream.statusCode, stream.headers)
124
154
  }
125
-
155
+
156
+ stream.pipe(res)
157
+ };
158
+ proxyOptions.rewriteRequestHeaders = function(req, headers)
159
+ {
126
160
  // used to auto-assign the client header for /oauth/token requests
127
161
  oauth2.autoProxy(req);
128
-
162
+ if (req.headers && req.headers.authorization)
163
+ {
164
+ headers["authorization"] = req.headers.authorization;
165
+ }
166
+
129
167
  // copy domain host into "x-cloudcms-domainhost"
130
168
  if (req.domainHost) {
131
169
  headers["x-cloudcms-domainhost"] = req.domainHost; // this could be "localhost"
132
170
  }
133
-
171
+
134
172
  // copy virtual host into "x-cloudcms-virtualhost"
135
173
  if (req.virtualHost) {
136
174
  headers["x-cloudcms-virtualhost"] = req.virtualHost; // this could be "root.cloudcms.net" or "abc.cloudcms.net"
137
175
  }
138
-
176
+
139
177
  // copy deployment descriptor info
140
178
  if (req.descriptor)
141
179
  {
@@ -145,27 +183,27 @@ var createProxyHandler = function(proxyTarget, pathPrefix)
145
183
  {
146
184
  headers["x-cloudcms-tenant-id"] = req.descriptor.tenant.id;
147
185
  }
148
-
186
+
149
187
  if (req.descriptor.tenant.title)
150
188
  {
151
189
  headers["x-cloudcms-tenant-title"] = req.descriptor.tenant.title;
152
190
  }
153
191
  }
154
-
192
+
155
193
  if (req.descriptor.application)
156
194
  {
157
195
  if (req.descriptor.application.id)
158
196
  {
159
197
  headers["x-cloudcms-application-id"] = req.descriptor.application.id;
160
198
  }
161
-
199
+
162
200
  if (req.descriptor.application.title)
163
201
  {
164
202
  headers["x-cloudcms-application-title"] = req.descriptor.application.title;
165
203
  }
166
204
  }
167
205
  }
168
-
206
+
169
207
  // set optional "x-cloudcms-origin" header
170
208
  var cloudcmsOrigin = null;
171
209
  if (req.virtualHost)
@@ -176,13 +214,13 @@ var createProxyHandler = function(proxyTarget, pathPrefix)
176
214
  {
177
215
  headers["x-cloudcms-origin"] = cloudcmsOrigin;
178
216
  }
179
-
217
+
180
218
  // set x-cloudcms-server-version header
181
219
  headers["x-cloudcms-server-version"] = process.env.CLOUDCMS_APPSERVER_PACKAGE_VERSION;
182
-
220
+
183
221
  // keep alive
184
222
  //req.headers["connection"] = "keep-alive";
185
-
223
+
186
224
  // if the incoming request didn't have an "Authorization" header
187
225
  // and we have a logged in Gitana User via Auth, then set authorization header to Bearer Access Token
188
226
  if (!req.headers["authorization"])
@@ -196,85 +234,22 @@ var createProxyHandler = function(proxyTarget, pathPrefix)
196
234
  headers["authorization"] = "Bearer " + req.gitana_proxy_access_token;
197
235
  }
198
236
  }
199
- };
200
- webConfig.onRes = function(req, res, proxyRes) {
201
-
202
- if (req.gitana_user)
203
- {
204
- var chunks = [];
205
-
206
- // triggers on data receive
207
- proxyRes.on('data', function(chunk) {
208
- // add received chunk to chunks array
209
- chunks.push(chunk);
210
- });
211
-
212
- proxyRes.on("end", function () {
213
-
214
- if (proxyRes.statusCode === 401)
215
- {
216
- var text = "" + Buffer.concat(chunks);
217
- if (text && (text.indexOf("invalid_token") > -1) || (text.indexOf("invalid_grant") > -1))
218
- {
219
- var identifier = req.identity_properties.provider_id + "/" + req.identity_properties.user_identifier;
220
237
 
221
- _LOCK([identifier], function(err, releaseLockFn) {
222
-
223
- if (err)
224
- {
225
- // failed to acquire lock
226
- console.log("FAILED TO ACQUIRE LOCK", err);
227
- req.log("FAILED TO ACQUIRE LOCK", err);
228
- try { releaseLockFn(); } catch (e) { }
229
- return;
230
- }
231
-
232
- var cleanup = function (full)
233
- {
234
- delete Gitana.APPS[req.identity_properties.token];
235
- delete Gitana.PLATFORM_CACHE[req.identity_properties.token];
236
-
237
- if (full) {
238
- auth.removeUserCacheEntry(identifier);
239
- }
240
- };
241
-
242
- // null out the access token
243
- // this will force the refresh token to be used to get a new one on the next request
244
- req.gitana_user.getDriver().http.refresh(function (err) {
245
-
246
- if (err) {
247
- cleanup(true);
248
- req.log("Invalidated auth state for gitana user: " + req.identity_properties.token);
249
- return releaseLockFn();
250
- }
238
+ return headers;
239
+ };
240
+ // rewrite response headers
241
+ proxyOptions.rewriteHeaders = function(headers)
242
+ {
243
+ return headers;
244
+ };
245
+ // request invoke settings
246
+ //proxyOptions.request = {};
251
247
 
252
- req.gitana_user.getDriver().reloadAuthInfo(function () {
253
- cleanup(true);
254
- req.log("Refreshed token for gitana user: " + req.identity_properties.token);
255
- releaseLockFn();
256
- });
257
- });
258
- });
259
- }
248
+ //////////////////////////////////////////////////////////////////////////
260
249
 
261
- }
262
- });
263
- }
264
-
265
- //res.setHeader('x-powered-by', 'cloudcms');
266
- res.writeHead(proxyRes.statusCode, proxyRes.headers)
267
- proxyRes.pipe(res)
268
- };
269
-
270
250
  var proxyRequestHandler = function(req, res) {
271
- proxy.web(req, res, webConfig, function(err, req, res) {
272
- defaultWebHandler(err, req, res);
273
- });
251
+ proxy(req, res, pathPrefix, proxyOptions);
274
252
  };
275
-
276
- // cookie domain rewrite?
277
- // not needed - this is handled intrinsically by http2-proxy
278
253
 
279
254
  return proxyRequestHandler;
280
255
  };
package/.last_command DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "command": {
3
- "group": "server",
4
- "name": "start"
5
- },
6
- "arguments": {}
7
- }