request-iframe 0.1.0 → 0.2.0
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/QUICKSTART.CN.md +4 -2
- package/QUICKSTART.md +4 -2
- package/README.CN.md +302 -54
- package/README.md +281 -36
- package/cdn/request-iframe-react.umd.js +3354 -0
- package/cdn/request-iframe-react.umd.js.map +1 -0
- package/cdn/request-iframe-react.umd.min.js +2 -0
- package/cdn/request-iframe-react.umd.min.js.map +1 -0
- package/cdn/request-iframe.umd.js +19735 -0
- package/cdn/request-iframe.umd.js.map +1 -0
- package/cdn/request-iframe.umd.min.js +4 -0
- package/cdn/request-iframe.umd.min.js.map +1 -0
- package/esm/api/client.js +31 -22
- package/esm/api/endpoint.js +229 -0
- package/esm/api/server.js +19 -9
- package/esm/constants/debug.js +17 -0
- package/esm/constants/index.js +115 -66
- package/esm/constants/log.js +11 -0
- package/esm/constants/messages.js +6 -1
- package/esm/constants/warn-once.js +15 -0
- package/esm/endpoint/facade.js +390 -0
- package/esm/endpoint/heartbeat/heartbeat.js +60 -0
- package/esm/endpoint/heartbeat/ping.js +20 -0
- package/esm/endpoint/index.js +13 -0
- package/esm/endpoint/infra/hub.js +316 -0
- package/esm/endpoint/infra/inbox.js +232 -0
- package/esm/endpoint/infra/outbox.js +408 -0
- package/esm/endpoint/stream/dispatcher.js +58 -0
- package/esm/endpoint/stream/errors.js +27 -0
- package/esm/endpoint/stream/factory.js +76 -0
- package/esm/endpoint/stream/file-auto-resolve.js +34 -0
- package/esm/endpoint/stream/file-writable.js +105 -0
- package/esm/endpoint/stream/handler.js +26 -0
- package/esm/{core → impl}/client.js +243 -320
- package/esm/{core → impl}/response.js +120 -154
- package/esm/impl/server.js +568 -0
- package/esm/index.js +13 -6
- package/esm/message/ack.js +27 -0
- package/esm/message/channel-cache.js +108 -0
- package/esm/message/channel.js +92 -5
- package/esm/message/dispatcher.js +149 -98
- package/esm/stream/error.js +22 -0
- package/esm/stream/index.js +3 -1
- package/esm/stream/readable-stream.js +101 -26
- package/esm/stream/stream-core.js +121 -3
- package/esm/stream/writable-stream.js +368 -43
- package/esm/utils/ack.js +36 -0
- package/esm/utils/blob.js +16 -0
- package/esm/utils/cache.js +25 -76
- package/esm/utils/content-type.js +81 -0
- package/esm/utils/debug.js +157 -180
- package/esm/utils/hooks.js +130 -0
- package/esm/utils/id.js +14 -0
- package/esm/utils/iframe.js +20 -0
- package/esm/utils/index.js +12 -162
- package/esm/utils/is.js +3 -0
- package/esm/utils/logger.js +55 -0
- package/esm/utils/origin.js +3 -1
- package/esm/utils/promise.js +3 -0
- package/esm/utils/window.js +31 -0
- package/library/api/client.d.ts.map +1 -1
- package/library/api/client.js +32 -23
- package/library/api/endpoint.d.ts +23 -0
- package/library/api/endpoint.d.ts.map +1 -0
- package/library/api/endpoint.js +235 -0
- package/library/api/server.d.ts +4 -1
- package/library/api/server.d.ts.map +1 -1
- package/library/api/server.js +19 -9
- package/library/constants/debug.d.ts +18 -0
- package/library/constants/debug.d.ts.map +1 -0
- package/library/constants/debug.js +23 -0
- package/library/constants/index.d.ts +58 -7
- package/library/constants/index.d.ts.map +1 -1
- package/library/constants/index.js +143 -67
- package/library/constants/log.d.ts +12 -0
- package/library/constants/log.d.ts.map +1 -0
- package/library/constants/log.js +17 -0
- package/library/constants/messages.d.ts +6 -1
- package/library/constants/messages.d.ts.map +1 -1
- package/library/constants/messages.js +6 -1
- package/library/constants/warn-once.d.ts +12 -0
- package/library/constants/warn-once.d.ts.map +1 -0
- package/library/constants/warn-once.js +22 -0
- package/library/endpoint/facade.d.ts +238 -0
- package/library/endpoint/facade.d.ts.map +1 -0
- package/library/endpoint/facade.js +398 -0
- package/library/endpoint/heartbeat/heartbeat.d.ts +34 -0
- package/library/endpoint/heartbeat/heartbeat.d.ts.map +1 -0
- package/library/endpoint/heartbeat/heartbeat.js +67 -0
- package/library/endpoint/heartbeat/ping.d.ts +18 -0
- package/library/endpoint/heartbeat/ping.d.ts.map +1 -0
- package/library/endpoint/heartbeat/ping.js +26 -0
- package/library/endpoint/index.d.ts +16 -0
- package/library/endpoint/index.d.ts.map +1 -0
- package/library/endpoint/index.js +114 -0
- package/library/endpoint/infra/hub.d.ts +170 -0
- package/library/endpoint/infra/hub.d.ts.map +1 -0
- package/library/endpoint/infra/hub.js +323 -0
- package/library/endpoint/infra/inbox.d.ts +73 -0
- package/library/endpoint/infra/inbox.d.ts.map +1 -0
- package/library/endpoint/infra/inbox.js +239 -0
- package/library/endpoint/infra/outbox.d.ts +149 -0
- package/library/endpoint/infra/outbox.d.ts.map +1 -0
- package/library/endpoint/infra/outbox.js +415 -0
- package/library/endpoint/stream/dispatcher.d.ts +33 -0
- package/library/endpoint/stream/dispatcher.d.ts.map +1 -0
- package/library/endpoint/stream/dispatcher.js +66 -0
- package/library/endpoint/stream/errors.d.ts +20 -0
- package/library/endpoint/stream/errors.d.ts.map +1 -0
- package/library/endpoint/stream/errors.js +32 -0
- package/library/endpoint/stream/factory.d.ts +44 -0
- package/library/endpoint/stream/factory.d.ts.map +1 -0
- package/library/endpoint/stream/factory.js +82 -0
- package/library/endpoint/stream/file-auto-resolve.d.ts +26 -0
- package/library/endpoint/stream/file-auto-resolve.d.ts.map +1 -0
- package/library/endpoint/stream/file-auto-resolve.js +41 -0
- package/library/endpoint/stream/file-writable.d.ts +33 -0
- package/library/endpoint/stream/file-writable.d.ts.map +1 -0
- package/library/endpoint/stream/file-writable.js +115 -0
- package/library/endpoint/stream/handler.d.ts +20 -0
- package/library/endpoint/stream/handler.d.ts.map +1 -0
- package/library/endpoint/stream/handler.js +32 -0
- package/library/{core → impl}/client.d.ts +16 -13
- package/library/impl/client.d.ts.map +1 -0
- package/library/{core → impl}/client.js +254 -333
- package/library/{core → impl}/request.d.ts.map +1 -1
- package/library/{core → impl}/response.d.ts +7 -12
- package/library/impl/response.d.ts.map +1 -0
- package/library/{core → impl}/response.js +120 -154
- package/library/{core → impl}/server.d.ts +26 -55
- package/library/impl/server.d.ts.map +1 -0
- package/library/impl/server.js +575 -0
- package/library/index.d.ts +13 -6
- package/library/index.d.ts.map +1 -1
- package/library/index.js +16 -16
- package/library/message/ack.d.ts +15 -0
- package/library/message/ack.d.ts.map +1 -0
- package/library/message/ack.js +33 -0
- package/library/message/channel-cache.d.ts +26 -0
- package/library/message/channel-cache.d.ts.map +1 -0
- package/library/message/channel-cache.js +115 -0
- package/library/message/channel.d.ts +53 -6
- package/library/message/channel.d.ts.map +1 -1
- package/library/message/channel.js +96 -9
- package/library/message/dispatcher.d.ts +17 -0
- package/library/message/dispatcher.d.ts.map +1 -1
- package/library/message/dispatcher.js +149 -98
- package/library/stream/error.d.ts +24 -0
- package/library/stream/error.d.ts.map +1 -0
- package/library/stream/error.js +29 -0
- package/library/stream/index.d.ts +4 -1
- package/library/stream/index.d.ts.map +1 -1
- package/library/stream/index.js +7 -4
- package/library/stream/readable-stream.d.ts.map +1 -1
- package/library/stream/readable-stream.js +102 -27
- package/library/stream/stream-core.d.ts +22 -1
- package/library/stream/stream-core.d.ts.map +1 -1
- package/library/stream/stream-core.js +120 -2
- package/library/stream/types.d.ts +115 -2
- package/library/stream/types.d.ts.map +1 -1
- package/library/stream/writable-stream.d.ts +20 -2
- package/library/stream/writable-stream.d.ts.map +1 -1
- package/library/stream/writable-stream.js +366 -41
- package/library/types/index.d.ts +17 -22
- package/library/types/index.d.ts.map +1 -1
- package/library/utils/ack.d.ts +2 -0
- package/library/utils/ack.d.ts.map +1 -0
- package/library/utils/ack.js +44 -0
- package/library/utils/blob.d.ts +3 -0
- package/library/utils/blob.d.ts.map +1 -0
- package/library/utils/blob.js +22 -0
- package/library/utils/cache.d.ts +10 -20
- package/library/utils/cache.d.ts.map +1 -1
- package/library/utils/cache.js +25 -79
- package/library/utils/content-type.d.ts +13 -0
- package/library/utils/content-type.d.ts.map +1 -0
- package/library/utils/content-type.js +87 -0
- package/library/utils/debug.d.ts.map +1 -1
- package/library/utils/debug.js +156 -178
- package/library/utils/hooks.d.ts +30 -0
- package/library/utils/hooks.d.ts.map +1 -0
- package/library/utils/hooks.js +139 -0
- package/library/utils/id.d.ts +9 -0
- package/library/utils/id.d.ts.map +1 -0
- package/library/utils/id.js +21 -0
- package/library/utils/iframe.d.ts +5 -0
- package/library/utils/iframe.d.ts.map +1 -0
- package/library/utils/iframe.js +25 -0
- package/library/utils/index.d.ts +7 -34
- package/library/utils/index.d.ts.map +1 -1
- package/library/utils/index.js +58 -193
- package/library/utils/is.d.ts +2 -0
- package/library/utils/is.d.ts.map +1 -0
- package/library/utils/is.js +9 -0
- package/library/utils/logger.d.ts +13 -0
- package/library/utils/logger.d.ts.map +1 -0
- package/library/utils/logger.js +63 -0
- package/library/utils/origin.d.ts.map +1 -1
- package/library/utils/origin.js +2 -1
- package/library/utils/promise.d.ts +2 -0
- package/library/utils/promise.d.ts.map +1 -0
- package/library/utils/promise.js +9 -0
- package/library/utils/window.d.ts +2 -0
- package/library/utils/window.d.ts.map +1 -0
- package/library/utils/window.js +38 -0
- package/package.json +49 -2
- package/react/package.json +2 -1
- package/esm/core/client-server.js +0 -329
- package/esm/core/server.js +0 -767
- package/esm/utils/ack-meta.js +0 -53
- package/library/core/client-server.d.ts +0 -106
- package/library/core/client-server.d.ts.map +0 -1
- package/library/core/client-server.js +0 -336
- package/library/core/client.d.ts.map +0 -1
- package/library/core/response.d.ts.map +0 -1
- package/library/core/server.d.ts.map +0 -1
- package/library/core/server.js +0 -772
- package/library/utils/ack-meta.d.ts +0 -2
- package/library/utils/ack-meta.d.ts.map +0 -1
- package/library/utils/ack-meta.js +0 -59
- /package/esm/{core → impl}/request.js +0 -0
- /package/library/{core → impl}/request.d.ts +0 -0
- /package/library/{core → impl}/request.js +0 -0
package/library/core/server.js
DELETED
|
@@ -1,772 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
require("core-js/modules/es.symbol.description.js");
|
|
4
|
-
require("core-js/modules/es.array.filter.js");
|
|
5
|
-
require("core-js/modules/es.array.from.js");
|
|
6
|
-
require("core-js/modules/es.array.slice.js");
|
|
7
|
-
require("core-js/modules/es.object.get-own-property-descriptors.js");
|
|
8
|
-
require("core-js/modules/es.regexp.to-string.js");
|
|
9
|
-
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
10
|
-
Object.defineProperty(exports, "__esModule", {
|
|
11
|
-
value: true
|
|
12
|
-
});
|
|
13
|
-
exports.RequestIframeServerImpl = void 0;
|
|
14
|
-
require("core-js/modules/es.array.includes.js");
|
|
15
|
-
require("core-js/modules/es.array.iterator.js");
|
|
16
|
-
require("core-js/modules/es.map.js");
|
|
17
|
-
require("core-js/modules/es.object.entries.js");
|
|
18
|
-
require("core-js/modules/es.promise.js");
|
|
19
|
-
require("core-js/modules/es.regexp.exec.js");
|
|
20
|
-
require("core-js/modules/es.string.includes.js");
|
|
21
|
-
require("core-js/modules/es.string.match.js");
|
|
22
|
-
require("core-js/modules/es.string.replace.js");
|
|
23
|
-
require("core-js/modules/es.string.starts-with.js");
|
|
24
|
-
require("core-js/modules/web.dom-collections.for-each.js");
|
|
25
|
-
require("core-js/modules/web.dom-collections.iterator.js");
|
|
26
|
-
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
27
|
-
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
28
|
-
var _utils = require("../utils");
|
|
29
|
-
var _pathMatch = require("../utils/path-match");
|
|
30
|
-
var _origin = require("../utils/origin");
|
|
31
|
-
var _request = require("./request");
|
|
32
|
-
var _response = require("./response");
|
|
33
|
-
var _message = require("../message");
|
|
34
|
-
var _cache = require("../utils/cache");
|
|
35
|
-
var _constants = require("../constants");
|
|
36
|
-
var _stream = require("../stream");
|
|
37
|
-
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
38
|
-
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
39
|
-
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
40
|
-
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
41
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
42
|
-
/**
|
|
43
|
-
* Middleware item (contains path matcher and middleware function)
|
|
44
|
-
*/
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Pending acknowledgment
|
|
48
|
-
*/
|
|
49
|
-
|
|
50
|
-
/** Pending request waiting for client stream (streamId present) */
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Server configuration options
|
|
54
|
-
*/
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* RequestIframeServer implementation
|
|
58
|
-
* Uses shared MessageDispatcher (backed by MessageChannel) to listen for and send messages
|
|
59
|
-
*/
|
|
60
|
-
class RequestIframeServerImpl {
|
|
61
|
-
constructor(options) {
|
|
62
|
-
var _options$ackTimeout, _options$versionValid, _options$maxConcurren;
|
|
63
|
-
/** Unique instance ID */
|
|
64
|
-
(0, _defineProperty2.default)(this, "handlers", new Map());
|
|
65
|
-
(0, _defineProperty2.default)(this, "middlewares", []);
|
|
66
|
-
(0, _defineProperty2.default)(this, "inFlightByClientKey", new Map());
|
|
67
|
-
/** Responses waiting for client acknowledgment */
|
|
68
|
-
(0, _defineProperty2.default)(this, "pendingAcks", new Map());
|
|
69
|
-
/** Pending pings waiting for client PONG (server -> client heartbeat) */
|
|
70
|
-
(0, _defineProperty2.default)(this, "pendingPongs", new Map());
|
|
71
|
-
/** Pending requests waiting for client stream_start (streamId present) */
|
|
72
|
-
(0, _defineProperty2.default)(this, "pendingStreamRequests", new Map());
|
|
73
|
-
/** Stream message handlers (streamId -> handler) for client→server streams */
|
|
74
|
-
(0, _defineProperty2.default)(this, "streamHandlers", new Map());
|
|
75
|
-
/** List of functions to unregister handlers */
|
|
76
|
-
(0, _defineProperty2.default)(this, "unregisterFns", []);
|
|
77
|
-
/** Whether it is open */
|
|
78
|
-
(0, _defineProperty2.default)(this, "_isOpen", false);
|
|
79
|
-
// Use custom id if provided, otherwise generate one
|
|
80
|
-
this.id = (options === null || options === void 0 ? void 0 : options.id) || (0, _utils.generateInstanceId)();
|
|
81
|
-
this.ackTimeout = (_options$ackTimeout = options === null || options === void 0 ? void 0 : options.ackTimeout) !== null && _options$ackTimeout !== void 0 ? _options$ackTimeout : _constants.DefaultTimeout.ACK;
|
|
82
|
-
this.versionValidator = (_options$versionValid = options === null || options === void 0 ? void 0 : options.versionValidator) !== null && _options$versionValid !== void 0 ? _options$versionValid : _utils.isCompatibleVersion;
|
|
83
|
-
this.maxConcurrentRequestsPerClient = (_options$maxConcurren = options === null || options === void 0 ? void 0 : options.maxConcurrentRequestsPerClient) !== null && _options$maxConcurren !== void 0 ? _options$maxConcurren : Number.POSITIVE_INFINITY;
|
|
84
|
-
|
|
85
|
-
// Build origin validator (incoming messages)
|
|
86
|
-
if (options !== null && options !== void 0 && options.validateOrigin) {
|
|
87
|
-
this.originValidator = (origin, data, context) => options.validateOrigin(origin, data, context);
|
|
88
|
-
} else if (options !== null && options !== void 0 && options.allowedOrigins) {
|
|
89
|
-
var matcher = options.allowedOrigins;
|
|
90
|
-
this.originValidator = origin => (0, _origin.matchOrigin)(origin, matcher);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Get or create shared channel and create dispatcher
|
|
94
|
-
var channel = (0, _cache.getOrCreateMessageChannel)(options === null || options === void 0 ? void 0 : options.secretKey);
|
|
95
|
-
this.dispatcher = new _message.MessageDispatcher(channel, _constants.MessageRole.SERVER, this.id);
|
|
96
|
-
|
|
97
|
-
// Auto-open by default (unless explicitly set to false)
|
|
98
|
-
if ((options === null || options === void 0 ? void 0 : options.autoOpen) !== false) {
|
|
99
|
-
this.open();
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Check whether an incoming message origin is allowed.
|
|
105
|
-
*/
|
|
106
|
-
isOriginAllowed(data, context) {
|
|
107
|
-
if (!this.originValidator) return true;
|
|
108
|
-
try {
|
|
109
|
-
return this.originValidator(context.origin, data, context);
|
|
110
|
-
} catch (_unused) {
|
|
111
|
-
return false;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Build a per-client key used for concurrency limiting.
|
|
117
|
-
* We intentionally include origin to prevent cross-origin collisions.
|
|
118
|
-
*/
|
|
119
|
-
getClientKey(origin, creatorId) {
|
|
120
|
-
return `${origin}::${creatorId || 'unknown'}`;
|
|
121
|
-
}
|
|
122
|
-
incInFlight(clientKey) {
|
|
123
|
-
var current = this.inFlightByClientKey.get(clientKey) || 0;
|
|
124
|
-
this.inFlightByClientKey.set(clientKey, current + 1);
|
|
125
|
-
}
|
|
126
|
-
decInFlight(clientKey) {
|
|
127
|
-
var current = this.inFlightByClientKey.get(clientKey) || 0;
|
|
128
|
-
var next = current - 1;
|
|
129
|
-
if (next <= 0) {
|
|
130
|
-
this.inFlightByClientKey.delete(clientKey);
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
this.inFlightByClientKey.set(clientKey, next);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Open message processing (register message handlers)
|
|
138
|
-
*/
|
|
139
|
-
open() {
|
|
140
|
-
if (this._isOpen) return;
|
|
141
|
-
this._isOpen = true;
|
|
142
|
-
this.registerHandlers();
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Close message processing (unregister message handlers, but don't release channel)
|
|
147
|
-
*/
|
|
148
|
-
close() {
|
|
149
|
-
if (!this._isOpen) return;
|
|
150
|
-
this._isOpen = false;
|
|
151
|
-
|
|
152
|
-
// Unregister all handlers
|
|
153
|
-
this.unregisterFns.forEach(fn => fn());
|
|
154
|
-
this.unregisterFns.length = 0;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Whether it is open
|
|
159
|
-
*/
|
|
160
|
-
get isOpen() {
|
|
161
|
-
return this._isOpen;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Register message handlers
|
|
166
|
-
*/
|
|
167
|
-
registerHandlers() {
|
|
168
|
-
var handlerOptions = {
|
|
169
|
-
versionValidator: this.versionValidator,
|
|
170
|
-
onVersionError: this.handleVersionError.bind(this)
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
// Handle REQUEST messages
|
|
174
|
-
this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.REQUEST, (data, context) => this.handleRequest(data, context), handlerOptions));
|
|
175
|
-
|
|
176
|
-
// Handle PING messages
|
|
177
|
-
this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.PING, (data, context) => this.handlePing(data, context), handlerOptions));
|
|
178
|
-
|
|
179
|
-
// Handle PONG messages (server -> client heartbeat)
|
|
180
|
-
this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.PONG, (data, context) => this.handlePong(data, context), handlerOptions));
|
|
181
|
-
|
|
182
|
-
// Handle RECEIVED messages (for confirming response delivery)
|
|
183
|
-
this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.RECEIVED, (data, context) => this.handleReceived(data, context), handlerOptions));
|
|
184
|
-
|
|
185
|
-
// Handle stream_* messages (client→server stream)
|
|
186
|
-
this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.STREAM_START, (data, ctx) => this.handleStreamStart(data, ctx), handlerOptions));
|
|
187
|
-
this.unregisterFns.push(this.dispatcher.registerHandler(type => type.startsWith('stream_') && type !== _constants.MessageType.STREAM_START, (data, context) => this.dispatchStreamMessage(data, context), handlerOptions));
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/** Handle stream_start from client (stream request with streamId) */
|
|
191
|
-
handleStreamStart(data, context) {
|
|
192
|
-
var _body$chunked;
|
|
193
|
-
if (data.role !== _constants.MessageRole.CLIENT) return;
|
|
194
|
-
if (!this.isOriginAllowed(data, context)) return;
|
|
195
|
-
var body = data.body;
|
|
196
|
-
if (!(body !== null && body !== void 0 && body.streamId)) return;
|
|
197
|
-
var pending = this.pendingStreamRequests.get(data.requestId);
|
|
198
|
-
if (!pending || pending.streamId !== body.streamId) return;
|
|
199
|
-
clearTimeout(pending.timeoutId);
|
|
200
|
-
this.pendingStreamRequests.delete(data.requestId);
|
|
201
|
-
var targetWindow = pending.targetWindow,
|
|
202
|
-
targetOrigin = pending.targetOrigin,
|
|
203
|
-
res = pending.res,
|
|
204
|
-
reqData = pending.data,
|
|
205
|
-
reqContext = pending.context,
|
|
206
|
-
handlerFn = pending.handlerFn;
|
|
207
|
-
var streamHandler = {
|
|
208
|
-
registerStreamHandler: (streamId, handler) => {
|
|
209
|
-
this.streamHandlers.set(streamId, handler);
|
|
210
|
-
},
|
|
211
|
-
unregisterStreamHandler: streamId => {
|
|
212
|
-
this.streamHandlers.delete(streamId);
|
|
213
|
-
},
|
|
214
|
-
postMessage: message => {
|
|
215
|
-
this.dispatcher.send(targetWindow, message, targetOrigin);
|
|
216
|
-
}
|
|
217
|
-
};
|
|
218
|
-
var streamType = body.type || _constants.StreamType.DATA;
|
|
219
|
-
var streamMode = body.mode;
|
|
220
|
-
var streamChunked = (_body$chunked = body.chunked) !== null && _body$chunked !== void 0 ? _body$chunked : true;
|
|
221
|
-
var streamMetadata = body.metadata;
|
|
222
|
-
var req = new _request.ServerRequestImpl(reqData, reqContext, res, pending.params);
|
|
223
|
-
|
|
224
|
-
// File stream: optionally auto-resolve to File/Blob before calling handler
|
|
225
|
-
if (streamType === _constants.StreamType.FILE) {
|
|
226
|
-
var _body$autoResolve;
|
|
227
|
-
var fileStream = new _stream.IframeFileReadableStream(body.streamId, data.requestId, streamHandler, {
|
|
228
|
-
chunked: streamChunked,
|
|
229
|
-
metadata: streamMetadata,
|
|
230
|
-
secretKey: data.secretKey,
|
|
231
|
-
mode: streamMode,
|
|
232
|
-
filename: streamMetadata === null || streamMetadata === void 0 ? void 0 : streamMetadata.filename,
|
|
233
|
-
mimeType: streamMetadata === null || streamMetadata === void 0 ? void 0 : streamMetadata.mimeType,
|
|
234
|
-
size: streamMetadata === null || streamMetadata === void 0 ? void 0 : streamMetadata.size
|
|
235
|
-
});
|
|
236
|
-
var autoResolve = (_body$autoResolve = body.autoResolve) !== null && _body$autoResolve !== void 0 ? _body$autoResolve : false;
|
|
237
|
-
if (autoResolve) {
|
|
238
|
-
var name = fileStream.filename || (streamMetadata === null || streamMetadata === void 0 ? void 0 : streamMetadata.filename);
|
|
239
|
-
var promise = name ? fileStream.readAsFile(name) : fileStream.readAsBlob();
|
|
240
|
-
promise.then(fileData => {
|
|
241
|
-
req.body = fileData;
|
|
242
|
-
req.stream = undefined;
|
|
243
|
-
this.runMiddlewares(req, res, () => {
|
|
244
|
-
try {
|
|
245
|
-
var result = handlerFn(req, res);
|
|
246
|
-
if ((0, _utils.isPromise)(result)) {
|
|
247
|
-
// Window check is handled in MessageDispatcher
|
|
248
|
-
this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ASYNC, data.requestId, {
|
|
249
|
-
path: reqData.path,
|
|
250
|
-
targetId: data.creatorId
|
|
251
|
-
});
|
|
252
|
-
result.then(this.handleRequestResult.bind(this, res, targetWindow, targetOrigin, reqData)).catch(this.handleRequestError.bind(this, res, targetWindow, targetOrigin, reqData));
|
|
253
|
-
} else {
|
|
254
|
-
this.handleRequestResult(res, targetWindow, targetOrigin, reqData, result);
|
|
255
|
-
}
|
|
256
|
-
} catch (error) {
|
|
257
|
-
this.handleRequestError(res, targetWindow, targetOrigin, reqData, error);
|
|
258
|
-
}
|
|
259
|
-
});
|
|
260
|
-
}).catch(error => {
|
|
261
|
-
this.handleRequestError(res, targetWindow, targetOrigin, reqData, error);
|
|
262
|
-
});
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// Non-autoResolve: expose stream directly
|
|
267
|
-
req.body = fileStream;
|
|
268
|
-
req.stream = fileStream;
|
|
269
|
-
} else {
|
|
270
|
-
// Non-file stream
|
|
271
|
-
var readableStream = new _stream.IframeReadableStream(body.streamId, data.requestId, streamHandler, {
|
|
272
|
-
type: streamType,
|
|
273
|
-
mode: streamMode,
|
|
274
|
-
chunked: streamChunked,
|
|
275
|
-
metadata: streamMetadata,
|
|
276
|
-
secretKey: data.secretKey
|
|
277
|
-
});
|
|
278
|
-
req.body = undefined;
|
|
279
|
-
req.stream = readableStream;
|
|
280
|
-
}
|
|
281
|
-
this.runMiddlewares(req, res, () => {
|
|
282
|
-
try {
|
|
283
|
-
var result = handlerFn(req, res);
|
|
284
|
-
if ((0, _utils.isPromise)(result)) {
|
|
285
|
-
// Window check is handled in MessageDispatcher
|
|
286
|
-
this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ASYNC, data.requestId, {
|
|
287
|
-
path: reqData.path,
|
|
288
|
-
targetId: data.creatorId
|
|
289
|
-
});
|
|
290
|
-
result.then(this.handleRequestResult.bind(this, res, targetWindow, targetOrigin, reqData)).catch(this.handleRequestError.bind(this, res, targetWindow, targetOrigin, reqData));
|
|
291
|
-
} else {
|
|
292
|
-
this.handleRequestResult(res, targetWindow, targetOrigin, reqData, result);
|
|
293
|
-
}
|
|
294
|
-
} catch (error) {
|
|
295
|
-
this.handleRequestError(res, targetWindow, targetOrigin, reqData, error);
|
|
296
|
-
}
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
dispatchStreamMessage(data, context) {
|
|
300
|
-
if (!this.isOriginAllowed(data, context)) return;
|
|
301
|
-
var body = data.body;
|
|
302
|
-
if (!(body !== null && body !== void 0 && body.streamId)) return;
|
|
303
|
-
var handler = this.streamHandlers.get(body.streamId);
|
|
304
|
-
if (handler) {
|
|
305
|
-
var messageType = data.type.replace('stream_', '');
|
|
306
|
-
handler(_objectSpread(_objectSpread({}, body), {}, {
|
|
307
|
-
type: messageType
|
|
308
|
-
}));
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/**
|
|
313
|
-
* Handle protocol version error
|
|
314
|
-
*/
|
|
315
|
-
handleVersionError(data, context, version) {
|
|
316
|
-
if (!context.source) return;
|
|
317
|
-
|
|
318
|
-
// Send protocol version incompatibility error
|
|
319
|
-
// Window check is handled in MessageDispatcher
|
|
320
|
-
this.dispatcher.sendMessage(context.source, context.origin, _constants.MessageType.ERROR, data.requestId, {
|
|
321
|
-
path: data.path,
|
|
322
|
-
status: _constants.HttpStatus.BAD_REQUEST,
|
|
323
|
-
statusText: _constants.Messages.PROTOCOL_VERSION_UNSUPPORTED,
|
|
324
|
-
error: {
|
|
325
|
-
message: (0, _constants.formatMessage)(_constants.Messages.PROTOCOL_VERSION_TOO_LOW, version, _constants.ProtocolVersion.MIN_SUPPORTED),
|
|
326
|
-
code: _constants.ErrorCode.PROTOCOL_UNSUPPORTED
|
|
327
|
-
}
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Handle ping message
|
|
333
|
-
*/
|
|
334
|
-
handlePing(data, context) {
|
|
335
|
-
if (!context.source) return;
|
|
336
|
-
if (!this.isOriginAllowed(data, context)) return;
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Only allow one server instance to respond.
|
|
340
|
-
* This is important when multiple server instances share the same channel.
|
|
341
|
-
*/
|
|
342
|
-
if (!context.handledBy) {
|
|
343
|
-
// Mark as accepted so MessageDispatcher can auto-send ACK when requireAck === true
|
|
344
|
-
context.accepted = true;
|
|
345
|
-
context.handledBy = this.id;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
// Window check is handled in MessageDispatcher
|
|
349
|
-
this.dispatcher.sendMessage(context.source, context.origin, _constants.MessageType.PONG, data.requestId);
|
|
350
|
-
}
|
|
351
|
-
handlePong(data, context) {
|
|
352
|
-
if (!this.isOriginAllowed(data, context)) return;
|
|
353
|
-
var pending = this.pendingPongs.get(data.requestId);
|
|
354
|
-
if (pending) {
|
|
355
|
-
if (!context.handledBy) {
|
|
356
|
-
context.accepted = true;
|
|
357
|
-
context.handledBy = this.id;
|
|
358
|
-
}
|
|
359
|
-
clearTimeout(pending.timeoutId);
|
|
360
|
-
this.pendingPongs.delete(data.requestId);
|
|
361
|
-
pending.resolve(true);
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
pingClient(targetWindow, targetOrigin, targetClientId) {
|
|
365
|
-
var requestId = (0, _utils.generateRequestId)();
|
|
366
|
-
return new Promise(resolve => {
|
|
367
|
-
var timeoutId = setTimeout(() => {
|
|
368
|
-
this.pendingPongs.delete(requestId);
|
|
369
|
-
resolve(false);
|
|
370
|
-
}, this.ackTimeout);
|
|
371
|
-
this.pendingPongs.set(requestId, {
|
|
372
|
-
resolve,
|
|
373
|
-
timeoutId
|
|
374
|
-
});
|
|
375
|
-
// Window check is handled in MessageDispatcher
|
|
376
|
-
this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.PING, requestId, {
|
|
377
|
-
requireAck: true,
|
|
378
|
-
targetId: targetClientId
|
|
379
|
-
});
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* Handle received acknowledgment
|
|
385
|
-
*/
|
|
386
|
-
handleReceived(data, context) {
|
|
387
|
-
if (!this.isOriginAllowed(data, context)) return;
|
|
388
|
-
var pending = this.pendingAcks.get(data.requestId);
|
|
389
|
-
if (pending) {
|
|
390
|
-
// Best-effort: prevent other server instances from also resolving
|
|
391
|
-
if (!context.handledBy) {
|
|
392
|
-
context.handledBy = this.id;
|
|
393
|
-
}
|
|
394
|
-
clearTimeout(pending.timeoutId);
|
|
395
|
-
this.pendingAcks.delete(data.requestId);
|
|
396
|
-
pending.resolve(true, data.ackMeta);
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
/** Get secretKey */
|
|
401
|
-
get secretKey() {
|
|
402
|
-
return this.dispatcher.secretKey;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
/** Get the underlying MessageDispatcher */
|
|
406
|
-
get messageDispatcher() {
|
|
407
|
-
return this.dispatcher;
|
|
408
|
-
}
|
|
409
|
-
handleRequestError(res, targetWindow, targetOrigin, data, err) {
|
|
410
|
-
if (!res._sent) {
|
|
411
|
-
res._markSent();
|
|
412
|
-
/**
|
|
413
|
-
* Use INTERNAL_SERVER_ERROR (500) for handler errors unless a different error status code was explicitly set.
|
|
414
|
-
* If statusCode is still the default OK (200), override it to INTERNAL_SERVER_ERROR.
|
|
415
|
-
*/
|
|
416
|
-
var errorStatus = res.statusCode === _constants.HttpStatus.OK ? _constants.HttpStatus.INTERNAL_SERVER_ERROR : res.statusCode;
|
|
417
|
-
|
|
418
|
-
// Window check is handled in MessageDispatcher
|
|
419
|
-
this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ERROR, data.requestId, {
|
|
420
|
-
path: data.path,
|
|
421
|
-
error: {
|
|
422
|
-
message: err && err.message || _constants.Messages.REQUEST_FAILED,
|
|
423
|
-
code: err && err.code || _constants.ErrorCode.REQUEST_ERROR
|
|
424
|
-
},
|
|
425
|
-
status: errorStatus,
|
|
426
|
-
statusText: _constants.HttpStatusText[errorStatus] || _constants.HttpStatusText[_constants.HttpStatus.INTERNAL_SERVER_ERROR],
|
|
427
|
-
headers: res.headers,
|
|
428
|
-
targetId: data.creatorId
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
handleRequestResult(res, targetWindow, targetOrigin, data, result) {
|
|
433
|
-
if (!res._sent && result !== undefined) {
|
|
434
|
-
res.send(result);
|
|
435
|
-
} else if (!res._sent) {
|
|
436
|
-
res._markSent();
|
|
437
|
-
this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ERROR, data.requestId, {
|
|
438
|
-
path: data.path,
|
|
439
|
-
error: {
|
|
440
|
-
message: _constants.Messages.NO_RESPONSE_SENT,
|
|
441
|
-
code: _constants.ErrorCode.NO_RESPONSE
|
|
442
|
-
},
|
|
443
|
-
status: _constants.HttpStatus.INTERNAL_SERVER_ERROR,
|
|
444
|
-
statusText: _constants.HttpStatusText[_constants.HttpStatus.INTERNAL_SERVER_ERROR],
|
|
445
|
-
headers: res.headers
|
|
446
|
-
});
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
/**
|
|
451
|
-
* Find matching handler and extract path parameters
|
|
452
|
-
* @param requestPath The actual request path
|
|
453
|
-
* @returns Handler function and extracted parameters, or null if not found
|
|
454
|
-
*/
|
|
455
|
-
findHandler(requestPath) {
|
|
456
|
-
var prefixedRequestPath = this.dispatcher.prefixPath(requestPath);
|
|
457
|
-
|
|
458
|
-
// First try exact match (for backward compatibility and performance)
|
|
459
|
-
var exactHandler = this.handlers.get(prefixedRequestPath);
|
|
460
|
-
if (exactHandler) {
|
|
461
|
-
return {
|
|
462
|
-
handler: exactHandler,
|
|
463
|
-
params: {}
|
|
464
|
-
};
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
// Then try parameter matching (e.g., '/api/users/:id' matches '/api/users/123')
|
|
468
|
-
var _iterator = _createForOfIteratorHelper(this.handlers.entries()),
|
|
469
|
-
_step;
|
|
470
|
-
try {
|
|
471
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
472
|
-
var _step$value = (0, _slicedToArray2.default)(_step.value, 2),
|
|
473
|
-
registeredPath = _step$value[0],
|
|
474
|
-
handler = _step$value[1];
|
|
475
|
-
// Check if registered path contains parameters
|
|
476
|
-
if (registeredPath.includes(':')) {
|
|
477
|
-
var matchResult = (0, _pathMatch.matchPathWithParams)(prefixedRequestPath, registeredPath);
|
|
478
|
-
if (matchResult.match) {
|
|
479
|
-
return {
|
|
480
|
-
handler,
|
|
481
|
-
params: matchResult.params
|
|
482
|
-
};
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
} catch (err) {
|
|
487
|
-
_iterator.e(err);
|
|
488
|
-
} finally {
|
|
489
|
-
_iterator.f();
|
|
490
|
-
}
|
|
491
|
-
return null;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
/**
|
|
495
|
-
* Handle request
|
|
496
|
-
*/
|
|
497
|
-
handleRequest(data, context) {
|
|
498
|
-
// If targetId is specified, only process if it matches this server's id
|
|
499
|
-
if (!data.path || data.targetId && data.targetId !== this.id) return;
|
|
500
|
-
if (!context.source) return;
|
|
501
|
-
if (!this.isOriginAllowed(data, context)) return;
|
|
502
|
-
|
|
503
|
-
// If message has already been handled by another server instance, skip processing
|
|
504
|
-
if (context.handledBy) {
|
|
505
|
-
return;
|
|
506
|
-
}
|
|
507
|
-
var targetWindow = context.source;
|
|
508
|
-
var targetOrigin = context.origin;
|
|
509
|
-
|
|
510
|
-
// Find matching handler and extract path parameters
|
|
511
|
-
var handlerMatch = this.findHandler(data.path);
|
|
512
|
-
if (!handlerMatch) {
|
|
513
|
-
// No handler found in this instance
|
|
514
|
-
// Mark as handled by this instance (using special marker) to prevent other instances from processing
|
|
515
|
-
// This ensures only one instance sends the error response
|
|
516
|
-
context.handledBy = this.id;
|
|
517
|
-
|
|
518
|
-
// Send METHOD_NOT_FOUND error
|
|
519
|
-
// Use request's creatorId as targetId to route back to the correct client
|
|
520
|
-
// Window check is handled in MessageDispatcher
|
|
521
|
-
this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ERROR, data.requestId, {
|
|
522
|
-
path: data.path,
|
|
523
|
-
error: {
|
|
524
|
-
message: _constants.Messages.METHOD_NOT_FOUND,
|
|
525
|
-
code: _constants.ErrorCode.METHOD_NOT_FOUND
|
|
526
|
-
},
|
|
527
|
-
status: _constants.HttpStatus.NOT_FOUND,
|
|
528
|
-
statusText: _constants.HttpStatusText[_constants.HttpStatus.NOT_FOUND],
|
|
529
|
-
targetId: data.creatorId
|
|
530
|
-
});
|
|
531
|
-
return;
|
|
532
|
-
}
|
|
533
|
-
var handlerFn = handlerMatch.handler,
|
|
534
|
-
params = handlerMatch.params;
|
|
535
|
-
var clientKey = this.getClientKey(targetOrigin, data.creatorId);
|
|
536
|
-
if (Number.isFinite(this.maxConcurrentRequestsPerClient)) {
|
|
537
|
-
var inFlight = this.inFlightByClientKey.get(clientKey) || 0;
|
|
538
|
-
if (inFlight >= this.maxConcurrentRequestsPerClient) {
|
|
539
|
-
// Prevent other server instances from also responding
|
|
540
|
-
context.handledBy = this.id;
|
|
541
|
-
this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ERROR, data.requestId, {
|
|
542
|
-
path: data.path,
|
|
543
|
-
error: {
|
|
544
|
-
message: (0, _constants.formatMessage)(_constants.Messages.TOO_MANY_REQUESTS, this.maxConcurrentRequestsPerClient),
|
|
545
|
-
code: _constants.ErrorCode.TOO_MANY_REQUESTS
|
|
546
|
-
},
|
|
547
|
-
status: _constants.HttpStatus.TOO_MANY_REQUESTS,
|
|
548
|
-
statusText: _constants.HttpStatusText[_constants.HttpStatus.TOO_MANY_REQUESTS],
|
|
549
|
-
requireAck: data.requireAck,
|
|
550
|
-
ackMeta: data.ackMeta,
|
|
551
|
-
targetId: data.creatorId
|
|
552
|
-
});
|
|
553
|
-
return;
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
this.incInFlight(clientKey);
|
|
557
|
-
|
|
558
|
-
// Mark as accepted so MessageDispatcher can auto-send ACK (delivery confirmation)
|
|
559
|
-
context.accepted = true;
|
|
560
|
-
|
|
561
|
-
// Mark message as handled by this server instance to prevent other server instances from processing it
|
|
562
|
-
context.handledBy = this.id;
|
|
563
|
-
|
|
564
|
-
// Create response object with channel reference
|
|
565
|
-
// Pass request's creatorId as targetId so responses are routed back to the correct client
|
|
566
|
-
var res = new _response.ServerResponseImpl(data.requestId, data.path || '', data.secretKey, targetWindow, targetOrigin, this.dispatcher.getChannel(), this.id, data.creatorId, {
|
|
567
|
-
registerStreamHandler: (streamId, handler) => {
|
|
568
|
-
this.streamHandlers.set(streamId, handler);
|
|
569
|
-
},
|
|
570
|
-
unregisterStreamHandler: streamId => {
|
|
571
|
-
this.streamHandlers.delete(streamId);
|
|
572
|
-
},
|
|
573
|
-
heartbeat: () => this.pingClient(targetWindow, targetOrigin, data.creatorId),
|
|
574
|
-
onSent: () => this.decInFlight(clientKey)
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
// Register callback waiting for client acknowledgment
|
|
578
|
-
this.registerPendingAck(data.requestId, (received, ackMeta) => {
|
|
579
|
-
res._triggerAck(received, ackMeta);
|
|
580
|
-
}, () => {
|
|
581
|
-
res._triggerAck(false);
|
|
582
|
-
});
|
|
583
|
-
|
|
584
|
-
// Client sends body as stream: wait for stream_start, then create readable stream and call handler
|
|
585
|
-
// If streamId is present, this is a stream request
|
|
586
|
-
var streamId = data.streamId;
|
|
587
|
-
if (streamId) {
|
|
588
|
-
var streamStartTimeout = this.ackTimeout;
|
|
589
|
-
var timeoutId = setTimeout(() => {
|
|
590
|
-
var pending = this.pendingStreamRequests.get(data.requestId);
|
|
591
|
-
if (!pending) return;
|
|
592
|
-
this.pendingStreamRequests.delete(data.requestId);
|
|
593
|
-
if (!pending.res._sent) {
|
|
594
|
-
pending.res._markSent();
|
|
595
|
-
this.dispatcher.sendMessage(pending.targetWindow, pending.targetOrigin, _constants.MessageType.ERROR, pending.requestId, {
|
|
596
|
-
path: pending.path,
|
|
597
|
-
error: {
|
|
598
|
-
message: (0, _constants.formatMessage)(_constants.Messages.STREAM_START_TIMEOUT, streamStartTimeout),
|
|
599
|
-
code: _constants.ErrorCode.STREAM_START_TIMEOUT
|
|
600
|
-
},
|
|
601
|
-
status: _constants.HttpStatus.REQUEST_TIMEOUT,
|
|
602
|
-
statusText: _constants.HttpStatusText[_constants.HttpStatus.REQUEST_TIMEOUT],
|
|
603
|
-
requireAck: pending.data.requireAck,
|
|
604
|
-
ackMeta: pending.data.ackMeta,
|
|
605
|
-
targetId: pending.data.creatorId
|
|
606
|
-
});
|
|
607
|
-
}
|
|
608
|
-
}, streamStartTimeout);
|
|
609
|
-
this.pendingStreamRequests.set(data.requestId, {
|
|
610
|
-
path: data.path || '',
|
|
611
|
-
requestId: data.requestId,
|
|
612
|
-
streamId,
|
|
613
|
-
timeoutId,
|
|
614
|
-
handlerFn,
|
|
615
|
-
targetWindow,
|
|
616
|
-
targetOrigin,
|
|
617
|
-
res,
|
|
618
|
-
data,
|
|
619
|
-
context,
|
|
620
|
-
params
|
|
621
|
-
});
|
|
622
|
-
return;
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
// Create request object with path parameters
|
|
626
|
-
var req = new _request.ServerRequestImpl(data, context, res, params);
|
|
627
|
-
|
|
628
|
-
// Execute middleware chain
|
|
629
|
-
this.runMiddlewares(req, res, () => {
|
|
630
|
-
try {
|
|
631
|
-
var result = handlerFn(req, res);
|
|
632
|
-
if ((0, _utils.isPromise)(result)) {
|
|
633
|
-
// Async task
|
|
634
|
-
// Window check is handled in MessageDispatcher
|
|
635
|
-
// Use request's creatorId as targetId to route back to the correct client
|
|
636
|
-
this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ASYNC, data.requestId, {
|
|
637
|
-
path: data.path,
|
|
638
|
-
targetId: data.creatorId
|
|
639
|
-
});
|
|
640
|
-
result.then(this.handleRequestResult.bind(this, res, targetWindow, targetOrigin, data)).catch(this.handleRequestError.bind(this, res, targetWindow, targetOrigin, data));
|
|
641
|
-
} else {
|
|
642
|
-
// Synchronous processing
|
|
643
|
-
this.handleRequestResult(res, targetWindow, targetOrigin, data, result);
|
|
644
|
-
}
|
|
645
|
-
} catch (error) {
|
|
646
|
-
this.handleRequestError(res, targetWindow, targetOrigin, data, error);
|
|
647
|
-
}
|
|
648
|
-
});
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
/**
|
|
652
|
-
* Register pending acknowledgment response
|
|
653
|
-
*/
|
|
654
|
-
registerPendingAck(requestId, resolve, reject) {
|
|
655
|
-
var timeoutId = setTimeout(() => {
|
|
656
|
-
this.pendingAcks.delete(requestId);
|
|
657
|
-
resolve(false);
|
|
658
|
-
}, this.ackTimeout);
|
|
659
|
-
this.pendingAcks.set(requestId, {
|
|
660
|
-
resolve,
|
|
661
|
-
reject,
|
|
662
|
-
timeoutId
|
|
663
|
-
});
|
|
664
|
-
}
|
|
665
|
-
use(pathOrMiddleware, middleware) {
|
|
666
|
-
if (typeof pathOrMiddleware === 'function') {
|
|
667
|
-
this.middlewares.push({
|
|
668
|
-
matcher: null,
|
|
669
|
-
middleware: pathOrMiddleware
|
|
670
|
-
});
|
|
671
|
-
} else if (middleware) {
|
|
672
|
-
this.middlewares.push({
|
|
673
|
-
matcher: pathOrMiddleware,
|
|
674
|
-
middleware
|
|
675
|
-
});
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
on(path, handler) {
|
|
679
|
-
var prefixedPath = this.dispatcher.prefixPath(path);
|
|
680
|
-
this.handlers.set(prefixedPath, handler);
|
|
681
|
-
|
|
682
|
-
// Return unregister function
|
|
683
|
-
return () => {
|
|
684
|
-
this.handlers.delete(prefixedPath);
|
|
685
|
-
};
|
|
686
|
-
}
|
|
687
|
-
runMiddlewares(req, res, finalHandler) {
|
|
688
|
-
var path = req.path;
|
|
689
|
-
var index = 0;
|
|
690
|
-
var next = () => {
|
|
691
|
-
if (res._sent) {
|
|
692
|
-
return;
|
|
693
|
-
}
|
|
694
|
-
while (index < this.middlewares.length) {
|
|
695
|
-
var item = this.middlewares[index++];
|
|
696
|
-
if (item.matcher === null || (0, _pathMatch.matchPath)(path, item.matcher)) {
|
|
697
|
-
try {
|
|
698
|
-
var result = item.middleware(req, res, next);
|
|
699
|
-
if (result instanceof Promise) {
|
|
700
|
-
result.catch(err => {
|
|
701
|
-
if (!res._sent) {
|
|
702
|
-
res.status(_constants.HttpStatus.INTERNAL_SERVER_ERROR).send({
|
|
703
|
-
error: err.message || _constants.Messages.MIDDLEWARE_ERROR
|
|
704
|
-
});
|
|
705
|
-
}
|
|
706
|
-
});
|
|
707
|
-
}
|
|
708
|
-
return;
|
|
709
|
-
} catch (err) {
|
|
710
|
-
if (!res._sent) {
|
|
711
|
-
res.status(_constants.HttpStatus.INTERNAL_SERVER_ERROR).send({
|
|
712
|
-
error: (err === null || err === void 0 ? void 0 : err.message) || _constants.Messages.MIDDLEWARE_ERROR
|
|
713
|
-
});
|
|
714
|
-
}
|
|
715
|
-
return;
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
if (index >= this.middlewares.length) {
|
|
720
|
-
finalHandler();
|
|
721
|
-
}
|
|
722
|
-
};
|
|
723
|
-
next();
|
|
724
|
-
}
|
|
725
|
-
off(path) {
|
|
726
|
-
if (Array.isArray(path)) {
|
|
727
|
-
// Batch unregister
|
|
728
|
-
path.forEach(p => {
|
|
729
|
-
this.handlers.delete(this.dispatcher.prefixPath(p));
|
|
730
|
-
});
|
|
731
|
-
} else {
|
|
732
|
-
// Single unregister
|
|
733
|
-
this.handlers.delete(this.dispatcher.prefixPath(path));
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
map(handlers) {
|
|
737
|
-
var unregisterFns = [];
|
|
738
|
-
Object.entries(handlers).forEach(([path, h]) => {
|
|
739
|
-
unregisterFns.push(this.on(path, h));
|
|
740
|
-
});
|
|
741
|
-
return () => {
|
|
742
|
-
unregisterFns.forEach(fn => fn());
|
|
743
|
-
};
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
/**
|
|
747
|
-
* Destroy (close and release channel reference)
|
|
748
|
-
*/
|
|
749
|
-
destroy() {
|
|
750
|
-
// Close first
|
|
751
|
-
this.close();
|
|
752
|
-
|
|
753
|
-
// Clean up pending
|
|
754
|
-
this.pendingAcks.forEach(pending => clearTimeout(pending.timeoutId));
|
|
755
|
-
this.pendingAcks.clear();
|
|
756
|
-
this.pendingPongs.forEach(pending => clearTimeout(pending.timeoutId));
|
|
757
|
-
this.pendingPongs.clear();
|
|
758
|
-
this.pendingStreamRequests.forEach(pending => clearTimeout(pending.timeoutId));
|
|
759
|
-
this.pendingStreamRequests.clear();
|
|
760
|
-
this.inFlightByClientKey.clear();
|
|
761
|
-
|
|
762
|
-
// Clean up handlers
|
|
763
|
-
this.handlers.clear();
|
|
764
|
-
this.middlewares.length = 0;
|
|
765
|
-
this.streamHandlers.clear();
|
|
766
|
-
|
|
767
|
-
// Destroy dispatcher and release channel reference
|
|
768
|
-
this.dispatcher.destroy();
|
|
769
|
-
(0, _cache.releaseMessageChannel)(this.dispatcher.getChannel());
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
exports.RequestIframeServerImpl = RequestIframeServerImpl;
|