@resolveio/server-lib 22.1.17 → 22.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/managers/websocket.manager.d.ts +4 -0
- package/managers/websocket.manager.js +21 -0
- package/managers/websocket.manager.js.map +1 -1
- package/package.json +1 -1
- package/server-app.d.ts +33 -0
- package/server-app.js +1000 -293
- package/server-app.js.map +1 -1
package/server-app.js
CHANGED
|
@@ -76,6 +76,7 @@ exports.ResolveIOMainServer = void 0;
|
|
|
76
76
|
var express = require("express");
|
|
77
77
|
var xmlParser = require("express-xml-bodyparser");
|
|
78
78
|
var http_1 = require("http");
|
|
79
|
+
var crypto = require("crypto");
|
|
79
80
|
var fs = require("fs");
|
|
80
81
|
var jwt = require("jsonwebtoken");
|
|
81
82
|
var moment = require("moment-timezone");
|
|
@@ -142,9 +143,16 @@ var ResolveIOMainServer = /** @class */ (function () {
|
|
|
142
143
|
this._isWorkersEnabled = false;
|
|
143
144
|
this._isWorkerInstance = false;
|
|
144
145
|
this._safeShutdown = false;
|
|
146
|
+
this._dynamicAppGatewayEnabled = false;
|
|
147
|
+
this._dynamicAppGatewayCache = new Map();
|
|
148
|
+
this._socketTier = '';
|
|
149
|
+
this._maxClientSockets = 0;
|
|
150
|
+
this._singleIpPerUser = false;
|
|
151
|
+
this._socketPolicyUpgradeUrl = '';
|
|
145
152
|
this._clientHeartbeatIntervalMs = 20000;
|
|
146
153
|
this._clientHeartbeatInitialDelayMs = 5000;
|
|
147
154
|
this._clientHeartbeatBackpressureBytes = 5 * 1024 * 1024;
|
|
155
|
+
this._dynamicAppGatewayCacheMs = 30 * 1000;
|
|
148
156
|
}
|
|
149
157
|
ResolveIOMainServer.create = function () {
|
|
150
158
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -184,6 +192,18 @@ var ResolveIOMainServer = /** @class */ (function () {
|
|
|
184
192
|
this._timerDebugSampleRate = this.resolveTimerDebugSampleRate();
|
|
185
193
|
this._timerDebugLogLimit = this.resolveTimerDebugLogLimit();
|
|
186
194
|
this._aiWorkerDebug = this.parseDebugFlag(process.env.AI_ASSISTANT_WORKER_DEBUG);
|
|
195
|
+
this._dynamicAppGatewayEnabled = this.resolveDynamicAppGatewayEnabled();
|
|
196
|
+
this._socketTier = this.resolveSocketTier();
|
|
197
|
+
this._maxClientSockets = this.resolveMaxClientSockets(this._socketTier);
|
|
198
|
+
this._singleIpPerUser = this.resolveSingleIpPerUserPolicy(this._socketTier);
|
|
199
|
+
this._socketPolicyUpgradeUrl = this.resolveSocketPolicyUpgradeUrl();
|
|
200
|
+
if (this._maxClientSockets > 0 || this._singleIpPerUser) {
|
|
201
|
+
console.info(new Date(), '[Socket Policy] configured', {
|
|
202
|
+
tier: this._socketTier || 'none',
|
|
203
|
+
maxClientSockets: this._maxClientSockets,
|
|
204
|
+
singleIpPerUser: this._singleIpPerUser
|
|
205
|
+
});
|
|
206
|
+
}
|
|
187
207
|
_a = this;
|
|
188
208
|
return [4 /*yield*/, monitor_manager_1.MonitorManager.create()];
|
|
189
209
|
case 1:
|
|
@@ -566,6 +586,7 @@ var ResolveIOMainServer = /** @class */ (function () {
|
|
|
566
586
|
if (this.LOGGER === 'DEBUG') {
|
|
567
587
|
console.log('Setup cors');
|
|
568
588
|
}
|
|
589
|
+
this.installDynamicAppGatewayMiddleware();
|
|
569
590
|
// Set up http login route
|
|
570
591
|
(0, auth_1.setupAuthRoutes)(this, this._app, resolveio_server_app_1.ResolveIOServer.getServerConfig());
|
|
571
592
|
(0, health_1.setupHealthRoutes)(this._app);
|
|
@@ -577,6 +598,377 @@ var ResolveIOMainServer = /** @class */ (function () {
|
|
|
577
598
|
console.log('Setup express routes');
|
|
578
599
|
}
|
|
579
600
|
};
|
|
601
|
+
ResolveIOMainServer.prototype.installDynamicAppGatewayMiddleware = function () {
|
|
602
|
+
var _this = this;
|
|
603
|
+
if (!this._dynamicAppGatewayEnabled) {
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
this._app.use(function (req, res, next) { return __awaiter(_this, void 0, void 0, function () {
|
|
607
|
+
var appId, appDoc, allowedHosts, controlHosts, requestHost, originHeader, originHost, expectedToken, providedToken, error_4;
|
|
608
|
+
var _a, _b, _c;
|
|
609
|
+
return __generator(this, function (_d) {
|
|
610
|
+
switch (_d.label) {
|
|
611
|
+
case 0:
|
|
612
|
+
appId = this.extractDynamicAppGatewayId(req);
|
|
613
|
+
if (!appId) {
|
|
614
|
+
next();
|
|
615
|
+
return [2 /*return*/];
|
|
616
|
+
}
|
|
617
|
+
_d.label = 1;
|
|
618
|
+
case 1:
|
|
619
|
+
_d.trys.push([1, 3, , 4]);
|
|
620
|
+
return [4 /*yield*/, this.resolveCachedDynamicAppGatewayApp(appId)];
|
|
621
|
+
case 2:
|
|
622
|
+
appDoc = _d.sent();
|
|
623
|
+
if (!appDoc) {
|
|
624
|
+
res.status(404).send(JSON.stringify({
|
|
625
|
+
error: true,
|
|
626
|
+
result: 'App not found.'
|
|
627
|
+
}));
|
|
628
|
+
return [2 /*return*/];
|
|
629
|
+
}
|
|
630
|
+
allowedHosts = this.resolveDynamicAppAllowedHosts(appDoc);
|
|
631
|
+
controlHosts = this.resolveDynamicAppControlHosts();
|
|
632
|
+
requestHost = this.normalizeHostname(this.normalizeHeaderValue((_a = req.headers) === null || _a === void 0 ? void 0 : _a['x-forwarded-host'])
|
|
633
|
+
|| this.normalizeHeaderValue((_b = req.headers) === null || _b === void 0 ? void 0 : _b.host));
|
|
634
|
+
originHeader = this.normalizeHeaderValue((_c = req.headers) === null || _c === void 0 ? void 0 : _c.origin);
|
|
635
|
+
originHost = this.resolveOriginHostname(originHeader);
|
|
636
|
+
if (requestHost && controlHosts.has(requestHost) && !this.isLocalHostname(requestHost)) {
|
|
637
|
+
res.status(403).send(JSON.stringify({
|
|
638
|
+
error: true,
|
|
639
|
+
result: 'App API must be requested from an app domain.'
|
|
640
|
+
}));
|
|
641
|
+
return [2 /*return*/];
|
|
642
|
+
}
|
|
643
|
+
if (requestHost && !allowedHosts.has(requestHost) && !this.isLocalHostname(requestHost)) {
|
|
644
|
+
res.status(403).send(JSON.stringify({
|
|
645
|
+
error: true,
|
|
646
|
+
result: 'Host not allowed for app API.'
|
|
647
|
+
}));
|
|
648
|
+
return [2 /*return*/];
|
|
649
|
+
}
|
|
650
|
+
if (originHost && controlHosts.has(originHost) && !this.isLocalHostname(originHost)) {
|
|
651
|
+
res.status(403).send(JSON.stringify({
|
|
652
|
+
error: true,
|
|
653
|
+
result: 'App API origin must be an app domain.'
|
|
654
|
+
}));
|
|
655
|
+
return [2 /*return*/];
|
|
656
|
+
}
|
|
657
|
+
if (originHost && !allowedHosts.has(originHost)) {
|
|
658
|
+
res.status(403).send(JSON.stringify({
|
|
659
|
+
error: true,
|
|
660
|
+
result: 'Origin not allowed for app API.'
|
|
661
|
+
}));
|
|
662
|
+
return [2 /*return*/];
|
|
663
|
+
}
|
|
664
|
+
if (originHeader) {
|
|
665
|
+
this.applyDynamicAppGatewayCorsHeaders(res, originHeader);
|
|
666
|
+
}
|
|
667
|
+
if (req.method === 'OPTIONS') {
|
|
668
|
+
res.status(204).end();
|
|
669
|
+
return [2 /*return*/];
|
|
670
|
+
}
|
|
671
|
+
expectedToken = this.normalizeHeaderValue(appDoc === null || appDoc === void 0 ? void 0 : appDoc.rio_token);
|
|
672
|
+
if (!expectedToken) {
|
|
673
|
+
res.status(500).send(JSON.stringify({
|
|
674
|
+
error: true,
|
|
675
|
+
result: 'App token is not configured.'
|
|
676
|
+
}));
|
|
677
|
+
return [2 /*return*/];
|
|
678
|
+
}
|
|
679
|
+
providedToken = this.resolveDynamicAppGatewayToken(req);
|
|
680
|
+
if (!providedToken || providedToken !== expectedToken) {
|
|
681
|
+
res.status(401).send(JSON.stringify({
|
|
682
|
+
error: true,
|
|
683
|
+
result: 'Invalid or missing RIO token.'
|
|
684
|
+
}));
|
|
685
|
+
return [2 /*return*/];
|
|
686
|
+
}
|
|
687
|
+
next();
|
|
688
|
+
return [3 /*break*/, 4];
|
|
689
|
+
case 3:
|
|
690
|
+
error_4 = _d.sent();
|
|
691
|
+
console.error(new Date(), '[DynamicAppGateway] middleware failure', error_4);
|
|
692
|
+
res.status(500).send(JSON.stringify({
|
|
693
|
+
error: true,
|
|
694
|
+
result: (error_4 === null || error_4 === void 0 ? void 0 : error_4.message) || 'Dynamic app gateway error.'
|
|
695
|
+
}));
|
|
696
|
+
return [3 /*break*/, 4];
|
|
697
|
+
case 4: return [2 /*return*/];
|
|
698
|
+
}
|
|
699
|
+
});
|
|
700
|
+
}); });
|
|
701
|
+
};
|
|
702
|
+
ResolveIOMainServer.prototype.resolveDynamicAppGatewayEnabled = function () {
|
|
703
|
+
var _a;
|
|
704
|
+
var config = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
|
|
705
|
+
var raw = (_a = config['AI_CODER_DYNAMIC_APP_GATEWAY']) !== null && _a !== void 0 ? _a : process.env.AI_CODER_DYNAMIC_APP_GATEWAY;
|
|
706
|
+
if (raw !== undefined && raw !== null && "".concat(raw).trim() !== '') {
|
|
707
|
+
return this.parseDebugFlag(raw);
|
|
708
|
+
}
|
|
709
|
+
var urls = [
|
|
710
|
+
config['ROOT_URL'],
|
|
711
|
+
config['SEC_ROOT_URL'],
|
|
712
|
+
config['SERVER_URL'],
|
|
713
|
+
process.env.ROOT_URL,
|
|
714
|
+
process.env.SEC_ROOT_URL,
|
|
715
|
+
process.env.SERVER_URL
|
|
716
|
+
]
|
|
717
|
+
.map(function (value) { return "".concat(value || '').trim().toLowerCase(); })
|
|
718
|
+
.filter(Boolean);
|
|
719
|
+
return urls.some(function (value) { return value.includes('aicoder'); });
|
|
720
|
+
};
|
|
721
|
+
ResolveIOMainServer.prototype.extractDynamicAppGatewayId = function (req) {
|
|
722
|
+
var rawPath = "".concat(req.originalUrl || req.url || req.path || '');
|
|
723
|
+
var normalizedPath = rawPath.split('?')[0];
|
|
724
|
+
if (!normalizedPath.startsWith('/api/apps/')) {
|
|
725
|
+
return '';
|
|
726
|
+
}
|
|
727
|
+
var parts = normalizedPath.split('/').filter(Boolean);
|
|
728
|
+
if (parts.length < 3) {
|
|
729
|
+
return '';
|
|
730
|
+
}
|
|
731
|
+
return "".concat(parts[2] || '').trim();
|
|
732
|
+
};
|
|
733
|
+
ResolveIOMainServer.prototype.resolveDynamicAppGatewayToken = function (req) {
|
|
734
|
+
var e_1, _a, e_2, _b, e_3, _c;
|
|
735
|
+
var _d, _e, _f, _g, _h;
|
|
736
|
+
var authHeader = this.normalizeHeaderValue(((_d = req.headers) === null || _d === void 0 ? void 0 : _d.authorization) || ((_e = req.headers) === null || _e === void 0 ? void 0 : _e.Authorization));
|
|
737
|
+
if (authHeader) {
|
|
738
|
+
var bearerMatch = authHeader.match(/^bearer\s+(.+)$/i);
|
|
739
|
+
if (bearerMatch && bearerMatch[1]) {
|
|
740
|
+
return bearerMatch[1].trim();
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
var headerCandidates = [
|
|
744
|
+
(_f = req.headers) === null || _f === void 0 ? void 0 : _f['x-rio-token'],
|
|
745
|
+
(_g = req.headers) === null || _g === void 0 ? void 0 : _g['x-app-token'],
|
|
746
|
+
(_h = req.headers) === null || _h === void 0 ? void 0 : _h['x-api-key']
|
|
747
|
+
];
|
|
748
|
+
try {
|
|
749
|
+
for (var headerCandidates_1 = __values(headerCandidates), headerCandidates_1_1 = headerCandidates_1.next(); !headerCandidates_1_1.done; headerCandidates_1_1 = headerCandidates_1.next()) {
|
|
750
|
+
var candidate = headerCandidates_1_1.value;
|
|
751
|
+
var value = this.normalizeHeaderValue(candidate);
|
|
752
|
+
if (value) {
|
|
753
|
+
return value;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
758
|
+
finally {
|
|
759
|
+
try {
|
|
760
|
+
if (headerCandidates_1_1 && !headerCandidates_1_1.done && (_a = headerCandidates_1.return)) _a.call(headerCandidates_1);
|
|
761
|
+
}
|
|
762
|
+
finally { if (e_1) throw e_1.error; }
|
|
763
|
+
}
|
|
764
|
+
var body = req.body || {};
|
|
765
|
+
var query = req.query || {};
|
|
766
|
+
var bodyCandidates = [body.rioToken, body.rio_token, body.apiKey, body.token];
|
|
767
|
+
try {
|
|
768
|
+
for (var bodyCandidates_1 = __values(bodyCandidates), bodyCandidates_1_1 = bodyCandidates_1.next(); !bodyCandidates_1_1.done; bodyCandidates_1_1 = bodyCandidates_1.next()) {
|
|
769
|
+
var candidate = bodyCandidates_1_1.value;
|
|
770
|
+
var value = this.normalizeHeaderValue(candidate);
|
|
771
|
+
if (value) {
|
|
772
|
+
return value;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
777
|
+
finally {
|
|
778
|
+
try {
|
|
779
|
+
if (bodyCandidates_1_1 && !bodyCandidates_1_1.done && (_b = bodyCandidates_1.return)) _b.call(bodyCandidates_1);
|
|
780
|
+
}
|
|
781
|
+
finally { if (e_2) throw e_2.error; }
|
|
782
|
+
}
|
|
783
|
+
var queryCandidates = [query.rioToken, query.rio_token, query.apiKey, query.token];
|
|
784
|
+
try {
|
|
785
|
+
for (var queryCandidates_1 = __values(queryCandidates), queryCandidates_1_1 = queryCandidates_1.next(); !queryCandidates_1_1.done; queryCandidates_1_1 = queryCandidates_1.next()) {
|
|
786
|
+
var candidate = queryCandidates_1_1.value;
|
|
787
|
+
var value = this.normalizeHeaderValue(candidate);
|
|
788
|
+
if (value) {
|
|
789
|
+
return value;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
794
|
+
finally {
|
|
795
|
+
try {
|
|
796
|
+
if (queryCandidates_1_1 && !queryCandidates_1_1.done && (_c = queryCandidates_1.return)) _c.call(queryCandidates_1);
|
|
797
|
+
}
|
|
798
|
+
finally { if (e_3) throw e_3.error; }
|
|
799
|
+
}
|
|
800
|
+
return '';
|
|
801
|
+
};
|
|
802
|
+
ResolveIOMainServer.prototype.normalizeHeaderValue = function (value) {
|
|
803
|
+
if (Array.isArray(value)) {
|
|
804
|
+
return value.map(function (entry) { return "".concat(entry || '').trim(); }).filter(Boolean).join(',');
|
|
805
|
+
}
|
|
806
|
+
return "".concat(value || '').trim();
|
|
807
|
+
};
|
|
808
|
+
ResolveIOMainServer.prototype.normalizeHostname = function (value) {
|
|
809
|
+
var raw = "".concat(value || '').trim();
|
|
810
|
+
if (!raw) {
|
|
811
|
+
return '';
|
|
812
|
+
}
|
|
813
|
+
var candidate = raw.split(',')[0].trim();
|
|
814
|
+
if (!candidate) {
|
|
815
|
+
return '';
|
|
816
|
+
}
|
|
817
|
+
try {
|
|
818
|
+
if (candidate.startsWith('http://') || candidate.startsWith('https://')) {
|
|
819
|
+
return new url_1.URL(candidate).hostname.toLowerCase();
|
|
820
|
+
}
|
|
821
|
+
if (candidate.includes('/')) {
|
|
822
|
+
return new url_1.URL("http://".concat(candidate)).hostname.toLowerCase();
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
catch (_a) { }
|
|
826
|
+
candidate = candidate.replace(/^\[/, '').replace(/\]$/, '');
|
|
827
|
+
var lastColon = candidate.lastIndexOf(':');
|
|
828
|
+
if (lastColon > -1 && candidate.indexOf(':') === lastColon) {
|
|
829
|
+
candidate = candidate.slice(0, lastColon);
|
|
830
|
+
}
|
|
831
|
+
return candidate.toLowerCase();
|
|
832
|
+
};
|
|
833
|
+
ResolveIOMainServer.prototype.resolveOriginHostname = function (origin) {
|
|
834
|
+
var raw = "".concat(origin || '').trim();
|
|
835
|
+
if (!raw) {
|
|
836
|
+
return '';
|
|
837
|
+
}
|
|
838
|
+
try {
|
|
839
|
+
return new url_1.URL(raw).hostname.toLowerCase();
|
|
840
|
+
}
|
|
841
|
+
catch (_a) {
|
|
842
|
+
return this.normalizeHostname(raw);
|
|
843
|
+
}
|
|
844
|
+
};
|
|
845
|
+
ResolveIOMainServer.prototype.isLocalHostname = function (hostname) {
|
|
846
|
+
var normalized = this.normalizeHostname(hostname);
|
|
847
|
+
return normalized === 'localhost' || normalized === '127.0.0.1' || normalized === '::1';
|
|
848
|
+
};
|
|
849
|
+
ResolveIOMainServer.prototype.resolveDynamicAppControlHosts = function () {
|
|
850
|
+
var e_4, _a;
|
|
851
|
+
var config = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
|
|
852
|
+
var hosts = new Set();
|
|
853
|
+
var candidates = [
|
|
854
|
+
config['ROOT_URL'],
|
|
855
|
+
config['SEC_ROOT_URL'],
|
|
856
|
+
config['SERVER_URL'],
|
|
857
|
+
process.env.ROOT_URL,
|
|
858
|
+
process.env.SEC_ROOT_URL,
|
|
859
|
+
process.env.SERVER_URL,
|
|
860
|
+
process.env.AI_CODER_ROOT_URL,
|
|
861
|
+
process.env.AI_CODER_SEC_ROOT_URL,
|
|
862
|
+
process.env.AI_CODER_SERVER_URL
|
|
863
|
+
];
|
|
864
|
+
try {
|
|
865
|
+
for (var candidates_1 = __values(candidates), candidates_1_1 = candidates_1.next(); !candidates_1_1.done; candidates_1_1 = candidates_1.next()) {
|
|
866
|
+
var candidate = candidates_1_1.value;
|
|
867
|
+
var normalized = this.normalizeHostname("".concat(candidate || ''));
|
|
868
|
+
if (normalized) {
|
|
869
|
+
hosts.add(normalized);
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
874
|
+
finally {
|
|
875
|
+
try {
|
|
876
|
+
if (candidates_1_1 && !candidates_1_1.done && (_a = candidates_1.return)) _a.call(candidates_1);
|
|
877
|
+
}
|
|
878
|
+
finally { if (e_4) throw e_4.error; }
|
|
879
|
+
}
|
|
880
|
+
return hosts;
|
|
881
|
+
};
|
|
882
|
+
ResolveIOMainServer.prototype.resolveDynamicAppAllowedHosts = function (appDoc) {
|
|
883
|
+
var e_5, _a;
|
|
884
|
+
var hosts = new Set();
|
|
885
|
+
var candidates = [
|
|
886
|
+
appDoc === null || appDoc === void 0 ? void 0 : appDoc.domain,
|
|
887
|
+
appDoc === null || appDoc === void 0 ? void 0 : appDoc.backend_domain
|
|
888
|
+
];
|
|
889
|
+
if ((appDoc === null || appDoc === void 0 ? void 0 : appDoc.subdomain) && (appDoc === null || appDoc === void 0 ? void 0 : appDoc.domain_base)) {
|
|
890
|
+
candidates.push("".concat(appDoc.subdomain, ".").concat(appDoc.domain_base));
|
|
891
|
+
}
|
|
892
|
+
try {
|
|
893
|
+
for (var candidates_2 = __values(candidates), candidates_2_1 = candidates_2.next(); !candidates_2_1.done; candidates_2_1 = candidates_2.next()) {
|
|
894
|
+
var candidate = candidates_2_1.value;
|
|
895
|
+
var normalized = this.normalizeHostname("".concat(candidate || ''));
|
|
896
|
+
if (normalized) {
|
|
897
|
+
hosts.add(normalized);
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
|
902
|
+
finally {
|
|
903
|
+
try {
|
|
904
|
+
if (candidates_2_1 && !candidates_2_1.done && (_a = candidates_2.return)) _a.call(candidates_2);
|
|
905
|
+
}
|
|
906
|
+
finally { if (e_5) throw e_5.error; }
|
|
907
|
+
}
|
|
908
|
+
return hosts;
|
|
909
|
+
};
|
|
910
|
+
ResolveIOMainServer.prototype.applyDynamicAppGatewayCorsHeaders = function (res, origin) {
|
|
911
|
+
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
912
|
+
res.setHeader('Vary', 'Origin');
|
|
913
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');
|
|
914
|
+
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Rio-Token, X-API-Key');
|
|
915
|
+
res.setHeader('Access-Control-Allow-Credentials', 'true');
|
|
916
|
+
res.setHeader('Access-Control-Max-Age', '600');
|
|
917
|
+
};
|
|
918
|
+
ResolveIOMainServer.prototype.resolveCachedDynamicAppGatewayApp = function (appId) {
|
|
919
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
920
|
+
var now, cached, db, appCollection, appDoc, generated;
|
|
921
|
+
return __generator(this, function (_a) {
|
|
922
|
+
switch (_a.label) {
|
|
923
|
+
case 0:
|
|
924
|
+
now = Date.now();
|
|
925
|
+
cached = this._dynamicAppGatewayCache.get(appId);
|
|
926
|
+
if (cached && cached.expiresAt > now) {
|
|
927
|
+
return [2 /*return*/, cached.app];
|
|
928
|
+
}
|
|
929
|
+
db = resolveio_server_app_1.ResolveIOServer.getMainDB();
|
|
930
|
+
if (!db) {
|
|
931
|
+
return [2 /*return*/, null];
|
|
932
|
+
}
|
|
933
|
+
appCollection = db.collection('ai-coder-apps');
|
|
934
|
+
return [4 /*yield*/, appCollection.findOne({ _id: appId }, {
|
|
935
|
+
projection: {
|
|
936
|
+
_id: 1,
|
|
937
|
+
domain: 1,
|
|
938
|
+
backend_domain: 1,
|
|
939
|
+
subdomain: 1,
|
|
940
|
+
domain_base: 1,
|
|
941
|
+
rio_token: 1
|
|
942
|
+
}
|
|
943
|
+
})];
|
|
944
|
+
case 1:
|
|
945
|
+
appDoc = _a.sent();
|
|
946
|
+
if (!appDoc) {
|
|
947
|
+
this._dynamicAppGatewayCache.delete(appId);
|
|
948
|
+
return [2 /*return*/, null];
|
|
949
|
+
}
|
|
950
|
+
if (!!this.normalizeHeaderValue(appDoc.rio_token)) return [3 /*break*/, 3];
|
|
951
|
+
generated = crypto.randomBytes(32).toString('hex');
|
|
952
|
+
return [4 /*yield*/, appCollection.updateOne({ _id: appId }, {
|
|
953
|
+
$set: {
|
|
954
|
+
rio_token: generated,
|
|
955
|
+
updatedAt: new Date()
|
|
956
|
+
}
|
|
957
|
+
})];
|
|
958
|
+
case 2:
|
|
959
|
+
_a.sent();
|
|
960
|
+
appDoc.rio_token = generated;
|
|
961
|
+
_a.label = 3;
|
|
962
|
+
case 3:
|
|
963
|
+
this._dynamicAppGatewayCache.set(appId, {
|
|
964
|
+
expiresAt: now + this._dynamicAppGatewayCacheMs,
|
|
965
|
+
app: appDoc
|
|
966
|
+
});
|
|
967
|
+
return [2 /*return*/, appDoc];
|
|
968
|
+
}
|
|
969
|
+
});
|
|
970
|
+
});
|
|
971
|
+
};
|
|
580
972
|
ResolveIOMainServer.prototype.safeShutdown = function () {
|
|
581
973
|
return __awaiter(this, void 0, void 0, function () {
|
|
582
974
|
var _a;
|
|
@@ -760,36 +1152,44 @@ var ResolveIOMainServer = /** @class */ (function () {
|
|
|
760
1152
|
}
|
|
761
1153
|
else {
|
|
762
1154
|
jwt.verify(token, resolveio_server_app_1.ResolveIOServer.getServerConfig()['JWT_SECRET'], function (err, decoded) { return __awaiter(_this, void 0, void 0, function () {
|
|
763
|
-
var user, _a;
|
|
1155
|
+
var user, socketAdmission, _a;
|
|
764
1156
|
return __generator(this, function (_b) {
|
|
765
1157
|
switch (_b.label) {
|
|
766
1158
|
case 0:
|
|
767
1159
|
if (!err) return [3 /*break*/, 1];
|
|
768
1160
|
cb(false, 401, 'Unauthorized');
|
|
769
|
-
return [3 /*break*/,
|
|
1161
|
+
return [3 /*break*/, 8];
|
|
770
1162
|
case 1:
|
|
771
1163
|
info.req['id_user'] = decoded['id_user'];
|
|
772
1164
|
_b.label = 2;
|
|
773
1165
|
case 2:
|
|
774
|
-
_b.trys.push([2,
|
|
1166
|
+
_b.trys.push([2, 7, , 8]);
|
|
775
1167
|
return [4 /*yield*/, user_collection_1.Users.findById(decoded['id_user'])];
|
|
776
1168
|
case 3:
|
|
777
1169
|
user = _b.sent();
|
|
778
|
-
if (user)
|
|
779
|
-
|
|
780
|
-
info.req['user_readonly'] = user.readonly || false;
|
|
781
|
-
info.req['doc_user'] = user;
|
|
782
|
-
cb(true);
|
|
783
|
-
}
|
|
784
|
-
else {
|
|
785
|
-
cb(false);
|
|
786
|
-
}
|
|
787
|
-
return [3 /*break*/, 5];
|
|
1170
|
+
if (!user) return [3 /*break*/, 5];
|
|
1171
|
+
return [4 /*yield*/, this.evaluateClientSocketAdmission(decoded['id_user'], info.req)];
|
|
788
1172
|
case 4:
|
|
1173
|
+
socketAdmission = _b.sent();
|
|
1174
|
+
if (!socketAdmission.allowed) {
|
|
1175
|
+
cb(false, socketAdmission.statusCode, socketAdmission.message || 'Socket connection rejected.');
|
|
1176
|
+
return [2 /*return*/];
|
|
1177
|
+
}
|
|
1178
|
+
info.req['user'] = user.fullname;
|
|
1179
|
+
info.req['user_readonly'] = user.readonly || false;
|
|
1180
|
+
info.req['doc_user'] = user;
|
|
1181
|
+
info.req['client_ip'] = socketAdmission.clientIp;
|
|
1182
|
+
cb(true);
|
|
1183
|
+
return [3 /*break*/, 6];
|
|
1184
|
+
case 5:
|
|
1185
|
+
cb(false);
|
|
1186
|
+
_b.label = 6;
|
|
1187
|
+
case 6: return [3 /*break*/, 8];
|
|
1188
|
+
case 7:
|
|
789
1189
|
_a = _b.sent();
|
|
790
1190
|
cb(false);
|
|
791
|
-
return [3 /*break*/,
|
|
792
|
-
case
|
|
1191
|
+
return [3 /*break*/, 8];
|
|
1192
|
+
case 8: return [2 /*return*/];
|
|
793
1193
|
}
|
|
794
1194
|
});
|
|
795
1195
|
}); });
|
|
@@ -808,288 +1208,334 @@ var ResolveIOMainServer = /** @class */ (function () {
|
|
|
808
1208
|
this._serverHTTP.listen(this._portHTTP, host, function () {
|
|
809
1209
|
console.log('Running HTTP/WS server on port %s', _this._portHTTP);
|
|
810
1210
|
});
|
|
811
|
-
this._serverWSS.on('connection', function (ws, req) {
|
|
812
|
-
var
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
var rootUrl = resolveio_server_app_1.ResolveIOServer.getServerConfig()['ROOT_URL'] || 'http://localhost';
|
|
822
|
-
try {
|
|
823
|
-
var requestUrl = new url_1.URL(req.url, rootUrl);
|
|
824
|
-
workerIndex = requestUrl.searchParams.get('workerIndex');
|
|
825
|
-
workerInstance = requestUrl.searchParams.get('workerInstance');
|
|
826
|
-
}
|
|
827
|
-
catch (_c) {
|
|
1211
|
+
this._serverWSS.on('connection', function (ws, req) { return __awaiter(_this, void 0, void 0, function () {
|
|
1212
|
+
var workerId_1, workerIndex, workerInstance, rootUrl, requestUrl, workerIndexForLog, workerInstanceForLog, interval_1, lastComm_1, missedPongs_1, heartbeatIntervalMs, maxMissedPongs_1, maxSilenceMs_1, socketAdmission, socketPolicyError_1;
|
|
1213
|
+
var _this = this;
|
|
1214
|
+
var _a;
|
|
1215
|
+
return __generator(this, function (_b) {
|
|
1216
|
+
switch (_b.label) {
|
|
1217
|
+
case 0:
|
|
1218
|
+
if (!(req.url && req.url.includes('workerToken='))) return [3 /*break*/, 1];
|
|
1219
|
+
workerId_1 = (0, common_1.objectIdHexString)();
|
|
1220
|
+
ws['id_worker'] = workerId_1;
|
|
828
1221
|
workerIndex = null;
|
|
829
1222
|
workerInstance = null;
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
ws['workerInstance'] = workerInstance;
|
|
843
|
-
}
|
|
844
|
-
var workerIndexForLog = ws['workerIndex'] || 'UNKNOWN';
|
|
845
|
-
var workerInstanceForLog = ws['workerInstance'] || 'UNKNOWN';
|
|
846
|
-
console.log(new Date(), 'Worker Connected', workerIndexForLog, workerInstanceForLog);
|
|
847
|
-
_this._workerDispatcherManager.addWorker(ws);
|
|
848
|
-
var interval_1 = null;
|
|
849
|
-
var lastComm_1 = new Date();
|
|
850
|
-
var missedPongs_1 = 0;
|
|
851
|
-
var heartbeatIntervalMs = 30000;
|
|
852
|
-
var maxMissedPongs_1 = 2;
|
|
853
|
-
var maxSilenceMs_1 = heartbeatIntervalMs * (maxMissedPongs_1 + 1);
|
|
854
|
-
_this._workerDispatcherManager.sendWorkerPayload(ws, 'ping');
|
|
855
|
-
interval_1 = setInterval(function () {
|
|
856
|
-
var now = Date.now();
|
|
857
|
-
var last = lastComm_1 ? lastComm_1.getTime() : 0;
|
|
858
|
-
var silenceMs = last ? now - last : maxSilenceMs_1 + 1;
|
|
859
|
-
if (silenceMs > maxSilenceMs_1 || missedPongs_1 > maxMissedPongs_1) {
|
|
860
|
-
_this._workerDispatcherManager.disconnectWorker(ws['id_worker']);
|
|
861
|
-
ws.close();
|
|
862
|
-
return;
|
|
863
|
-
}
|
|
864
|
-
missedPongs_1 += 1;
|
|
865
|
-
_this._workerDispatcherManager.sendWorkerPayload(ws, 'ping');
|
|
866
|
-
}, heartbeatIntervalMs);
|
|
867
|
-
ws.on('message', function (message) {
|
|
868
|
-
lastComm_1 = new Date();
|
|
869
|
-
if (typeof message === 'string') {
|
|
870
|
-
if (message === 'ping') {
|
|
871
|
-
_this._workerDispatcherManager.sendWorkerPayload(ws, 'pong');
|
|
872
|
-
}
|
|
873
|
-
else if (message === 'pong') {
|
|
874
|
-
missedPongs_1 = 0;
|
|
1223
|
+
ws['supportsBinary'] = true;
|
|
1224
|
+
if (req.url) {
|
|
1225
|
+
rootUrl = resolveio_server_app_1.ResolveIOServer.getServerConfig()['ROOT_URL'] || 'http://localhost';
|
|
1226
|
+
try {
|
|
1227
|
+
requestUrl = new url_1.URL(req.url, rootUrl);
|
|
1228
|
+
workerIndex = requestUrl.searchParams.get('workerIndex');
|
|
1229
|
+
workerInstance = requestUrl.searchParams.get('workerInstance');
|
|
1230
|
+
}
|
|
1231
|
+
catch (_c) {
|
|
1232
|
+
workerIndex = null;
|
|
1233
|
+
workerInstance = null;
|
|
1234
|
+
}
|
|
875
1235
|
}
|
|
876
|
-
|
|
877
|
-
|
|
1236
|
+
if (!workerIndex && req['workerIndex']) {
|
|
1237
|
+
workerIndex = req['workerIndex'];
|
|
878
1238
|
}
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
var buffer;
|
|
882
|
-
if (Buffer.isBuffer(message)) {
|
|
883
|
-
buffer = message;
|
|
884
|
-
}
|
|
885
|
-
else if (Array.isArray(message)) {
|
|
886
|
-
var chunks = message;
|
|
887
|
-
buffer = Buffer.concat(chunks);
|
|
888
|
-
}
|
|
889
|
-
else if (message instanceof ArrayBuffer) {
|
|
890
|
-
buffer = Buffer.from(message);
|
|
891
|
-
}
|
|
892
|
-
else if (ArrayBuffer.isView(message)) {
|
|
893
|
-
var view = message;
|
|
894
|
-
buffer = Buffer.from(view.buffer, view.byteOffset, view.byteLength);
|
|
895
|
-
}
|
|
896
|
-
else {
|
|
897
|
-
buffer = Buffer.from(message);
|
|
898
|
-
}
|
|
899
|
-
if (buffer.length === 4) {
|
|
900
|
-
var heartbeat = buffer.toString('utf8');
|
|
901
|
-
if (heartbeat === 'ping') {
|
|
902
|
-
_this._workerDispatcherManager.sendWorkerPayload(ws, 'pong');
|
|
903
|
-
return;
|
|
1239
|
+
if (!workerInstance && req['workerInstance']) {
|
|
1240
|
+
workerInstance = req['workerInstance'];
|
|
904
1241
|
}
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
return;
|
|
1242
|
+
if (workerIndex !== null && workerIndex !== undefined) {
|
|
1243
|
+
ws['workerIndex'] = workerIndex;
|
|
908
1244
|
}
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
origin: (_b = req === null || req === void 0 ? void 0 : req.headers) === null || _b === void 0 ? void 0 : _b.origin
|
|
941
|
-
});
|
|
942
|
-
setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
943
|
-
return __generator(this, function (_a) {
|
|
944
|
-
switch (_a.label) {
|
|
945
|
-
case 0: return [4 /*yield*/, this.triggerClientHeartbeat(ws)];
|
|
946
|
-
case 1:
|
|
947
|
-
_a.sent();
|
|
948
|
-
return [2 /*return*/];
|
|
949
|
-
}
|
|
950
|
-
});
|
|
951
|
-
}); }, _this._clientHeartbeatInitialDelayMs);
|
|
952
|
-
if (_this.LOGGER === 'DEBUG') {
|
|
953
|
-
console.log('Connection from user: ' + req['user']);
|
|
954
|
-
}
|
|
955
|
-
ws['isAlive'] = true;
|
|
956
|
-
ws['retryCnt'] = 0;
|
|
957
|
-
ws.on('pong', function () {
|
|
958
|
-
ws['isAlive'] = true;
|
|
959
|
-
ws['pongTime'] = new Date();
|
|
960
|
-
if (ws['pingTime']) {
|
|
961
|
-
ws['latency'] = moment.duration(moment(ws['pongTime']).diff(ws['pingTime'])).asMilliseconds();
|
|
962
|
-
_this._subscriptionManager.loggedInLatency(ws);
|
|
963
|
-
}
|
|
964
|
-
});
|
|
965
|
-
ws.on('message', function (message) { return __awaiter(_this, void 0, void 0, function () {
|
|
966
|
-
var socketData, usedBinary, bufferPayload, decodeResult, decodeResult, decodeResult, view, decodeResult, e_1, correlationId, context;
|
|
967
|
-
return __generator(this, function (_a) {
|
|
968
|
-
switch (_a.label) {
|
|
969
|
-
case 0:
|
|
970
|
-
this._debugMsgRecv += 1;
|
|
971
|
-
socketData = [];
|
|
972
|
-
usedBinary = false;
|
|
973
|
-
_a.label = 1;
|
|
974
|
-
case 1:
|
|
975
|
-
_a.trys.push([1, 2, , 4]);
|
|
976
|
-
if (typeof message === 'string') {
|
|
977
|
-
if (message === 'ping' || message === 'pong') {
|
|
978
|
-
socketData = message;
|
|
979
|
-
}
|
|
980
|
-
else {
|
|
981
|
-
socketData = JSON.parse(message, common_1.dateReviver);
|
|
982
|
-
}
|
|
983
|
-
}
|
|
984
|
-
else if (Buffer.isBuffer(message)) {
|
|
985
|
-
bufferPayload = message;
|
|
986
|
-
decodeResult = this.decodeBufferPayload(bufferPayload);
|
|
987
|
-
socketData = decodeResult.data;
|
|
988
|
-
usedBinary = decodeResult.usedBinary;
|
|
1245
|
+
if (workerInstance !== null && workerInstance !== undefined) {
|
|
1246
|
+
ws['workerInstance'] = workerInstance;
|
|
1247
|
+
}
|
|
1248
|
+
workerIndexForLog = ws['workerIndex'] || 'UNKNOWN';
|
|
1249
|
+
workerInstanceForLog = ws['workerInstance'] || 'UNKNOWN';
|
|
1250
|
+
console.log(new Date(), 'Worker Connected', workerIndexForLog, workerInstanceForLog);
|
|
1251
|
+
this._workerDispatcherManager.addWorker(ws);
|
|
1252
|
+
interval_1 = null;
|
|
1253
|
+
lastComm_1 = new Date();
|
|
1254
|
+
missedPongs_1 = 0;
|
|
1255
|
+
heartbeatIntervalMs = 30000;
|
|
1256
|
+
maxMissedPongs_1 = 2;
|
|
1257
|
+
maxSilenceMs_1 = heartbeatIntervalMs * (maxMissedPongs_1 + 1);
|
|
1258
|
+
this._workerDispatcherManager.sendWorkerPayload(ws, 'ping');
|
|
1259
|
+
interval_1 = setInterval(function () {
|
|
1260
|
+
var now = Date.now();
|
|
1261
|
+
var last = lastComm_1 ? lastComm_1.getTime() : 0;
|
|
1262
|
+
var silenceMs = last ? now - last : maxSilenceMs_1 + 1;
|
|
1263
|
+
if (silenceMs > maxSilenceMs_1 || missedPongs_1 > maxMissedPongs_1) {
|
|
1264
|
+
_this._workerDispatcherManager.disconnectWorker(ws['id_worker']);
|
|
1265
|
+
ws.close();
|
|
1266
|
+
return;
|
|
1267
|
+
}
|
|
1268
|
+
missedPongs_1 += 1;
|
|
1269
|
+
_this._workerDispatcherManager.sendWorkerPayload(ws, 'ping');
|
|
1270
|
+
}, heartbeatIntervalMs);
|
|
1271
|
+
ws.on('message', function (message) {
|
|
1272
|
+
lastComm_1 = new Date();
|
|
1273
|
+
if (typeof message === 'string') {
|
|
1274
|
+
if (message === 'ping') {
|
|
1275
|
+
_this._workerDispatcherManager.sendWorkerPayload(ws, 'pong');
|
|
989
1276
|
}
|
|
990
|
-
else if (
|
|
991
|
-
|
|
992
|
-
decodeResult = this.decodeBufferPayload(bufferPayload);
|
|
993
|
-
socketData = decodeResult.data;
|
|
994
|
-
usedBinary = decodeResult.usedBinary;
|
|
1277
|
+
else if (message === 'pong') {
|
|
1278
|
+
missedPongs_1 = 0;
|
|
995
1279
|
}
|
|
996
|
-
else
|
|
997
|
-
|
|
998
|
-
decodeResult = this.decodeBufferPayload(bufferPayload);
|
|
999
|
-
socketData = decodeResult.data;
|
|
1000
|
-
usedBinary = decodeResult.usedBinary;
|
|
1280
|
+
else {
|
|
1281
|
+
_this._workerDispatcherManager.handleWorkerMessage(ws['id_worker'], message);
|
|
1001
1282
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1283
|
+
return;
|
|
1284
|
+
}
|
|
1285
|
+
var buffer;
|
|
1286
|
+
if (Buffer.isBuffer(message)) {
|
|
1287
|
+
buffer = message;
|
|
1288
|
+
}
|
|
1289
|
+
else if (Array.isArray(message)) {
|
|
1290
|
+
var chunks = message;
|
|
1291
|
+
buffer = Buffer.concat(chunks);
|
|
1292
|
+
}
|
|
1293
|
+
else if (message instanceof ArrayBuffer) {
|
|
1294
|
+
buffer = Buffer.from(message);
|
|
1295
|
+
}
|
|
1296
|
+
else if (ArrayBuffer.isView(message)) {
|
|
1297
|
+
var view = message;
|
|
1298
|
+
buffer = Buffer.from(view.buffer, view.byteOffset, view.byteLength);
|
|
1299
|
+
}
|
|
1300
|
+
else {
|
|
1301
|
+
buffer = Buffer.from(message);
|
|
1302
|
+
}
|
|
1303
|
+
if (buffer.length === 4) {
|
|
1304
|
+
var heartbeat = buffer.toString('utf8');
|
|
1305
|
+
if (heartbeat === 'ping') {
|
|
1306
|
+
_this._workerDispatcherManager.sendWorkerPayload(ws, 'pong');
|
|
1307
|
+
return;
|
|
1008
1308
|
}
|
|
1009
|
-
else {
|
|
1010
|
-
|
|
1309
|
+
else if (heartbeat === 'pong') {
|
|
1310
|
+
missedPongs_1 = 0;
|
|
1311
|
+
return;
|
|
1011
1312
|
}
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1313
|
+
}
|
|
1314
|
+
_this._workerDispatcherManager.handleWorkerMessage(ws['id_worker'], buffer);
|
|
1315
|
+
});
|
|
1316
|
+
ws.on('close', function () {
|
|
1317
|
+
_this._workerDispatcherManager.disconnectWorker(ws['id_worker']);
|
|
1318
|
+
console.log(new Date(), 'Worker disconnected:', workerId_1);
|
|
1319
|
+
if (interval_1) {
|
|
1320
|
+
clearInterval(interval_1);
|
|
1321
|
+
}
|
|
1322
|
+
});
|
|
1323
|
+
ws.on('error', function (error) {
|
|
1324
|
+
_this._workerDispatcherManager.disconnectWorker(ws['id_worker']);
|
|
1325
|
+
console.error('Error on WS Worker', error);
|
|
1326
|
+
ws.close();
|
|
1327
|
+
});
|
|
1328
|
+
return [3 /*break*/, 6];
|
|
1329
|
+
case 1:
|
|
1330
|
+
// Normal client
|
|
1331
|
+
ws['id_socket'] = (0, common_1.objectIdHexString)();
|
|
1332
|
+
ws['supportsBinary'] = true;
|
|
1333
|
+
ws['id_user'] = req['id_user'];
|
|
1334
|
+
ws['user'] = req['user'];
|
|
1335
|
+
ws['user_readonly'] = req['user_readonly'];
|
|
1336
|
+
ws['doc_user'] = req['doc_user'];
|
|
1337
|
+
ws['client_ip'] = this.resolveClientIp(req);
|
|
1338
|
+
socketAdmission = void 0;
|
|
1339
|
+
_b.label = 2;
|
|
1340
|
+
case 2:
|
|
1341
|
+
_b.trys.push([2, 4, , 5]);
|
|
1342
|
+
return [4 /*yield*/, this.evaluateClientSocketAdmission(ws['id_user'], req)];
|
|
1343
|
+
case 3:
|
|
1344
|
+
socketAdmission = _b.sent();
|
|
1345
|
+
return [3 /*break*/, 5];
|
|
1346
|
+
case 4:
|
|
1347
|
+
socketPolicyError_1 = _b.sent();
|
|
1348
|
+
this.logConnectDebug('WS socket policy evaluation failed', {
|
|
1349
|
+
id_socket: ws['id_socket'],
|
|
1350
|
+
id_user: ws['id_user'],
|
|
1351
|
+
user: ws['user'],
|
|
1352
|
+
ip: ws['client_ip'],
|
|
1353
|
+
error: (socketPolicyError_1 === null || socketPolicyError_1 === void 0 ? void 0 : socketPolicyError_1.message) || socketPolicyError_1
|
|
1354
|
+
});
|
|
1355
|
+
try {
|
|
1356
|
+
ws.close(1011, 'Socket policy error');
|
|
1357
|
+
}
|
|
1358
|
+
catch (_d) { }
|
|
1359
|
+
return [2 /*return*/];
|
|
1360
|
+
case 5:
|
|
1361
|
+
if (!socketAdmission.allowed) {
|
|
1362
|
+
this.logConnectDebug('WS client rejected', {
|
|
1363
|
+
id_socket: ws['id_socket'],
|
|
1364
|
+
id_user: ws['id_user'],
|
|
1365
|
+
user: ws['user'],
|
|
1366
|
+
ip: ws['client_ip'],
|
|
1367
|
+
reason: socketAdmission.message
|
|
1368
|
+
});
|
|
1369
|
+
try {
|
|
1370
|
+
ws.close(1008, this.buildSocketLimitCloseReason());
|
|
1371
|
+
}
|
|
1372
|
+
catch (_e) { }
|
|
1373
|
+
return [2 /*return*/];
|
|
1374
|
+
}
|
|
1375
|
+
ws['client_ip'] = socketAdmission.clientIp || ws['client_ip'];
|
|
1376
|
+
this._websocketManager.addWebSocket(ws);
|
|
1377
|
+
this.logConnectDebug('WS client connected', {
|
|
1378
|
+
id_socket: ws['id_socket'],
|
|
1379
|
+
id_user: ws['id_user'],
|
|
1380
|
+
user: ws['user'],
|
|
1381
|
+
url: req === null || req === void 0 ? void 0 : req.url,
|
|
1382
|
+
ip: ws['client_ip'],
|
|
1383
|
+
origin: (_a = req === null || req === void 0 ? void 0 : req.headers) === null || _a === void 0 ? void 0 : _a.origin
|
|
1384
|
+
});
|
|
1385
|
+
setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
1386
|
+
return __generator(this, function (_a) {
|
|
1387
|
+
switch (_a.label) {
|
|
1388
|
+
case 0: return [4 /*yield*/, this.triggerClientHeartbeat(ws)];
|
|
1389
|
+
case 1:
|
|
1390
|
+
_a.sent();
|
|
1391
|
+
return [2 /*return*/];
|
|
1029
1392
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
_a.sent();
|
|
1035
|
-
return [2 /*return*/];
|
|
1036
|
-
}
|
|
1037
|
-
});
|
|
1038
|
-
}); })
|
|
1039
|
-
.on('end', function () {
|
|
1040
|
-
ws.close();
|
|
1041
|
-
})
|
|
1042
|
-
.on('error', function () {
|
|
1043
|
-
ws.close();
|
|
1044
|
-
})
|
|
1045
|
-
.on('close', function () { return __awaiter(_this, void 0, void 0, function () {
|
|
1046
|
-
return __generator(this, function (_a) {
|
|
1047
|
-
switch (_a.label) {
|
|
1048
|
-
case 0:
|
|
1049
|
-
this.logConnectDebug('WS client closed', {
|
|
1050
|
-
id_socket: ws['id_socket'],
|
|
1051
|
-
id_user: ws['id_user'],
|
|
1052
|
-
user: ws['user']
|
|
1053
|
-
});
|
|
1054
|
-
return [4 /*yield*/, this.unsubscribeWS(ws)];
|
|
1055
|
-
case 1:
|
|
1056
|
-
_a.sent();
|
|
1057
|
-
return [2 /*return*/];
|
|
1058
|
-
}
|
|
1059
|
-
});
|
|
1060
|
-
}); });
|
|
1061
|
-
// Do not block message handler registration on DB write; this avoids losing
|
|
1062
|
-
// very-early subscription messages sent immediately after websocket open.
|
|
1063
|
-
setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
1064
|
-
var error_4;
|
|
1065
|
-
return __generator(this, function (_a) {
|
|
1066
|
-
switch (_a.label) {
|
|
1067
|
-
case 0:
|
|
1068
|
-
_a.trys.push([0, 2, , 3]);
|
|
1069
|
-
return [4 /*yield*/, this._subscriptionManager.createLoggedInUser(ws['id_socket'])];
|
|
1070
|
-
case 1:
|
|
1071
|
-
_a.sent();
|
|
1072
|
-
return [3 /*break*/, 3];
|
|
1073
|
-
case 2:
|
|
1074
|
-
error_4 = _a.sent();
|
|
1075
|
-
console.error(new Date(), 'Error creating logged-in user', ws['id_socket'], error_4);
|
|
1076
|
-
this.logConnectDebug('Create logged-in user failed', {
|
|
1077
|
-
id_socket: ws['id_socket'],
|
|
1078
|
-
id_user: ws['id_user'],
|
|
1079
|
-
user: ws['user'],
|
|
1080
|
-
error: (error_4 === null || error_4 === void 0 ? void 0 : error_4.message) || error_4
|
|
1081
|
-
});
|
|
1082
|
-
return [3 /*break*/, 3];
|
|
1083
|
-
case 3: return [2 /*return*/];
|
|
1393
|
+
});
|
|
1394
|
+
}); }, this._clientHeartbeatInitialDelayMs);
|
|
1395
|
+
if (this.LOGGER === 'DEBUG') {
|
|
1396
|
+
console.log('Connection from user: ' + req['user']);
|
|
1084
1397
|
}
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1398
|
+
ws['isAlive'] = true;
|
|
1399
|
+
ws['retryCnt'] = 0;
|
|
1400
|
+
ws.on('pong', function () {
|
|
1401
|
+
ws['isAlive'] = true;
|
|
1402
|
+
ws['pongTime'] = new Date();
|
|
1403
|
+
if (ws['pingTime']) {
|
|
1404
|
+
ws['latency'] = moment.duration(moment(ws['pongTime']).diff(ws['pingTime'])).asMilliseconds();
|
|
1405
|
+
_this._subscriptionManager.loggedInLatency(ws);
|
|
1406
|
+
}
|
|
1407
|
+
});
|
|
1408
|
+
ws.on('message', function (message) { return __awaiter(_this, void 0, void 0, function () {
|
|
1409
|
+
var socketData, usedBinary, bufferPayload, decodeResult, decodeResult, decodeResult, view, decodeResult, e_6, correlationId, context;
|
|
1410
|
+
return __generator(this, function (_a) {
|
|
1411
|
+
switch (_a.label) {
|
|
1412
|
+
case 0:
|
|
1413
|
+
this._debugMsgRecv += 1;
|
|
1414
|
+
socketData = [];
|
|
1415
|
+
usedBinary = false;
|
|
1416
|
+
_a.label = 1;
|
|
1417
|
+
case 1:
|
|
1418
|
+
_a.trys.push([1, 2, , 4]);
|
|
1419
|
+
if (typeof message === 'string') {
|
|
1420
|
+
if (message === 'ping' || message === 'pong') {
|
|
1421
|
+
socketData = message;
|
|
1422
|
+
}
|
|
1423
|
+
else {
|
|
1424
|
+
socketData = JSON.parse(message, common_1.dateReviver);
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
else if (Buffer.isBuffer(message)) {
|
|
1428
|
+
bufferPayload = message;
|
|
1429
|
+
decodeResult = this.decodeBufferPayload(bufferPayload);
|
|
1430
|
+
socketData = decodeResult.data;
|
|
1431
|
+
usedBinary = decodeResult.usedBinary;
|
|
1432
|
+
}
|
|
1433
|
+
else if (Array.isArray(message)) {
|
|
1434
|
+
bufferPayload = Buffer.concat(message);
|
|
1435
|
+
decodeResult = this.decodeBufferPayload(bufferPayload);
|
|
1436
|
+
socketData = decodeResult.data;
|
|
1437
|
+
usedBinary = decodeResult.usedBinary;
|
|
1438
|
+
}
|
|
1439
|
+
else if (message instanceof ArrayBuffer) {
|
|
1440
|
+
bufferPayload = Buffer.from(message);
|
|
1441
|
+
decodeResult = this.decodeBufferPayload(bufferPayload);
|
|
1442
|
+
socketData = decodeResult.data;
|
|
1443
|
+
usedBinary = decodeResult.usedBinary;
|
|
1444
|
+
}
|
|
1445
|
+
else if (ArrayBuffer.isView(message)) {
|
|
1446
|
+
view = message;
|
|
1447
|
+
bufferPayload = Buffer.from(view.buffer, view.byteOffset, view.byteLength);
|
|
1448
|
+
decodeResult = this.decodeBufferPayload(bufferPayload);
|
|
1449
|
+
socketData = decodeResult.data;
|
|
1450
|
+
usedBinary = decodeResult.usedBinary;
|
|
1451
|
+
}
|
|
1452
|
+
else {
|
|
1453
|
+
throw new Error('Unsupported WebSocket message type: ' + typeof message);
|
|
1454
|
+
}
|
|
1455
|
+
return [3 /*break*/, 4];
|
|
1456
|
+
case 2:
|
|
1457
|
+
e_6 = _a.sent();
|
|
1458
|
+
console.log('Error - WS message parse', e_6);
|
|
1459
|
+
correlationId = (0, common_1.objectIdHexString)();
|
|
1460
|
+
context = {
|
|
1461
|
+
rawBinary: bufferPayload ? bufferPayload.toString('base64') : undefined,
|
|
1462
|
+
rawMessage: typeof message === 'string' ? message : undefined,
|
|
1463
|
+
error: e_6 instanceof Error ? { name: e_6.name, message: e_6.message, stack: e_6.stack } : e_6
|
|
1464
|
+
};
|
|
1465
|
+
return [4 /*yield*/, this.reportServerError('SERVER - JSON Parse Error - ' + resolveio_server_app_1.ResolveIOServer.getServerConfig()['CLIENT_NAME'], correlationId, context, { context: 'websocket-message-parse' }, 'error', e_6 instanceof Error ? e_6.stack : undefined)];
|
|
1466
|
+
case 3:
|
|
1467
|
+
_a.sent();
|
|
1468
|
+
return [2 /*return*/];
|
|
1469
|
+
case 4:
|
|
1470
|
+
if (usedBinary) {
|
|
1471
|
+
ws['supportsBinary'] = true;
|
|
1472
|
+
}
|
|
1473
|
+
// call our existing processSocketMessage
|
|
1474
|
+
return [4 /*yield*/, this.processSocketMessage(ws, socketData)];
|
|
1475
|
+
case 5:
|
|
1476
|
+
// call our existing processSocketMessage
|
|
1477
|
+
_a.sent();
|
|
1478
|
+
return [2 /*return*/];
|
|
1479
|
+
}
|
|
1480
|
+
});
|
|
1481
|
+
}); })
|
|
1482
|
+
.on('end', function () {
|
|
1483
|
+
ws.close();
|
|
1484
|
+
})
|
|
1485
|
+
.on('error', function () {
|
|
1486
|
+
ws.close();
|
|
1487
|
+
})
|
|
1488
|
+
.on('close', function () { return __awaiter(_this, void 0, void 0, function () {
|
|
1489
|
+
return __generator(this, function (_a) {
|
|
1490
|
+
switch (_a.label) {
|
|
1491
|
+
case 0:
|
|
1492
|
+
this.logConnectDebug('WS client closed', {
|
|
1493
|
+
id_socket: ws['id_socket'],
|
|
1494
|
+
id_user: ws['id_user'],
|
|
1495
|
+
user: ws['user']
|
|
1496
|
+
});
|
|
1497
|
+
return [4 /*yield*/, this.unsubscribeWS(ws)];
|
|
1498
|
+
case 1:
|
|
1499
|
+
_a.sent();
|
|
1500
|
+
return [2 /*return*/];
|
|
1501
|
+
}
|
|
1502
|
+
});
|
|
1503
|
+
}); });
|
|
1504
|
+
// Do not block message handler registration on DB write; this avoids losing
|
|
1505
|
+
// very-early subscription messages sent immediately after websocket open.
|
|
1506
|
+
setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
1507
|
+
var error_5;
|
|
1508
|
+
return __generator(this, function (_a) {
|
|
1509
|
+
switch (_a.label) {
|
|
1510
|
+
case 0:
|
|
1511
|
+
_a.trys.push([0, 2, , 3]);
|
|
1512
|
+
return [4 /*yield*/, this._subscriptionManager.createLoggedInUser(ws['id_socket'])];
|
|
1513
|
+
case 1:
|
|
1514
|
+
_a.sent();
|
|
1515
|
+
return [3 /*break*/, 3];
|
|
1516
|
+
case 2:
|
|
1517
|
+
error_5 = _a.sent();
|
|
1518
|
+
console.error(new Date(), 'Error creating logged-in user', ws['id_socket'], error_5);
|
|
1519
|
+
this.logConnectDebug('Create logged-in user failed', {
|
|
1520
|
+
id_socket: ws['id_socket'],
|
|
1521
|
+
id_user: ws['id_user'],
|
|
1522
|
+
user: ws['user'],
|
|
1523
|
+
error: (error_5 === null || error_5 === void 0 ? void 0 : error_5.message) || error_5
|
|
1524
|
+
});
|
|
1525
|
+
return [3 /*break*/, 3];
|
|
1526
|
+
case 3: return [2 /*return*/];
|
|
1527
|
+
}
|
|
1528
|
+
});
|
|
1529
|
+
}); }, 0);
|
|
1530
|
+
_b.label = 6;
|
|
1531
|
+
case 6: return [2 /*return*/];
|
|
1532
|
+
}
|
|
1533
|
+
});
|
|
1534
|
+
}); });
|
|
1089
1535
|
// Keep alive timer
|
|
1090
1536
|
setInterval(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
1091
|
-
var _a, _b, ws,
|
|
1092
|
-
var
|
|
1537
|
+
var _a, _b, ws, e_7_1;
|
|
1538
|
+
var e_7, _c;
|
|
1093
1539
|
return __generator(this, function (_d) {
|
|
1094
1540
|
switch (_d.label) {
|
|
1095
1541
|
case 0:
|
|
@@ -1130,14 +1576,14 @@ var ResolveIOMainServer = /** @class */ (function () {
|
|
|
1130
1576
|
return [3 /*break*/, 1];
|
|
1131
1577
|
case 9: return [3 /*break*/, 12];
|
|
1132
1578
|
case 10:
|
|
1133
|
-
|
|
1134
|
-
|
|
1579
|
+
e_7_1 = _d.sent();
|
|
1580
|
+
e_7 = { error: e_7_1 };
|
|
1135
1581
|
return [3 /*break*/, 12];
|
|
1136
1582
|
case 11:
|
|
1137
1583
|
try {
|
|
1138
1584
|
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
|
|
1139
1585
|
}
|
|
1140
|
-
finally { if (
|
|
1586
|
+
finally { if (e_7) throw e_7.error; }
|
|
1141
1587
|
return [7 /*endfinally*/];
|
|
1142
1588
|
case 12: return [2 /*return*/];
|
|
1143
1589
|
}
|
|
@@ -1146,8 +1592,8 @@ var ResolveIOMainServer = /** @class */ (function () {
|
|
|
1146
1592
|
};
|
|
1147
1593
|
ResolveIOMainServer.prototype.processSocketMessage = function (ws, socketData) {
|
|
1148
1594
|
return __awaiter(this, void 0, void 0, function () {
|
|
1149
|
-
var socketData_1, socketData_1_1, message,
|
|
1150
|
-
var
|
|
1595
|
+
var socketData_1, socketData_1_1, message, e_8_1;
|
|
1596
|
+
var e_8, _a;
|
|
1151
1597
|
return __generator(this, function (_b) {
|
|
1152
1598
|
switch (_b.label) {
|
|
1153
1599
|
case 0:
|
|
@@ -1191,14 +1637,14 @@ var ResolveIOMainServer = /** @class */ (function () {
|
|
|
1191
1637
|
return [3 /*break*/, 2];
|
|
1192
1638
|
case 5: return [3 /*break*/, 8];
|
|
1193
1639
|
case 6:
|
|
1194
|
-
|
|
1195
|
-
|
|
1640
|
+
e_8_1 = _b.sent();
|
|
1641
|
+
e_8 = { error: e_8_1 };
|
|
1196
1642
|
return [3 /*break*/, 8];
|
|
1197
1643
|
case 7:
|
|
1198
1644
|
try {
|
|
1199
1645
|
if (socketData_1_1 && !socketData_1_1.done && (_a = socketData_1.return)) _a.call(socketData_1);
|
|
1200
1646
|
}
|
|
1201
|
-
finally { if (
|
|
1647
|
+
finally { if (e_8) throw e_8.error; }
|
|
1202
1648
|
return [7 /*endfinally*/];
|
|
1203
1649
|
case 8: return [2 /*return*/];
|
|
1204
1650
|
}
|
|
@@ -1605,6 +2051,267 @@ var ResolveIOMainServer = /** @class */ (function () {
|
|
|
1605
2051
|
}
|
|
1606
2052
|
return false;
|
|
1607
2053
|
};
|
|
2054
|
+
ResolveIOMainServer.prototype.parseOptionalBoolean = function (value) {
|
|
2055
|
+
if (value === null || value === undefined) {
|
|
2056
|
+
return null;
|
|
2057
|
+
}
|
|
2058
|
+
var normalized = "".concat(value).trim();
|
|
2059
|
+
if (!normalized) {
|
|
2060
|
+
return null;
|
|
2061
|
+
}
|
|
2062
|
+
return this.parseDebugFlag(normalized);
|
|
2063
|
+
};
|
|
2064
|
+
ResolveIOMainServer.prototype.parseNonNegativeInt = function (value, fallback) {
|
|
2065
|
+
var parsed = parseInt("".concat(value !== null && value !== void 0 ? value : ''), 10);
|
|
2066
|
+
if (Number.isNaN(parsed) || parsed < 0) {
|
|
2067
|
+
return fallback;
|
|
2068
|
+
}
|
|
2069
|
+
return parsed;
|
|
2070
|
+
};
|
|
2071
|
+
ResolveIOMainServer.prototype.resolveSocketTier = function () {
|
|
2072
|
+
var config = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
|
|
2073
|
+
return "".concat(process.env.AI_CODER_PLAN_TIER || config['AI_CODER_PLAN_TIER'] || '').trim().toLowerCase();
|
|
2074
|
+
};
|
|
2075
|
+
ResolveIOMainServer.prototype.resolveSocketTierKeySuffix = function (planTier) {
|
|
2076
|
+
return "".concat(planTier || '')
|
|
2077
|
+
.trim()
|
|
2078
|
+
.toUpperCase()
|
|
2079
|
+
.replace(/[^A-Z0-9]+/g, '_');
|
|
2080
|
+
};
|
|
2081
|
+
ResolveIOMainServer.prototype.resolveMaxClientSockets = function (planTier) {
|
|
2082
|
+
var _a, _b, _c;
|
|
2083
|
+
var config = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
|
|
2084
|
+
var explicitLimit = this.parseNonNegativeInt((_a = config['AI_CODER_MAX_SOCKETS']) !== null && _a !== void 0 ? _a : process.env.AI_CODER_MAX_SOCKETS, -1);
|
|
2085
|
+
if (explicitLimit >= 0) {
|
|
2086
|
+
return explicitLimit;
|
|
2087
|
+
}
|
|
2088
|
+
var normalizedTier = "".concat(planTier || '').trim().toLowerCase();
|
|
2089
|
+
var tierKeySuffix = this.resolveSocketTierKeySuffix(normalizedTier);
|
|
2090
|
+
if (tierKeySuffix) {
|
|
2091
|
+
var tierLimitKey = "AI_CODER_MAX_SOCKETS_".concat(tierKeySuffix);
|
|
2092
|
+
var tierLimit = this.parseNonNegativeInt((_b = config[tierLimitKey]) !== null && _b !== void 0 ? _b : process.env[tierLimitKey], -1);
|
|
2093
|
+
if (tierLimit >= 0) {
|
|
2094
|
+
return tierLimit;
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
var maxUsers = this.parseNonNegativeInt((_c = config['AI_CODER_MAX_USERS']) !== null && _c !== void 0 ? _c : process.env.AI_CODER_MAX_USERS, -1);
|
|
2098
|
+
if (maxUsers > 0) {
|
|
2099
|
+
return maxUsers === 1 ? 1 : maxUsers * 2;
|
|
2100
|
+
}
|
|
2101
|
+
if (normalizedTier === 'tool') {
|
|
2102
|
+
return 1;
|
|
2103
|
+
}
|
|
2104
|
+
if (normalizedTier === 'small') {
|
|
2105
|
+
return 10;
|
|
2106
|
+
}
|
|
2107
|
+
if (normalizedTier === 'medium') {
|
|
2108
|
+
return 50;
|
|
2109
|
+
}
|
|
2110
|
+
if (normalizedTier === 'large') {
|
|
2111
|
+
return 200;
|
|
2112
|
+
}
|
|
2113
|
+
if (normalizedTier === 'enterprise') {
|
|
2114
|
+
return 0;
|
|
2115
|
+
}
|
|
2116
|
+
return 0;
|
|
2117
|
+
};
|
|
2118
|
+
ResolveIOMainServer.prototype.resolveSingleIpPerUserPolicy = function (planTier) {
|
|
2119
|
+
var _a, _b;
|
|
2120
|
+
var config = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
|
|
2121
|
+
var normalizedTier = "".concat(planTier || '').trim().toLowerCase();
|
|
2122
|
+
var tierKeySuffix = this.resolveSocketTierKeySuffix(normalizedTier);
|
|
2123
|
+
if (tierKeySuffix) {
|
|
2124
|
+
var tierPolicyKey = "AI_CODER_SINGLE_IP_PER_USER_".concat(tierKeySuffix);
|
|
2125
|
+
var tierPolicy = this.parseOptionalBoolean((_a = config[tierPolicyKey]) !== null && _a !== void 0 ? _a : process.env[tierPolicyKey]);
|
|
2126
|
+
if (tierPolicy !== null) {
|
|
2127
|
+
return tierPolicy;
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
var policy = this.parseOptionalBoolean((_b = config['AI_CODER_SINGLE_IP_PER_USER']) !== null && _b !== void 0 ? _b : process.env.AI_CODER_SINGLE_IP_PER_USER);
|
|
2131
|
+
if (policy !== null) {
|
|
2132
|
+
return policy;
|
|
2133
|
+
}
|
|
2134
|
+
return !!normalizedTier;
|
|
2135
|
+
};
|
|
2136
|
+
ResolveIOMainServer.prototype.resolveSocketPolicyUpgradeUrl = function () {
|
|
2137
|
+
var config = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
|
|
2138
|
+
var direct = "".concat(config['AI_CODER_SOCKET_UPGRADE_URL'] || process.env.AI_CODER_SOCKET_UPGRADE_URL || '').trim();
|
|
2139
|
+
if (direct) {
|
|
2140
|
+
return direct.replace(/\/$/, '');
|
|
2141
|
+
}
|
|
2142
|
+
var dashboard = "".concat(config['AI_CODER_CLIENT_DASHBOARD_URL'] || process.env.AI_CODER_CLIENT_DASHBOARD_URL || '').trim();
|
|
2143
|
+
if (dashboard) {
|
|
2144
|
+
return dashboard.replace(/\/$/, '');
|
|
2145
|
+
}
|
|
2146
|
+
var root = "".concat(config['AI_CODER_ROOT_URL'] || process.env.AI_CODER_ROOT_URL || config['ROOT_URL'] || process.env.ROOT_URL || '').trim();
|
|
2147
|
+
if (!root) {
|
|
2148
|
+
return '';
|
|
2149
|
+
}
|
|
2150
|
+
return "".concat(root.replace(/\/$/, ''), "/dashboard/client");
|
|
2151
|
+
};
|
|
2152
|
+
ResolveIOMainServer.prototype.resolveSocketUpgradeUrlWithAppId = function () {
|
|
2153
|
+
var base = "".concat(this._socketPolicyUpgradeUrl || '').trim();
|
|
2154
|
+
if (!base) {
|
|
2155
|
+
return '';
|
|
2156
|
+
}
|
|
2157
|
+
var appId = "".concat(process.env.AI_CODER_APP_ID || '').trim();
|
|
2158
|
+
if (!appId) {
|
|
2159
|
+
return base;
|
|
2160
|
+
}
|
|
2161
|
+
var separator = base.includes('?') ? '&' : '?';
|
|
2162
|
+
return "".concat(base).concat(separator, "appId=").concat(encodeURIComponent(appId));
|
|
2163
|
+
};
|
|
2164
|
+
ResolveIOMainServer.prototype.normalizeIpAddress = function (value) {
|
|
2165
|
+
var ip = "".concat(value || '').trim();
|
|
2166
|
+
if (!ip) {
|
|
2167
|
+
return '';
|
|
2168
|
+
}
|
|
2169
|
+
if (ip.includes(',')) {
|
|
2170
|
+
ip = ip.split(',')[0].trim();
|
|
2171
|
+
}
|
|
2172
|
+
if (ip.startsWith('::ffff:')) {
|
|
2173
|
+
ip = ip.slice(7);
|
|
2174
|
+
}
|
|
2175
|
+
if (/^\d+\.\d+\.\d+\.\d+:\d+$/.test(ip)) {
|
|
2176
|
+
ip = ip.split(':')[0].trim();
|
|
2177
|
+
}
|
|
2178
|
+
if (ip === '::1') {
|
|
2179
|
+
return '127.0.0.1';
|
|
2180
|
+
}
|
|
2181
|
+
return ip.toLowerCase();
|
|
2182
|
+
};
|
|
2183
|
+
ResolveIOMainServer.prototype.resolveClientIp = function (req) {
|
|
2184
|
+
var _a, _b, _c, _d;
|
|
2185
|
+
var forwardedFor = this.normalizeHeaderValue((_a = req === null || req === void 0 ? void 0 : req.headers) === null || _a === void 0 ? void 0 : _a['x-forwarded-for']);
|
|
2186
|
+
if (forwardedFor) {
|
|
2187
|
+
return this.normalizeIpAddress(forwardedFor);
|
|
2188
|
+
}
|
|
2189
|
+
var realIp = this.normalizeHeaderValue((_b = req === null || req === void 0 ? void 0 : req.headers) === null || _b === void 0 ? void 0 : _b['x-real-ip']);
|
|
2190
|
+
if (realIp) {
|
|
2191
|
+
return this.normalizeIpAddress(realIp);
|
|
2192
|
+
}
|
|
2193
|
+
var socketIp = ((_c = req === null || req === void 0 ? void 0 : req.socket) === null || _c === void 0 ? void 0 : _c.remoteAddress) || ((_d = req === null || req === void 0 ? void 0 : req.connection) === null || _d === void 0 ? void 0 : _d.remoteAddress) || (req === null || req === void 0 ? void 0 : req.ip) || '';
|
|
2194
|
+
return this.normalizeIpAddress(socketIp);
|
|
2195
|
+
};
|
|
2196
|
+
ResolveIOMainServer.prototype.buildSocketLimitMessage = function (activeSockets) {
|
|
2197
|
+
var tierLabel = this._socketTier ? this._socketTier[0].toUpperCase() + this._socketTier.slice(1) : 'Current';
|
|
2198
|
+
var upgradeUrl = this.resolveSocketUpgradeUrlWithAppId();
|
|
2199
|
+
var base = "Socket connection limit reached (".concat(activeSockets, "/").concat(this._maxClientSockets, ") for the ").concat(tierLabel, " tier.");
|
|
2200
|
+
if (!upgradeUrl) {
|
|
2201
|
+
return "".concat(base, " Upgrade to increase capacity.");
|
|
2202
|
+
}
|
|
2203
|
+
return "".concat(base, " Upgrade at ").concat(upgradeUrl, ".");
|
|
2204
|
+
};
|
|
2205
|
+
ResolveIOMainServer.prototype.buildSocketLimitCloseReason = function () {
|
|
2206
|
+
return "Socket limit reached (".concat(this._maxClientSockets, ")");
|
|
2207
|
+
};
|
|
2208
|
+
ResolveIOMainServer.prototype.disconnectUserSocketsFromDifferentIps = function (idUser, incomingIp) {
|
|
2209
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2210
|
+
var normalizedUser, normalizedIncomingIp, userSockets, disconnected, userSockets_1, userSockets_1_1, existingSocket, existingIp, e_9_1;
|
|
2211
|
+
var e_9, _a;
|
|
2212
|
+
return __generator(this, function (_b) {
|
|
2213
|
+
switch (_b.label) {
|
|
2214
|
+
case 0:
|
|
2215
|
+
if (!this._websocketManager) {
|
|
2216
|
+
return [2 /*return*/, 0];
|
|
2217
|
+
}
|
|
2218
|
+
normalizedUser = "".concat(idUser || '').trim();
|
|
2219
|
+
normalizedIncomingIp = this.normalizeIpAddress(incomingIp);
|
|
2220
|
+
if (!normalizedUser || !normalizedIncomingIp) {
|
|
2221
|
+
return [2 /*return*/, 0];
|
|
2222
|
+
}
|
|
2223
|
+
userSockets = this._websocketManager.getUserWebSockets(normalizedUser);
|
|
2224
|
+
disconnected = 0;
|
|
2225
|
+
_b.label = 1;
|
|
2226
|
+
case 1:
|
|
2227
|
+
_b.trys.push([1, 6, 7, 8]);
|
|
2228
|
+
userSockets_1 = __values(userSockets), userSockets_1_1 = userSockets_1.next();
|
|
2229
|
+
_b.label = 2;
|
|
2230
|
+
case 2:
|
|
2231
|
+
if (!!userSockets_1_1.done) return [3 /*break*/, 5];
|
|
2232
|
+
existingSocket = userSockets_1_1.value;
|
|
2233
|
+
existingIp = this.normalizeIpAddress(existingSocket === null || existingSocket === void 0 ? void 0 : existingSocket['client_ip']);
|
|
2234
|
+
if (!existingIp || existingIp === normalizedIncomingIp) {
|
|
2235
|
+
return [3 /*break*/, 4];
|
|
2236
|
+
}
|
|
2237
|
+
this.logConnectDebug('WS single-ip enforcement disconnect', {
|
|
2238
|
+
id_socket: existingSocket === null || existingSocket === void 0 ? void 0 : existingSocket['id_socket'],
|
|
2239
|
+
id_user: normalizedUser,
|
|
2240
|
+
existingIp: existingIp,
|
|
2241
|
+
incomingIp: normalizedIncomingIp
|
|
2242
|
+
});
|
|
2243
|
+
return [4 /*yield*/, this.unsubscribeWS(existingSocket)];
|
|
2244
|
+
case 3:
|
|
2245
|
+
_b.sent();
|
|
2246
|
+
if (existingSocket.readyState === WebSocket.OPEN || existingSocket.readyState === WebSocket.CONNECTING) {
|
|
2247
|
+
try {
|
|
2248
|
+
existingSocket.close(1008, 'Signed in from another IP');
|
|
2249
|
+
}
|
|
2250
|
+
catch (_c) { }
|
|
2251
|
+
}
|
|
2252
|
+
disconnected += 1;
|
|
2253
|
+
_b.label = 4;
|
|
2254
|
+
case 4:
|
|
2255
|
+
userSockets_1_1 = userSockets_1.next();
|
|
2256
|
+
return [3 /*break*/, 2];
|
|
2257
|
+
case 5: return [3 /*break*/, 8];
|
|
2258
|
+
case 6:
|
|
2259
|
+
e_9_1 = _b.sent();
|
|
2260
|
+
e_9 = { error: e_9_1 };
|
|
2261
|
+
return [3 /*break*/, 8];
|
|
2262
|
+
case 7:
|
|
2263
|
+
try {
|
|
2264
|
+
if (userSockets_1_1 && !userSockets_1_1.done && (_a = userSockets_1.return)) _a.call(userSockets_1);
|
|
2265
|
+
}
|
|
2266
|
+
finally { if (e_9) throw e_9.error; }
|
|
2267
|
+
return [7 /*endfinally*/];
|
|
2268
|
+
case 8: return [2 /*return*/, disconnected];
|
|
2269
|
+
}
|
|
2270
|
+
});
|
|
2271
|
+
});
|
|
2272
|
+
};
|
|
2273
|
+
ResolveIOMainServer.prototype.evaluateClientSocketAdmission = function (idUser, req) {
|
|
2274
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2275
|
+
var normalizedUser, clientIp, activeSockets, message;
|
|
2276
|
+
return __generator(this, function (_a) {
|
|
2277
|
+
switch (_a.label) {
|
|
2278
|
+
case 0:
|
|
2279
|
+
normalizedUser = "".concat(idUser || '').trim();
|
|
2280
|
+
clientIp = this.resolveClientIp(req);
|
|
2281
|
+
if (!this._singleIpPerUser) return [3 /*break*/, 2];
|
|
2282
|
+
return [4 /*yield*/, this.disconnectUserSocketsFromDifferentIps(normalizedUser, clientIp)];
|
|
2283
|
+
case 1:
|
|
2284
|
+
_a.sent();
|
|
2285
|
+
_a.label = 2;
|
|
2286
|
+
case 2:
|
|
2287
|
+
if (this._maxClientSockets > 0 && this._websocketManager) {
|
|
2288
|
+
activeSockets = this._websocketManager.getActiveWebSocketCount();
|
|
2289
|
+
if (activeSockets >= this._maxClientSockets) {
|
|
2290
|
+
message = this.buildSocketLimitMessage(activeSockets);
|
|
2291
|
+
this.logConnectDebug('WS socket limit blocked', {
|
|
2292
|
+
id_user: normalizedUser,
|
|
2293
|
+
clientIp: clientIp,
|
|
2294
|
+
activeSockets: activeSockets,
|
|
2295
|
+
maxClientSockets: this._maxClientSockets
|
|
2296
|
+
});
|
|
2297
|
+
return [2 /*return*/, {
|
|
2298
|
+
allowed: false,
|
|
2299
|
+
statusCode: 429,
|
|
2300
|
+
message: message,
|
|
2301
|
+
clientIp: clientIp
|
|
2302
|
+
}];
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
return [2 /*return*/, {
|
|
2306
|
+
allowed: true,
|
|
2307
|
+
statusCode: 200,
|
|
2308
|
+
message: '',
|
|
2309
|
+
clientIp: clientIp
|
|
2310
|
+
}];
|
|
2311
|
+
}
|
|
2312
|
+
});
|
|
2313
|
+
});
|
|
2314
|
+
};
|
|
1608
2315
|
ResolveIOMainServer.prototype.logConnectDebug = function (message, details) {
|
|
1609
2316
|
if (!this._wsConnectDebug) {
|
|
1610
2317
|
return;
|
|
@@ -1953,7 +2660,7 @@ var ResolveIOMainServer = /** @class */ (function () {
|
|
|
1953
2660
|
});
|
|
1954
2661
|
}
|
|
1955
2662
|
setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
1956
|
-
var
|
|
2663
|
+
var error_6;
|
|
1957
2664
|
return __generator(this, function (_a) {
|
|
1958
2665
|
switch (_a.label) {
|
|
1959
2666
|
case 0:
|
|
@@ -1963,8 +2670,8 @@ var ResolveIOMainServer = /** @class */ (function () {
|
|
|
1963
2670
|
_a.sent();
|
|
1964
2671
|
return [3 /*break*/, 3];
|
|
1965
2672
|
case 2:
|
|
1966
|
-
|
|
1967
|
-
console.error(new Date(), 'aiCoderTerminalRunCodex failed:',
|
|
2673
|
+
error_6 = _a.sent();
|
|
2674
|
+
console.error(new Date(), 'aiCoderTerminalRunCodex failed:', error_6);
|
|
1968
2675
|
return [3 /*break*/, 3];
|
|
1969
2676
|
case 3: return [2 /*return*/];
|
|
1970
2677
|
}
|